summaryrefslogtreecommitdiffstats
path: root/asset
diff options
context:
space:
mode:
Diffstat (limited to 'asset')
-rw-r--r--asset/css/awesome-icons.less35
-rw-r--r--asset/css/balls.less147
-rw-r--r--asset/css/cancel-button.less34
-rw-r--r--asset/css/compat.less88
-rw-r--r--asset/css/controls.less164
-rw-r--r--asset/css/copy-to-clipboard.less41
-rw-r--r--asset/css/datetime-picker.less9
-rw-r--r--asset/css/empty-state.less11
-rw-r--r--asset/css/file-element.less40
-rw-r--r--asset/css/fontawesome.css6372
-rw-r--r--asset/css/horizontal-key-value.less17
-rw-r--r--asset/css/icinga-icons.less64
-rw-r--r--asset/css/icons-base.less12
-rw-r--r--asset/css/list/item-list.less85
-rw-r--r--asset/css/list/item-table.less95
-rw-r--r--asset/css/list/list-item.less85
-rw-r--r--asset/css/mixin/card.less23
-rw-r--r--asset/css/mixin/mixins.less37
-rw-r--r--asset/css/mixin/state-badges.less31
-rw-r--r--asset/css/primary-submit-btn-duplicate.less16
-rw-r--r--asset/css/schedule-element.less210
-rw-r--r--asset/css/search-bar.less232
-rw-r--r--asset/css/search-base.less269
-rw-r--r--asset/css/search-editor.less268
-rw-r--r--asset/css/state-badge.less52
-rw-r--r--asset/css/variables.less216
-rw-r--r--asset/css/vendor/flatpickr.css791
-rw-r--r--asset/css/vendor/flatpickr.vars.less327
-rw-r--r--asset/css/vertical-key-value.less17
-rw-r--r--asset/js/notjQuery.js161
-rw-r--r--asset/js/vendor/Sortable.js3721
-rw-r--r--asset/js/vendor/Sortable.min.js2
-rw-r--r--asset/js/vendor/flatpickr.js2705
-rw-r--r--asset/js/vendor/flatpickr.min.js2
-rw-r--r--asset/js/vendor/flatpickr/l10n/ar.js62
-rw-r--r--asset/js/vendor/flatpickr/l10n/de.js70
-rw-r--r--asset/js/vendor/flatpickr/l10n/es.js70
-rw-r--r--asset/js/vendor/flatpickr/l10n/fi.js69
-rw-r--r--asset/js/vendor/flatpickr/l10n/fr.js75
-rw-r--r--asset/js/vendor/flatpickr/l10n/it.js71
-rw-r--r--asset/js/vendor/flatpickr/l10n/ja.js71
-rw-r--r--asset/js/vendor/flatpickr/l10n/pt.js66
-rw-r--r--asset/js/vendor/flatpickr/l10n/ru.js75
-rw-r--r--asset/js/vendor/flatpickr/l10n/uk.js66
-rw-r--r--asset/js/widget/BaseInput.js1049
-rw-r--r--asset/js/widget/Completer.js750
-rw-r--r--asset/js/widget/CopyToClipboard.js49
-rw-r--r--asset/js/widget/FilterInput.js1521
-rw-r--r--asset/js/widget/SearchBar.js81
-rw-r--r--asset/js/widget/SearchEditor.js79
-rw-r--r--asset/js/widget/TermInput.js196
-rw-r--r--asset/static/font/awesome/fa-brands-400.ttfbin0 -> 189684 bytes
-rw-r--r--asset/static/font/awesome/fa-brands-400.woff2bin0 -> 109816 bytes
-rw-r--r--asset/static/font/awesome/fa-regular-400.ttfbin0 -> 63348 bytes
-rw-r--r--asset/static/font/awesome/fa-regular-400.woff2bin0 -> 24468 bytes
-rw-r--r--asset/static/font/awesome/fa-solid-900.ttfbin0 -> 394668 bytes
-rw-r--r--asset/static/font/awesome/fa-solid-900.woff2bin0 -> 150024 bytes
-rw-r--r--asset/static/font/awesome/fa-v4compatibility.ttfbin0 -> 10172 bytes
-rw-r--r--asset/static/font/awesome/fa-v4compatibility.woff2bin0 -> 4568 bytes
-rw-r--r--asset/static/font/icinga-icons/fonts/Icinga-Icons.svg22
-rw-r--r--asset/static/font/icinga-icons/fonts/Icinga-Icons.ttfbin0 -> 4316 bytes
-rw-r--r--asset/static/font/icinga-icons/fonts/Icinga-Icons.woffbin0 -> 4392 bytes
-rw-r--r--asset/static/font/icinga-icons/selection.json1
-rw-r--r--asset/static/font/icinga-icons/src/bracket-close.svg14
-rw-r--r--asset/static/font/icinga-icons/src/bracket-open.svg14
-rw-r--r--asset/static/font/icinga-icons/src/ca-check-circle.svg20
-rw-r--r--asset/static/font/icinga-icons/src/certificate.svg26
-rw-r--r--asset/static/font/icinga-icons/src/filter-check-circle.svg17
-rw-r--r--asset/static/font/icinga-icons/src/icinga.svg49
-rw-r--r--asset/static/font/icinga-icons/src/list-view-default.svg37
-rw-r--r--asset/static/font/icinga-icons/src/list-view-detailed.svg34
-rw-r--r--asset/static/font/icinga-icons/src/list-view-minimal.svg46
-rw-r--r--asset/static/font/icinga-icons/src/refresh-cert.svg23
-rw-r--r--asset/static/font/icinga-icons/src/th-list.svg22
-rw-r--r--asset/static/font/icinga-icons/src/th-thumb-empty.svg21
-rw-r--r--asset/static/font/icinga-icons/style.css62
-rw-r--r--asset/static/img/select-icon-text-color.svg1
-rw-r--r--asset/static/img/select-icon.svg1
78 files changed, 21209 insertions, 0 deletions
diff --git a/asset/css/awesome-icons.less b/asset/css/awesome-icons.less
new file mode 100644
index 0000000..ba0b5cf
--- /dev/null
+++ b/asset/css/awesome-icons.less
@@ -0,0 +1,35 @@
+:root, :host {
+ --fa-font-regular: normal 400 1em/1 "Font Awesome 6 Free";
+ --fa-font-solid: normal 900 1em/1 "Font Awesome 6 Free";
+}
+
+@font-face {
+ font-family: 'Font Awesome 6 Free';
+ font-style: normal;
+ font-weight: 400;
+ font-display: block;
+ src: url('@{iplWebAssets}/font/awesome/fa-regular-400.woff2') format('woff2'),
+ url('@{iplWebAssets}/font/awesome/fa-regular-400.ttf') format('truetype');
+}
+
+.far,
+.fa-regular {
+ font-family: 'Font Awesome 6 Free';
+ font-weight: 400;
+}
+
+@font-face {
+ font-family: 'Font Awesome 6 Free';
+ font-style: normal;
+ font-weight: 900;
+ font-display: block;
+ src: url('@{iplWebAssets}/font/awesome/fa-solid-900.woff2') format('woff2'),
+ url('@{iplWebAssets}/font/awesome/fa-solid-900.ttf') format('truetype');
+}
+
+.fa,
+.fas,
+.fa-solid {
+ font-family: 'Font Awesome 6 Free';
+ font-weight: 900;
+}
diff --git a/asset/css/balls.less b/asset/css/balls.less
new file mode 100644
index 0000000..f3afae3
--- /dev/null
+++ b/asset/css/balls.less
@@ -0,0 +1,147 @@
+@ball-pad: 1/6em;
+
+.ball {
+ border-radius: 50%;
+ display: inline-block;
+ text-align: center;
+}
+
+.ball-size-xs {
+ height: 1/3em;
+ width: 1/3em;
+}
+
+.ball-size-s {
+ height: 0.5em;
+ width: 0.5em;
+}
+
+.ball-size-m {
+ height: 0.75em;
+ width: 0.75em;
+ line-height: 0;
+
+ i.icon:before {
+ font-size: .75 - @ball-pad * 2;
+ line-height: 1em;
+ }
+}
+
+.ball-size-ml {
+ height: 1em;
+ width: 1em;
+ line-height: 0;
+
+ i.icon {
+ line-height: 0.3;
+
+ &:before {
+ font-size: 0.8 - @ball-pad * 2;
+ line-height: 1 - @ball-pad * 2;
+ }
+ }
+}
+
+.ball-size-l {
+ height: 1.5em;
+ width: 1.5em;
+ line-height: 1em;
+
+ i.icon:before {
+ font-size: 1 - @ball-pad * 2;
+ line-height: 1.5 - @ball-pad * 2;
+ }
+}
+
+.ball-size-xl {
+ width: 2em;
+ height: 2em;
+
+ i.icon:before {
+ line-height: 2 - @ball-pad * 2;
+ }
+}
+
+.ball-outline(@color) {
+ border: @ball-pad solid @color;
+}
+
+.ball-solid(@color) {
+ background-color: @color;
+ color: var(--default-text-color-inverted, @default-text-color-inverted);
+ padding: @ball-pad;
+}
+
+.state-ball {
+ .ball();
+
+ &.state-pending:not(.ball-size-l):not(.ball-size-xl) {
+ .ball-solid(var(--state-pending, @state-pending));
+ }
+
+ &.state-pending.ball-size-l,
+ &.state-pending.ball-size-xl {
+ .ball-outline(var(--state-pending, @state-pending));
+ }
+
+ &.state-up:not(.ball-size-l):not(.ball-size-xl) {
+ .ball-solid(var(--state-up, @state-up));
+ }
+
+ &.state-up.ball-size-l,
+ &.state-up.ball-size-xl {
+ .ball-outline(var(--state-up, @state-up));
+ }
+
+ &.state-down {
+ .ball-solid(var(--state-down, @state-down));
+ }
+
+ &.state-ok:not(.ball-size-l):not(.ball-size-xl) {
+ .ball-solid(var(--state-ok, @state-ok));
+ }
+
+ &.state-ok.ball-size-l,
+ &.state-ok.ball-size-xl {
+ .ball-outline(var(--state-ok, @state-ok));
+ }
+
+ &.state-warning {
+ .ball-solid(var(--state-warning, @state-warning));
+ }
+
+ &.state-critical {
+ .ball-solid(var(--state-critical, @state-critical));
+ }
+
+ &.state-unknown {
+ .ball-solid(var(--state-unknown, @state-unknown));
+ }
+
+ &.handled {
+ opacity: 0.6;
+ }
+
+ i.icon {
+ text-align: center;
+ display: block;
+
+ &::before {
+ margin-right: 0;
+ }
+ }
+
+ // Specific icon styles
+ &.ball-size-l i {
+ &.fa-sitemap:before {
+ font-size: 8px; // px to ignore browser min font-size
+ }
+ }
+
+ &.ball-size-xl i {
+ &.fa-sitemap:before {
+ font-size: .857em;
+ line-height: (2 - @ball-pad * 2) / .857;
+ }
+ }
+}
diff --git a/asset/css/cancel-button.less b/asset/css/cancel-button.less
new file mode 100644
index 0000000..7640399
--- /dev/null
+++ b/asset/css/cancel-button.less
@@ -0,0 +1,34 @@
+.cancel-button {
+ display: inline-flex;
+ align-items: baseline;
+ padding: .5em 1em;
+
+ .appearance(none);
+ .rounded-corners();
+ line-height: normal;
+ cursor: pointer;
+
+ background: var(--cancel-button-bg, @cancel-button-bg);
+ border: 1px solid var(--cancel-button-border-color, @cancel-button-border-color);
+ color: var(--cancel-button-color, @cancel-button-color);
+
+ &:focus,
+ &:hover {
+ background-color: var(--cancel-button-hover-bg, @cancel-button-hover-bg);
+ color: var(--cancel-button-hover-color, @cancel-button-hover-color);
+ }
+
+ &[disabled] {
+ background: none;
+ cursor: default;
+
+ border: 1px solid var(--control-disabled-color, @control-disabled-color);
+ color: var(--control-disabled-color, @control-disabled-color);
+
+ &:focus,
+ &:hover {
+ background: none;
+ color: var(--control-disabled-color, @control-disabled-color);
+ }
+ }
+}
diff --git a/asset/css/compat.less b/asset/css/compat.less
new file mode 100644
index 0000000..1188c7e
--- /dev/null
+++ b/asset/css/compat.less
@@ -0,0 +1,88 @@
+// General input styles
+
+.icinga-controls {
+ .uploaded-files {
+ background-color: @default-input-bg;
+ }
+}
+
+form.icinga-form {
+ .uploaded-files {
+ flex: 1 1 auto;
+ width: 0;
+ }
+}
+
+.icinga-controls {
+ .uploaded-files {
+ font-size: inherit;
+ padding: .5em;
+ }
+}
+
+// Button styles
+
+// The `form` selector is only required to overrule the hover effect applied by Icinga Web.
+// It's not required if done by Icinga Web itself, only here because this is applied earlier
+// as it's part of a library.
+form.icinga-controls {
+ button[type="submit"].remove-uploaded-file {
+ all: unset;
+ }
+}
+
+// Schedule Element styles
+
+.icinga-form > .schedule-element,
+.icinga-form > .schedule-element > fieldset {
+ margin-top: 1em;
+
+ > .control-group:first-child {
+ margin-top: 0;
+ }
+}
+
+.icinga-form .schedule-element {
+ .control-group > fieldset > .weekly,
+ .control-group > .ordinal,
+ .control-group > .monthly,
+ .control-group > .annually {
+ flex: 1 1 auto;
+ }
+
+ // TODO: This effectively restricts the weekly fields to always be aligned to the right,
+ // regardless of the using an icinga-form or not. So this should be removed once we
+ // have re-implemented the decorators.
+ .control-group > fieldset > .weekly {
+ margin-left: 14em;
+ }
+}
+
+form.icinga-form .control-group {
+ > .monthly,
+ > .ordinal {
+ margin-right: 2em;
+ }
+
+ > .ordinal.annually {
+ margin-right: 1em;
+ }
+}
+
+// TermInput styles
+
+form.icinga-form .control-group {
+ > .term-input-area {
+ flex: 1 1 auto;
+
+ width: auto;
+ &.vertical {
+ width: 0;
+ }
+
+ input[type="text"] {
+ flex: unset;
+ width: 100%;
+ }
+ }
+}
diff --git a/asset/css/controls.less b/asset/css/controls.less
new file mode 100644
index 0000000..1bccbd8
--- /dev/null
+++ b/asset/css/controls.less
@@ -0,0 +1,164 @@
+.pagination-control {
+ li > a {
+ color: var(--control-color, @control-color);
+ border-radius: .25em;
+ }
+
+ li > a:hover {
+ background: var(--control-hover-bg, @control-hover-bg);
+ }
+
+ .previous-page,
+ .next-page {
+ padding: .5em .25em;
+
+ i {
+ display: block;
+ }
+
+ i:before {
+ margin: 0;
+ }
+ }
+
+ .previous-page > i {
+ margin-left: -.125em;
+ }
+
+ .next-page > i {
+ margin-right: -.125em;
+ }
+}
+
+// Style
+
+.control-button {
+ .appearance(none);
+ background: none;
+ border: none;
+ color: var(--control-color, @control-color);
+ .rounded-corners();
+
+ &:hover, &:focus, &.active {
+ background-color: var(--control-hover-bg, @control-hover-bg);
+ text-decoration: none;
+ }
+
+ &.disabled {
+ color: var(--control-disabled-color, @control-disabled-color);
+
+ &:hover {
+ background: none;
+ }
+ }
+
+ i.icon:before {
+ color: inherit;
+ }
+}
+
+// Layout
+
+.control-button {
+ display: inline-block;
+ padding: .25em .5em;
+
+ > i.icon {
+ display: inline-flex;
+ align-items: center;
+ height: 100%;
+ }
+
+ i.icon:before {
+ margin-right: 0;
+ }
+}
+
+.sort-control {
+ display: flex;
+ justify-content: flex-end;
+
+ .form-element {
+ display: inline-flex;
+ align-items: baseline;
+ margin-right: .5em;
+
+ label {
+ margin-right: .5em;
+ }
+ }
+
+ .control-button {
+ margin: 0;
+ }
+}
+
+.search-controls {
+ display: flex;
+ min-width: 100%;
+
+ .search-bar {
+ flex: 1 1 auto;
+
+ & ~ .control-button {
+ margin-left: .5em;
+ }
+ }
+}
+
+/**
+ The default layout of list controls in Icinga Web
+
+ ┌────────────────────────────────────────────────────────────────┐
+ │ .pagination-control .limit-control .sort-control │
+ │ <-------------------- .search-controls ----------------------> │
+ └────────────────────────────────────────────────────────────────┘
+ */
+.controls.default-layout {
+ .box-shadow(0, 0, 0, 1px, @controls-separator-bg);
+
+ z-index: 1; // The content may clip, this ensures the separator is always visible
+ & + .content {
+ z-index: 0;
+ }
+
+ > .pagination-control {
+ float: left;
+ }
+
+ > .sort-control,
+ > .limit-control {
+ float: right;
+ }
+
+ > .limit-control {
+ margin-right: .5em;
+ }
+
+ > .search-controls {
+ clear: both;
+ }
+
+ > :not(:only-child) {
+ margin-bottom: 0.5em;
+ }
+
+ > .sort-control,
+ > .search-controls > .control-button:last-child {
+ margin-right: -.5em;
+ }
+
+ > .search-controls > .search-bar .search-suggestions {
+ // Suggestions should be kept at a distance from the bottom of the page
+ margin-bottom: 2.5em;
+ }
+
+ > .search-controls > .search-bar .filter-input-area {
+ label {
+ &::after,
+ input {
+ padding: 0 .5em;
+ }
+ }
+ }
+}
diff --git a/asset/css/copy-to-clipboard.less b/asset/css/copy-to-clipboard.less
new file mode 100644
index 0000000..515b148
--- /dev/null
+++ b/asset/css/copy-to-clipboard.less
@@ -0,0 +1,41 @@
+.clipboard-wrapper {
+ position: relative;
+ > .copy-to-clipboard {
+ margin: 0.1em 0.1em 0 0;
+ position: absolute;
+ right: 0;
+ top: 0;
+ }
+
+ &:hover {
+ .copy-to-clipboard.active {
+ opacity: 0.8;
+ }
+ }
+}
+
+.copy-to-clipboard {
+ .appearance(none);
+ border: none;
+ opacity: 0;
+ background: none;
+ padding: 0.25em 0.5em;
+ cursor: default;
+
+ &.active {
+ cursor: pointer;
+ &:hover, &:focus {
+ opacity: 0.8;
+ color: var(--control-color, @control-color);
+ outline-offset: -2px;
+ }
+ }
+}
+
+.copy-to-clipboard.active,
+.clipboard-wrapper:hover .copy-to-clipboard.active {
+ &.copied {
+ opacity: 0;
+ transition: opacity 1s linear 3s;
+ }
+}
diff --git a/asset/css/datetime-picker.less b/asset/css/datetime-picker.less
new file mode 100644
index 0000000..3d9d9ac
--- /dev/null
+++ b/asset/css/datetime-picker.less
@@ -0,0 +1,9 @@
+.flatpickr-input + .input {
+ padding-right: 2em;
+
+ & + .fa-calendar {
+ margin: .5em 1em 0 -3.5em;
+ padding: 0 .5em 0 1em;
+ pointer-events: none;
+ }
+}
diff --git a/asset/css/empty-state.less b/asset/css/empty-state.less
new file mode 100644
index 0000000..6291055
--- /dev/null
+++ b/asset/css/empty-state.less
@@ -0,0 +1,11 @@
+.empty-state {
+ color: @empty-state-color;
+}
+
+.empty-state-bar {
+ padding: 1em;
+ text-align: center;
+
+ .rounded-corners();
+ background-color: @empty-state-bar-bg;
+}
diff --git a/asset/css/file-element.less b/asset/css/file-element.less
new file mode 100644
index 0000000..9d76d03
--- /dev/null
+++ b/asset/css/file-element.less
@@ -0,0 +1,40 @@
+form .uploaded-files {
+ list-style-type: none;
+ padding: 0;
+ margin: 0;
+
+ > li:not(:last-of-type) {
+ margin-bottom: .5em;
+ }
+
+ button[type="submit"].remove-uploaded-file {
+ .icon {
+ font-size: 1.2em;
+ }
+
+ &:focus, &:hover {
+ cursor: pointer;
+
+ .icon {
+ color: red;
+ }
+ }
+ }
+
+ // text-overflow: ellipsis layout rules, yes, exclusively
+ > li {
+ display: flex;
+
+ > button[type="submit"].remove-uploaded-file {
+ display: inline-flex;
+ flex: 1 1 auto;
+ width: 0;
+
+ > span {
+ white-space: nowrap;
+ overflow: hidden;
+ text-overflow: ellipsis;
+ }
+ }
+ }
+}
diff --git a/asset/css/fontawesome.css b/asset/css/fontawesome.css
new file mode 100644
index 0000000..b35a770
--- /dev/null
+++ b/asset/css/fontawesome.css
@@ -0,0 +1,6372 @@
+/*!
+ * Font Awesome Free 6.4.2 by @fontawesome - https://fontawesome.com
+ * License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License)
+ * Copyright 2023 Fonticons, Inc.
+ */
+.fa {
+ font-family: var(--fa-style-family, "Font Awesome 6 Free");
+ font-weight: var(--fa-style, 900); }
+
+.fa,
+.fa-classic,
+.fa-sharp,
+.fas,
+.fa-solid,
+.far,
+.fa-regular,
+.fab,
+.fa-brands {
+ -moz-osx-font-smoothing: grayscale;
+ -webkit-font-smoothing: antialiased;
+ display: var(--fa-display, inline-block);
+ font-style: normal;
+ font-variant: normal;
+ line-height: 1;
+ text-rendering: auto; }
+
+.fas,
+.fa-classic,
+.fa-solid,
+.far,
+.fa-regular {
+ font-family: 'Font Awesome 6 Free'; }
+
+.fab,
+.fa-brands {
+ font-family: 'Font Awesome 6 Brands'; }
+
+.fa-1x {
+ font-size: 1em; }
+
+.fa-2x {
+ font-size: 2em; }
+
+.fa-3x {
+ font-size: 3em; }
+
+.fa-4x {
+ font-size: 4em; }
+
+.fa-5x {
+ font-size: 5em; }
+
+.fa-6x {
+ font-size: 6em; }
+
+.fa-7x {
+ font-size: 7em; }
+
+.fa-8x {
+ font-size: 8em; }
+
+.fa-9x {
+ font-size: 9em; }
+
+.fa-10x {
+ font-size: 10em; }
+
+.fa-2xs {
+ font-size: 0.625em;
+ line-height: 0.1em;
+ vertical-align: 0.225em; }
+
+.fa-xs {
+ font-size: 0.75em;
+ line-height: 0.08333em;
+ vertical-align: 0.125em; }
+
+.fa-sm {
+ font-size: 0.875em;
+ line-height: 0.07143em;
+ vertical-align: 0.05357em; }
+
+.fa-lg {
+ font-size: 1.25em;
+ line-height: 0.05em;
+ vertical-align: -0.075em; }
+
+.fa-xl {
+ font-size: 1.5em;
+ line-height: 0.04167em;
+ vertical-align: -0.125em; }
+
+.fa-2xl {
+ font-size: 2em;
+ line-height: 0.03125em;
+ vertical-align: -0.1875em; }
+
+.fa-fw {
+ text-align: center;
+ width: 1.25em; }
+
+.fa-ul {
+ list-style-type: none;
+ margin-left: var(--fa-li-margin, 2.5em);
+ padding-left: 0; }
+ .fa-ul > li {
+ position: relative; }
+
+.fa-li {
+ left: calc(var(--fa-li-width, 2em) * -1);
+ position: absolute;
+ text-align: center;
+ width: var(--fa-li-width, 2em);
+ line-height: inherit; }
+
+.fa-border {
+ border-color: var(--fa-border-color, #eee);
+ border-radius: var(--fa-border-radius, 0.1em);
+ border-style: var(--fa-border-style, solid);
+ border-width: var(--fa-border-width, 0.08em);
+ padding: var(--fa-border-padding, 0.2em 0.25em 0.15em); }
+
+.fa-pull-left {
+ float: left;
+ margin-right: var(--fa-pull-margin, 0.3em); }
+
+.fa-pull-right {
+ float: right;
+ margin-left: var(--fa-pull-margin, 0.3em); }
+
+.fa-beat {
+ -webkit-animation-name: fa-beat;
+ animation-name: fa-beat;
+ -webkit-animation-delay: var(--fa-animation-delay, 0s);
+ animation-delay: var(--fa-animation-delay, 0s);
+ -webkit-animation-direction: var(--fa-animation-direction, normal);
+ animation-direction: var(--fa-animation-direction, normal);
+ -webkit-animation-duration: var(--fa-animation-duration, 1s);
+ animation-duration: var(--fa-animation-duration, 1s);
+ -webkit-animation-iteration-count: var(--fa-animation-iteration-count, infinite);
+ animation-iteration-count: var(--fa-animation-iteration-count, infinite);
+ -webkit-animation-timing-function: var(--fa-animation-timing, ease-in-out);
+ animation-timing-function: var(--fa-animation-timing, ease-in-out); }
+
+.fa-bounce {
+ -webkit-animation-name: fa-bounce;
+ animation-name: fa-bounce;
+ -webkit-animation-delay: var(--fa-animation-delay, 0s);
+ animation-delay: var(--fa-animation-delay, 0s);
+ -webkit-animation-direction: var(--fa-animation-direction, normal);
+ animation-direction: var(--fa-animation-direction, normal);
+ -webkit-animation-duration: var(--fa-animation-duration, 1s);
+ animation-duration: var(--fa-animation-duration, 1s);
+ -webkit-animation-iteration-count: var(--fa-animation-iteration-count, infinite);
+ animation-iteration-count: var(--fa-animation-iteration-count, infinite);
+ -webkit-animation-timing-function: var(--fa-animation-timing, cubic-bezier(0.28, 0.84, 0.42, 1));
+ animation-timing-function: var(--fa-animation-timing, cubic-bezier(0.28, 0.84, 0.42, 1)); }
+
+.fa-fade {
+ -webkit-animation-name: fa-fade;
+ animation-name: fa-fade;
+ -webkit-animation-delay: var(--fa-animation-delay, 0s);
+ animation-delay: var(--fa-animation-delay, 0s);
+ -webkit-animation-direction: var(--fa-animation-direction, normal);
+ animation-direction: var(--fa-animation-direction, normal);
+ -webkit-animation-duration: var(--fa-animation-duration, 1s);
+ animation-duration: var(--fa-animation-duration, 1s);
+ -webkit-animation-iteration-count: var(--fa-animation-iteration-count, infinite);
+ animation-iteration-count: var(--fa-animation-iteration-count, infinite);
+ -webkit-animation-timing-function: var(--fa-animation-timing, cubic-bezier(0.4, 0, 0.6, 1));
+ animation-timing-function: var(--fa-animation-timing, cubic-bezier(0.4, 0, 0.6, 1)); }
+
+.fa-beat-fade {
+ -webkit-animation-name: fa-beat-fade;
+ animation-name: fa-beat-fade;
+ -webkit-animation-delay: var(--fa-animation-delay, 0s);
+ animation-delay: var(--fa-animation-delay, 0s);
+ -webkit-animation-direction: var(--fa-animation-direction, normal);
+ animation-direction: var(--fa-animation-direction, normal);
+ -webkit-animation-duration: var(--fa-animation-duration, 1s);
+ animation-duration: var(--fa-animation-duration, 1s);
+ -webkit-animation-iteration-count: var(--fa-animation-iteration-count, infinite);
+ animation-iteration-count: var(--fa-animation-iteration-count, infinite);
+ -webkit-animation-timing-function: var(--fa-animation-timing, cubic-bezier(0.4, 0, 0.6, 1));
+ animation-timing-function: var(--fa-animation-timing, cubic-bezier(0.4, 0, 0.6, 1)); }
+
+.fa-flip {
+ -webkit-animation-name: fa-flip;
+ animation-name: fa-flip;
+ -webkit-animation-delay: var(--fa-animation-delay, 0s);
+ animation-delay: var(--fa-animation-delay, 0s);
+ -webkit-animation-direction: var(--fa-animation-direction, normal);
+ animation-direction: var(--fa-animation-direction, normal);
+ -webkit-animation-duration: var(--fa-animation-duration, 1s);
+ animation-duration: var(--fa-animation-duration, 1s);
+ -webkit-animation-iteration-count: var(--fa-animation-iteration-count, infinite);
+ animation-iteration-count: var(--fa-animation-iteration-count, infinite);
+ -webkit-animation-timing-function: var(--fa-animation-timing, ease-in-out);
+ animation-timing-function: var(--fa-animation-timing, ease-in-out); }
+
+.fa-shake {
+ -webkit-animation-name: fa-shake;
+ animation-name: fa-shake;
+ -webkit-animation-delay: var(--fa-animation-delay, 0s);
+ animation-delay: var(--fa-animation-delay, 0s);
+ -webkit-animation-direction: var(--fa-animation-direction, normal);
+ animation-direction: var(--fa-animation-direction, normal);
+ -webkit-animation-duration: var(--fa-animation-duration, 1s);
+ animation-duration: var(--fa-animation-duration, 1s);
+ -webkit-animation-iteration-count: var(--fa-animation-iteration-count, infinite);
+ animation-iteration-count: var(--fa-animation-iteration-count, infinite);
+ -webkit-animation-timing-function: var(--fa-animation-timing, linear);
+ animation-timing-function: var(--fa-animation-timing, linear); }
+
+.fa-spin {
+ -webkit-animation-name: fa-spin;
+ animation-name: fa-spin;
+ -webkit-animation-delay: var(--fa-animation-delay, 0s);
+ animation-delay: var(--fa-animation-delay, 0s);
+ -webkit-animation-direction: var(--fa-animation-direction, normal);
+ animation-direction: var(--fa-animation-direction, normal);
+ -webkit-animation-duration: var(--fa-animation-duration, 2s);
+ animation-duration: var(--fa-animation-duration, 2s);
+ -webkit-animation-iteration-count: var(--fa-animation-iteration-count, infinite);
+ animation-iteration-count: var(--fa-animation-iteration-count, infinite);
+ -webkit-animation-timing-function: var(--fa-animation-timing, linear);
+ animation-timing-function: var(--fa-animation-timing, linear); }
+
+.fa-spin-reverse {
+ --fa-animation-direction: reverse; }
+
+.fa-pulse,
+.fa-spin-pulse {
+ -webkit-animation-name: fa-spin;
+ animation-name: fa-spin;
+ -webkit-animation-direction: var(--fa-animation-direction, normal);
+ animation-direction: var(--fa-animation-direction, normal);
+ -webkit-animation-duration: var(--fa-animation-duration, 1s);
+ animation-duration: var(--fa-animation-duration, 1s);
+ -webkit-animation-iteration-count: var(--fa-animation-iteration-count, infinite);
+ animation-iteration-count: var(--fa-animation-iteration-count, infinite);
+ -webkit-animation-timing-function: var(--fa-animation-timing, steps(8));
+ animation-timing-function: var(--fa-animation-timing, steps(8)); }
+
+@media (prefers-reduced-motion: reduce) {
+ .fa-beat,
+ .fa-bounce,
+ .fa-fade,
+ .fa-beat-fade,
+ .fa-flip,
+ .fa-pulse,
+ .fa-shake,
+ .fa-spin,
+ .fa-spin-pulse {
+ -webkit-animation-delay: -1ms;
+ animation-delay: -1ms;
+ -webkit-animation-duration: 1ms;
+ animation-duration: 1ms;
+ -webkit-animation-iteration-count: 1;
+ animation-iteration-count: 1;
+ -webkit-transition-delay: 0s;
+ transition-delay: 0s;
+ -webkit-transition-duration: 0s;
+ transition-duration: 0s; } }
+
+@-webkit-keyframes fa-beat {
+ 0%, 90% {
+ -webkit-transform: scale(1);
+ transform: scale(1); }
+ 45% {
+ -webkit-transform: scale(var(--fa-beat-scale, 1.25));
+ transform: scale(var(--fa-beat-scale, 1.25)); } }
+
+@keyframes fa-beat {
+ 0%, 90% {
+ -webkit-transform: scale(1);
+ transform: scale(1); }
+ 45% {
+ -webkit-transform: scale(var(--fa-beat-scale, 1.25));
+ transform: scale(var(--fa-beat-scale, 1.25)); } }
+
+@-webkit-keyframes fa-bounce {
+ 0% {
+ -webkit-transform: scale(1, 1) translateY(0);
+ transform: scale(1, 1) translateY(0); }
+ 10% {
+ -webkit-transform: scale(var(--fa-bounce-start-scale-x, 1.1), var(--fa-bounce-start-scale-y, 0.9)) translateY(0);
+ transform: scale(var(--fa-bounce-start-scale-x, 1.1), var(--fa-bounce-start-scale-y, 0.9)) translateY(0); }
+ 30% {
+ -webkit-transform: scale(var(--fa-bounce-jump-scale-x, 0.9), var(--fa-bounce-jump-scale-y, 1.1)) translateY(var(--fa-bounce-height, -0.5em));
+ transform: scale(var(--fa-bounce-jump-scale-x, 0.9), var(--fa-bounce-jump-scale-y, 1.1)) translateY(var(--fa-bounce-height, -0.5em)); }
+ 50% {
+ -webkit-transform: scale(var(--fa-bounce-land-scale-x, 1.05), var(--fa-bounce-land-scale-y, 0.95)) translateY(0);
+ transform: scale(var(--fa-bounce-land-scale-x, 1.05), var(--fa-bounce-land-scale-y, 0.95)) translateY(0); }
+ 57% {
+ -webkit-transform: scale(1, 1) translateY(var(--fa-bounce-rebound, -0.125em));
+ transform: scale(1, 1) translateY(var(--fa-bounce-rebound, -0.125em)); }
+ 64% {
+ -webkit-transform: scale(1, 1) translateY(0);
+ transform: scale(1, 1) translateY(0); }
+ 100% {
+ -webkit-transform: scale(1, 1) translateY(0);
+ transform: scale(1, 1) translateY(0); } }
+
+@keyframes fa-bounce {
+ 0% {
+ -webkit-transform: scale(1, 1) translateY(0);
+ transform: scale(1, 1) translateY(0); }
+ 10% {
+ -webkit-transform: scale(var(--fa-bounce-start-scale-x, 1.1), var(--fa-bounce-start-scale-y, 0.9)) translateY(0);
+ transform: scale(var(--fa-bounce-start-scale-x, 1.1), var(--fa-bounce-start-scale-y, 0.9)) translateY(0); }
+ 30% {
+ -webkit-transform: scale(var(--fa-bounce-jump-scale-x, 0.9), var(--fa-bounce-jump-scale-y, 1.1)) translateY(var(--fa-bounce-height, -0.5em));
+ transform: scale(var(--fa-bounce-jump-scale-x, 0.9), var(--fa-bounce-jump-scale-y, 1.1)) translateY(var(--fa-bounce-height, -0.5em)); }
+ 50% {
+ -webkit-transform: scale(var(--fa-bounce-land-scale-x, 1.05), var(--fa-bounce-land-scale-y, 0.95)) translateY(0);
+ transform: scale(var(--fa-bounce-land-scale-x, 1.05), var(--fa-bounce-land-scale-y, 0.95)) translateY(0); }
+ 57% {
+ -webkit-transform: scale(1, 1) translateY(var(--fa-bounce-rebound, -0.125em));
+ transform: scale(1, 1) translateY(var(--fa-bounce-rebound, -0.125em)); }
+ 64% {
+ -webkit-transform: scale(1, 1) translateY(0);
+ transform: scale(1, 1) translateY(0); }
+ 100% {
+ -webkit-transform: scale(1, 1) translateY(0);
+ transform: scale(1, 1) translateY(0); } }
+
+@-webkit-keyframes fa-fade {
+ 50% {
+ opacity: var(--fa-fade-opacity, 0.4); } }
+
+@keyframes fa-fade {
+ 50% {
+ opacity: var(--fa-fade-opacity, 0.4); } }
+
+@-webkit-keyframes fa-beat-fade {
+ 0%, 100% {
+ opacity: var(--fa-beat-fade-opacity, 0.4);
+ -webkit-transform: scale(1);
+ transform: scale(1); }
+ 50% {
+ opacity: 1;
+ -webkit-transform: scale(var(--fa-beat-fade-scale, 1.125));
+ transform: scale(var(--fa-beat-fade-scale, 1.125)); } }
+
+@keyframes fa-beat-fade {
+ 0%, 100% {
+ opacity: var(--fa-beat-fade-opacity, 0.4);
+ -webkit-transform: scale(1);
+ transform: scale(1); }
+ 50% {
+ opacity: 1;
+ -webkit-transform: scale(var(--fa-beat-fade-scale, 1.125));
+ transform: scale(var(--fa-beat-fade-scale, 1.125)); } }
+
+@-webkit-keyframes fa-flip {
+ 50% {
+ -webkit-transform: rotate3d(var(--fa-flip-x, 0), var(--fa-flip-y, 1), var(--fa-flip-z, 0), var(--fa-flip-angle, -180deg));
+ transform: rotate3d(var(--fa-flip-x, 0), var(--fa-flip-y, 1), var(--fa-flip-z, 0), var(--fa-flip-angle, -180deg)); } }
+
+@keyframes fa-flip {
+ 50% {
+ -webkit-transform: rotate3d(var(--fa-flip-x, 0), var(--fa-flip-y, 1), var(--fa-flip-z, 0), var(--fa-flip-angle, -180deg));
+ transform: rotate3d(var(--fa-flip-x, 0), var(--fa-flip-y, 1), var(--fa-flip-z, 0), var(--fa-flip-angle, -180deg)); } }
+
+@-webkit-keyframes fa-shake {
+ 0% {
+ -webkit-transform: rotate(-15deg);
+ transform: rotate(-15deg); }
+ 4% {
+ -webkit-transform: rotate(15deg);
+ transform: rotate(15deg); }
+ 8%, 24% {
+ -webkit-transform: rotate(-18deg);
+ transform: rotate(-18deg); }
+ 12%, 28% {
+ -webkit-transform: rotate(18deg);
+ transform: rotate(18deg); }
+ 16% {
+ -webkit-transform: rotate(-22deg);
+ transform: rotate(-22deg); }
+ 20% {
+ -webkit-transform: rotate(22deg);
+ transform: rotate(22deg); }
+ 32% {
+ -webkit-transform: rotate(-12deg);
+ transform: rotate(-12deg); }
+ 36% {
+ -webkit-transform: rotate(12deg);
+ transform: rotate(12deg); }
+ 40%, 100% {
+ -webkit-transform: rotate(0deg);
+ transform: rotate(0deg); } }
+
+@keyframes fa-shake {
+ 0% {
+ -webkit-transform: rotate(-15deg);
+ transform: rotate(-15deg); }
+ 4% {
+ -webkit-transform: rotate(15deg);
+ transform: rotate(15deg); }
+ 8%, 24% {
+ -webkit-transform: rotate(-18deg);
+ transform: rotate(-18deg); }
+ 12%, 28% {
+ -webkit-transform: rotate(18deg);
+ transform: rotate(18deg); }
+ 16% {
+ -webkit-transform: rotate(-22deg);
+ transform: rotate(-22deg); }
+ 20% {
+ -webkit-transform: rotate(22deg);
+ transform: rotate(22deg); }
+ 32% {
+ -webkit-transform: rotate(-12deg);
+ transform: rotate(-12deg); }
+ 36% {
+ -webkit-transform: rotate(12deg);
+ transform: rotate(12deg); }
+ 40%, 100% {
+ -webkit-transform: rotate(0deg);
+ transform: rotate(0deg); } }
+
+@-webkit-keyframes fa-spin {
+ 0% {
+ -webkit-transform: rotate(0deg);
+ transform: rotate(0deg); }
+ 100% {
+ -webkit-transform: rotate(360deg);
+ transform: rotate(360deg); } }
+
+@keyframes fa-spin {
+ 0% {
+ -webkit-transform: rotate(0deg);
+ transform: rotate(0deg); }
+ 100% {
+ -webkit-transform: rotate(360deg);
+ transform: rotate(360deg); } }
+
+.fa-rotate-90 {
+ -webkit-transform: rotate(90deg);
+ transform: rotate(90deg); }
+
+.fa-rotate-180 {
+ -webkit-transform: rotate(180deg);
+ transform: rotate(180deg); }
+
+.fa-rotate-270 {
+ -webkit-transform: rotate(270deg);
+ transform: rotate(270deg); }
+
+.fa-flip-horizontal {
+ -webkit-transform: scale(-1, 1);
+ transform: scale(-1, 1); }
+
+.fa-flip-vertical {
+ -webkit-transform: scale(1, -1);
+ transform: scale(1, -1); }
+
+.fa-flip-both,
+.fa-flip-horizontal.fa-flip-vertical {
+ -webkit-transform: scale(-1, -1);
+ transform: scale(-1, -1); }
+
+.fa-rotate-by {
+ -webkit-transform: rotate(var(--fa-rotate-angle, none));
+ transform: rotate(var(--fa-rotate-angle, none)); }
+
+.fa-stack {
+ display: inline-block;
+ height: 2em;
+ line-height: 2em;
+ position: relative;
+ vertical-align: middle;
+ width: 2.5em; }
+
+.fa-stack-1x,
+.fa-stack-2x {
+ left: 0;
+ position: absolute;
+ text-align: center;
+ width: 100%;
+ z-index: var(--fa-stack-z-index, auto); }
+
+.fa-stack-1x {
+ line-height: inherit; }
+
+.fa-stack-2x {
+ font-size: 2em; }
+
+.fa-inverse {
+ color: var(--fa-inverse, #fff); }
+
+/* Font Awesome uses the Unicode Private Use Area (PUA) to ensure screen
+readers do not read off random characters that represent icons */
+
+.fa-0::before {
+ content: "\30"; }
+
+.fa-1::before {
+ content: "\31"; }
+
+.fa-2::before {
+ content: "\32"; }
+
+.fa-3::before {
+ content: "\33"; }
+
+.fa-4::before {
+ content: "\34"; }
+
+.fa-5::before {
+ content: "\35"; }
+
+.fa-6::before {
+ content: "\36"; }
+
+.fa-7::before {
+ content: "\37"; }
+
+.fa-8::before {
+ content: "\38"; }
+
+.fa-9::before {
+ content: "\39"; }
+
+.fa-fill-drip::before {
+ content: "\f576"; }
+
+.fa-arrows-to-circle::before {
+ content: "\e4bd"; }
+
+.fa-circle-chevron-right::before {
+ content: "\f138"; }
+
+.fa-chevron-circle-right::before {
+ content: "\f138"; }
+
+.fa-at::before {
+ content: "\40"; }
+
+.fa-trash-can::before {
+ content: "\f2ed"; }
+
+.fa-trash-alt::before {
+ content: "\f2ed"; }
+
+.fa-text-height::before {
+ content: "\f034"; }
+
+.fa-user-xmark::before {
+ content: "\f235"; }
+
+.fa-user-times::before {
+ content: "\f235"; }
+
+.fa-stethoscope::before {
+ content: "\f0f1"; }
+
+.fa-message::before {
+ content: "\f27a"; }
+
+.fa-comment-alt::before {
+ content: "\f27a"; }
+
+.fa-info::before {
+ content: "\f129"; }
+
+.fa-down-left-and-up-right-to-center::before {
+ content: "\f422"; }
+
+.fa-compress-alt::before {
+ content: "\f422"; }
+
+.fa-explosion::before {
+ content: "\e4e9"; }
+
+.fa-file-lines::before {
+ content: "\f15c"; }
+
+.fa-file-alt::before {
+ content: "\f15c"; }
+
+.fa-file-text::before {
+ content: "\f15c"; }
+
+.fa-wave-square::before {
+ content: "\f83e"; }
+
+.fa-ring::before {
+ content: "\f70b"; }
+
+.fa-building-un::before {
+ content: "\e4d9"; }
+
+.fa-dice-three::before {
+ content: "\f527"; }
+
+.fa-calendar-days::before {
+ content: "\f073"; }
+
+.fa-calendar-alt::before {
+ content: "\f073"; }
+
+.fa-anchor-circle-check::before {
+ content: "\e4aa"; }
+
+.fa-building-circle-arrow-right::before {
+ content: "\e4d1"; }
+
+.fa-volleyball::before {
+ content: "\f45f"; }
+
+.fa-volleyball-ball::before {
+ content: "\f45f"; }
+
+.fa-arrows-up-to-line::before {
+ content: "\e4c2"; }
+
+.fa-sort-down::before {
+ content: "\f0dd"; }
+
+.fa-sort-desc::before {
+ content: "\f0dd"; }
+
+.fa-circle-minus::before {
+ content: "\f056"; }
+
+.fa-minus-circle::before {
+ content: "\f056"; }
+
+.fa-door-open::before {
+ content: "\f52b"; }
+
+.fa-right-from-bracket::before {
+ content: "\f2f5"; }
+
+.fa-sign-out-alt::before {
+ content: "\f2f5"; }
+
+.fa-atom::before {
+ content: "\f5d2"; }
+
+.fa-soap::before {
+ content: "\e06e"; }
+
+.fa-icons::before {
+ content: "\f86d"; }
+
+.fa-heart-music-camera-bolt::before {
+ content: "\f86d"; }
+
+.fa-microphone-lines-slash::before {
+ content: "\f539"; }
+
+.fa-microphone-alt-slash::before {
+ content: "\f539"; }
+
+.fa-bridge-circle-check::before {
+ content: "\e4c9"; }
+
+.fa-pump-medical::before {
+ content: "\e06a"; }
+
+.fa-fingerprint::before {
+ content: "\f577"; }
+
+.fa-hand-point-right::before {
+ content: "\f0a4"; }
+
+.fa-magnifying-glass-location::before {
+ content: "\f689"; }
+
+.fa-search-location::before {
+ content: "\f689"; }
+
+.fa-forward-step::before {
+ content: "\f051"; }
+
+.fa-step-forward::before {
+ content: "\f051"; }
+
+.fa-face-smile-beam::before {
+ content: "\f5b8"; }
+
+.fa-smile-beam::before {
+ content: "\f5b8"; }
+
+.fa-flag-checkered::before {
+ content: "\f11e"; }
+
+.fa-football::before {
+ content: "\f44e"; }
+
+.fa-football-ball::before {
+ content: "\f44e"; }
+
+.fa-school-circle-exclamation::before {
+ content: "\e56c"; }
+
+.fa-crop::before {
+ content: "\f125"; }
+
+.fa-angles-down::before {
+ content: "\f103"; }
+
+.fa-angle-double-down::before {
+ content: "\f103"; }
+
+.fa-users-rectangle::before {
+ content: "\e594"; }
+
+.fa-people-roof::before {
+ content: "\e537"; }
+
+.fa-people-line::before {
+ content: "\e534"; }
+
+.fa-beer-mug-empty::before {
+ content: "\f0fc"; }
+
+.fa-beer::before {
+ content: "\f0fc"; }
+
+.fa-diagram-predecessor::before {
+ content: "\e477"; }
+
+.fa-arrow-up-long::before {
+ content: "\f176"; }
+
+.fa-long-arrow-up::before {
+ content: "\f176"; }
+
+.fa-fire-flame-simple::before {
+ content: "\f46a"; }
+
+.fa-burn::before {
+ content: "\f46a"; }
+
+.fa-person::before {
+ content: "\f183"; }
+
+.fa-male::before {
+ content: "\f183"; }
+
+.fa-laptop::before {
+ content: "\f109"; }
+
+.fa-file-csv::before {
+ content: "\f6dd"; }
+
+.fa-menorah::before {
+ content: "\f676"; }
+
+.fa-truck-plane::before {
+ content: "\e58f"; }
+
+.fa-record-vinyl::before {
+ content: "\f8d9"; }
+
+.fa-face-grin-stars::before {
+ content: "\f587"; }
+
+.fa-grin-stars::before {
+ content: "\f587"; }
+
+.fa-bong::before {
+ content: "\f55c"; }
+
+.fa-spaghetti-monster-flying::before {
+ content: "\f67b"; }
+
+.fa-pastafarianism::before {
+ content: "\f67b"; }
+
+.fa-arrow-down-up-across-line::before {
+ content: "\e4af"; }
+
+.fa-spoon::before {
+ content: "\f2e5"; }
+
+.fa-utensil-spoon::before {
+ content: "\f2e5"; }
+
+.fa-jar-wheat::before {
+ content: "\e517"; }
+
+.fa-envelopes-bulk::before {
+ content: "\f674"; }
+
+.fa-mail-bulk::before {
+ content: "\f674"; }
+
+.fa-file-circle-exclamation::before {
+ content: "\e4eb"; }
+
+.fa-circle-h::before {
+ content: "\f47e"; }
+
+.fa-hospital-symbol::before {
+ content: "\f47e"; }
+
+.fa-pager::before {
+ content: "\f815"; }
+
+.fa-address-book::before {
+ content: "\f2b9"; }
+
+.fa-contact-book::before {
+ content: "\f2b9"; }
+
+.fa-strikethrough::before {
+ content: "\f0cc"; }
+
+.fa-k::before {
+ content: "\4b"; }
+
+.fa-landmark-flag::before {
+ content: "\e51c"; }
+
+.fa-pencil::before {
+ content: "\f303"; }
+
+.fa-pencil-alt::before {
+ content: "\f303"; }
+
+.fa-backward::before {
+ content: "\f04a"; }
+
+.fa-caret-right::before {
+ content: "\f0da"; }
+
+.fa-comments::before {
+ content: "\f086"; }
+
+.fa-paste::before {
+ content: "\f0ea"; }
+
+.fa-file-clipboard::before {
+ content: "\f0ea"; }
+
+.fa-code-pull-request::before {
+ content: "\e13c"; }
+
+.fa-clipboard-list::before {
+ content: "\f46d"; }
+
+.fa-truck-ramp-box::before {
+ content: "\f4de"; }
+
+.fa-truck-loading::before {
+ content: "\f4de"; }
+
+.fa-user-check::before {
+ content: "\f4fc"; }
+
+.fa-vial-virus::before {
+ content: "\e597"; }
+
+.fa-sheet-plastic::before {
+ content: "\e571"; }
+
+.fa-blog::before {
+ content: "\f781"; }
+
+.fa-user-ninja::before {
+ content: "\f504"; }
+
+.fa-person-arrow-up-from-line::before {
+ content: "\e539"; }
+
+.fa-scroll-torah::before {
+ content: "\f6a0"; }
+
+.fa-torah::before {
+ content: "\f6a0"; }
+
+.fa-broom-ball::before {
+ content: "\f458"; }
+
+.fa-quidditch::before {
+ content: "\f458"; }
+
+.fa-quidditch-broom-ball::before {
+ content: "\f458"; }
+
+.fa-toggle-off::before {
+ content: "\f204"; }
+
+.fa-box-archive::before {
+ content: "\f187"; }
+
+.fa-archive::before {
+ content: "\f187"; }
+
+.fa-person-drowning::before {
+ content: "\e545"; }
+
+.fa-arrow-down-9-1::before {
+ content: "\f886"; }
+
+.fa-sort-numeric-desc::before {
+ content: "\f886"; }
+
+.fa-sort-numeric-down-alt::before {
+ content: "\f886"; }
+
+.fa-face-grin-tongue-squint::before {
+ content: "\f58a"; }
+
+.fa-grin-tongue-squint::before {
+ content: "\f58a"; }
+
+.fa-spray-can::before {
+ content: "\f5bd"; }
+
+.fa-truck-monster::before {
+ content: "\f63b"; }
+
+.fa-w::before {
+ content: "\57"; }
+
+.fa-earth-africa::before {
+ content: "\f57c"; }
+
+.fa-globe-africa::before {
+ content: "\f57c"; }
+
+.fa-rainbow::before {
+ content: "\f75b"; }
+
+.fa-circle-notch::before {
+ content: "\f1ce"; }
+
+.fa-tablet-screen-button::before {
+ content: "\f3fa"; }
+
+.fa-tablet-alt::before {
+ content: "\f3fa"; }
+
+.fa-paw::before {
+ content: "\f1b0"; }
+
+.fa-cloud::before {
+ content: "\f0c2"; }
+
+.fa-trowel-bricks::before {
+ content: "\e58a"; }
+
+.fa-face-flushed::before {
+ content: "\f579"; }
+
+.fa-flushed::before {
+ content: "\f579"; }
+
+.fa-hospital-user::before {
+ content: "\f80d"; }
+
+.fa-tent-arrow-left-right::before {
+ content: "\e57f"; }
+
+.fa-gavel::before {
+ content: "\f0e3"; }
+
+.fa-legal::before {
+ content: "\f0e3"; }
+
+.fa-binoculars::before {
+ content: "\f1e5"; }
+
+.fa-microphone-slash::before {
+ content: "\f131"; }
+
+.fa-box-tissue::before {
+ content: "\e05b"; }
+
+.fa-motorcycle::before {
+ content: "\f21c"; }
+
+.fa-bell-concierge::before {
+ content: "\f562"; }
+
+.fa-concierge-bell::before {
+ content: "\f562"; }
+
+.fa-pen-ruler::before {
+ content: "\f5ae"; }
+
+.fa-pencil-ruler::before {
+ content: "\f5ae"; }
+
+.fa-people-arrows::before {
+ content: "\e068"; }
+
+.fa-people-arrows-left-right::before {
+ content: "\e068"; }
+
+.fa-mars-and-venus-burst::before {
+ content: "\e523"; }
+
+.fa-square-caret-right::before {
+ content: "\f152"; }
+
+.fa-caret-square-right::before {
+ content: "\f152"; }
+
+.fa-scissors::before {
+ content: "\f0c4"; }
+
+.fa-cut::before {
+ content: "\f0c4"; }
+
+.fa-sun-plant-wilt::before {
+ content: "\e57a"; }
+
+.fa-toilets-portable::before {
+ content: "\e584"; }
+
+.fa-hockey-puck::before {
+ content: "\f453"; }
+
+.fa-table::before {
+ content: "\f0ce"; }
+
+.fa-magnifying-glass-arrow-right::before {
+ content: "\e521"; }
+
+.fa-tachograph-digital::before {
+ content: "\f566"; }
+
+.fa-digital-tachograph::before {
+ content: "\f566"; }
+
+.fa-users-slash::before {
+ content: "\e073"; }
+
+.fa-clover::before {
+ content: "\e139"; }
+
+.fa-reply::before {
+ content: "\f3e5"; }
+
+.fa-mail-reply::before {
+ content: "\f3e5"; }
+
+.fa-star-and-crescent::before {
+ content: "\f699"; }
+
+.fa-house-fire::before {
+ content: "\e50c"; }
+
+.fa-square-minus::before {
+ content: "\f146"; }
+
+.fa-minus-square::before {
+ content: "\f146"; }
+
+.fa-helicopter::before {
+ content: "\f533"; }
+
+.fa-compass::before {
+ content: "\f14e"; }
+
+.fa-square-caret-down::before {
+ content: "\f150"; }
+
+.fa-caret-square-down::before {
+ content: "\f150"; }
+
+.fa-file-circle-question::before {
+ content: "\e4ef"; }
+
+.fa-laptop-code::before {
+ content: "\f5fc"; }
+
+.fa-swatchbook::before {
+ content: "\f5c3"; }
+
+.fa-prescription-bottle::before {
+ content: "\f485"; }
+
+.fa-bars::before {
+ content: "\f0c9"; }
+
+.fa-navicon::before {
+ content: "\f0c9"; }
+
+.fa-people-group::before {
+ content: "\e533"; }
+
+.fa-hourglass-end::before {
+ content: "\f253"; }
+
+.fa-hourglass-3::before {
+ content: "\f253"; }
+
+.fa-heart-crack::before {
+ content: "\f7a9"; }
+
+.fa-heart-broken::before {
+ content: "\f7a9"; }
+
+.fa-square-up-right::before {
+ content: "\f360"; }
+
+.fa-external-link-square-alt::before {
+ content: "\f360"; }
+
+.fa-face-kiss-beam::before {
+ content: "\f597"; }
+
+.fa-kiss-beam::before {
+ content: "\f597"; }
+
+.fa-film::before {
+ content: "\f008"; }
+
+.fa-ruler-horizontal::before {
+ content: "\f547"; }
+
+.fa-people-robbery::before {
+ content: "\e536"; }
+
+.fa-lightbulb::before {
+ content: "\f0eb"; }
+
+.fa-caret-left::before {
+ content: "\f0d9"; }
+
+.fa-circle-exclamation::before {
+ content: "\f06a"; }
+
+.fa-exclamation-circle::before {
+ content: "\f06a"; }
+
+.fa-school-circle-xmark::before {
+ content: "\e56d"; }
+
+.fa-arrow-right-from-bracket::before {
+ content: "\f08b"; }
+
+.fa-sign-out::before {
+ content: "\f08b"; }
+
+.fa-circle-chevron-down::before {
+ content: "\f13a"; }
+
+.fa-chevron-circle-down::before {
+ content: "\f13a"; }
+
+.fa-unlock-keyhole::before {
+ content: "\f13e"; }
+
+.fa-unlock-alt::before {
+ content: "\f13e"; }
+
+.fa-cloud-showers-heavy::before {
+ content: "\f740"; }
+
+.fa-headphones-simple::before {
+ content: "\f58f"; }
+
+.fa-headphones-alt::before {
+ content: "\f58f"; }
+
+.fa-sitemap::before {
+ content: "\f0e8"; }
+
+.fa-circle-dollar-to-slot::before {
+ content: "\f4b9"; }
+
+.fa-donate::before {
+ content: "\f4b9"; }
+
+.fa-memory::before {
+ content: "\f538"; }
+
+.fa-road-spikes::before {
+ content: "\e568"; }
+
+.fa-fire-burner::before {
+ content: "\e4f1"; }
+
+.fa-flag::before {
+ content: "\f024"; }
+
+.fa-hanukiah::before {
+ content: "\f6e6"; }
+
+.fa-feather::before {
+ content: "\f52d"; }
+
+.fa-volume-low::before {
+ content: "\f027"; }
+
+.fa-volume-down::before {
+ content: "\f027"; }
+
+.fa-comment-slash::before {
+ content: "\f4b3"; }
+
+.fa-cloud-sun-rain::before {
+ content: "\f743"; }
+
+.fa-compress::before {
+ content: "\f066"; }
+
+.fa-wheat-awn::before {
+ content: "\e2cd"; }
+
+.fa-wheat-alt::before {
+ content: "\e2cd"; }
+
+.fa-ankh::before {
+ content: "\f644"; }
+
+.fa-hands-holding-child::before {
+ content: "\e4fa"; }
+
+.fa-asterisk::before {
+ content: "\2a"; }
+
+.fa-square-check::before {
+ content: "\f14a"; }
+
+.fa-check-square::before {
+ content: "\f14a"; }
+
+.fa-peseta-sign::before {
+ content: "\e221"; }
+
+.fa-heading::before {
+ content: "\f1dc"; }
+
+.fa-header::before {
+ content: "\f1dc"; }
+
+.fa-ghost::before {
+ content: "\f6e2"; }
+
+.fa-list::before {
+ content: "\f03a"; }
+
+.fa-list-squares::before {
+ content: "\f03a"; }
+
+.fa-square-phone-flip::before {
+ content: "\f87b"; }
+
+.fa-phone-square-alt::before {
+ content: "\f87b"; }
+
+.fa-cart-plus::before {
+ content: "\f217"; }
+
+.fa-gamepad::before {
+ content: "\f11b"; }
+
+.fa-circle-dot::before {
+ content: "\f192"; }
+
+.fa-dot-circle::before {
+ content: "\f192"; }
+
+.fa-face-dizzy::before {
+ content: "\f567"; }
+
+.fa-dizzy::before {
+ content: "\f567"; }
+
+.fa-egg::before {
+ content: "\f7fb"; }
+
+.fa-house-medical-circle-xmark::before {
+ content: "\e513"; }
+
+.fa-campground::before {
+ content: "\f6bb"; }
+
+.fa-folder-plus::before {
+ content: "\f65e"; }
+
+.fa-futbol::before {
+ content: "\f1e3"; }
+
+.fa-futbol-ball::before {
+ content: "\f1e3"; }
+
+.fa-soccer-ball::before {
+ content: "\f1e3"; }
+
+.fa-paintbrush::before {
+ content: "\f1fc"; }
+
+.fa-paint-brush::before {
+ content: "\f1fc"; }
+
+.fa-lock::before {
+ content: "\f023"; }
+
+.fa-gas-pump::before {
+ content: "\f52f"; }
+
+.fa-hot-tub-person::before {
+ content: "\f593"; }
+
+.fa-hot-tub::before {
+ content: "\f593"; }
+
+.fa-map-location::before {
+ content: "\f59f"; }
+
+.fa-map-marked::before {
+ content: "\f59f"; }
+
+.fa-house-flood-water::before {
+ content: "\e50e"; }
+
+.fa-tree::before {
+ content: "\f1bb"; }
+
+.fa-bridge-lock::before {
+ content: "\e4cc"; }
+
+.fa-sack-dollar::before {
+ content: "\f81d"; }
+
+.fa-pen-to-square::before {
+ content: "\f044"; }
+
+.fa-edit::before {
+ content: "\f044"; }
+
+.fa-car-side::before {
+ content: "\f5e4"; }
+
+.fa-share-nodes::before {
+ content: "\f1e0"; }
+
+.fa-share-alt::before {
+ content: "\f1e0"; }
+
+.fa-heart-circle-minus::before {
+ content: "\e4ff"; }
+
+.fa-hourglass-half::before {
+ content: "\f252"; }
+
+.fa-hourglass-2::before {
+ content: "\f252"; }
+
+.fa-microscope::before {
+ content: "\f610"; }
+
+.fa-sink::before {
+ content: "\e06d"; }
+
+.fa-bag-shopping::before {
+ content: "\f290"; }
+
+.fa-shopping-bag::before {
+ content: "\f290"; }
+
+.fa-arrow-down-z-a::before {
+ content: "\f881"; }
+
+.fa-sort-alpha-desc::before {
+ content: "\f881"; }
+
+.fa-sort-alpha-down-alt::before {
+ content: "\f881"; }
+
+.fa-mitten::before {
+ content: "\f7b5"; }
+
+.fa-person-rays::before {
+ content: "\e54d"; }
+
+.fa-users::before {
+ content: "\f0c0"; }
+
+.fa-eye-slash::before {
+ content: "\f070"; }
+
+.fa-flask-vial::before {
+ content: "\e4f3"; }
+
+.fa-hand::before {
+ content: "\f256"; }
+
+.fa-hand-paper::before {
+ content: "\f256"; }
+
+.fa-om::before {
+ content: "\f679"; }
+
+.fa-worm::before {
+ content: "\e599"; }
+
+.fa-house-circle-xmark::before {
+ content: "\e50b"; }
+
+.fa-plug::before {
+ content: "\f1e6"; }
+
+.fa-chevron-up::before {
+ content: "\f077"; }
+
+.fa-hand-spock::before {
+ content: "\f259"; }
+
+.fa-stopwatch::before {
+ content: "\f2f2"; }
+
+.fa-face-kiss::before {
+ content: "\f596"; }
+
+.fa-kiss::before {
+ content: "\f596"; }
+
+.fa-bridge-circle-xmark::before {
+ content: "\e4cb"; }
+
+.fa-face-grin-tongue::before {
+ content: "\f589"; }
+
+.fa-grin-tongue::before {
+ content: "\f589"; }
+
+.fa-chess-bishop::before {
+ content: "\f43a"; }
+
+.fa-face-grin-wink::before {
+ content: "\f58c"; }
+
+.fa-grin-wink::before {
+ content: "\f58c"; }
+
+.fa-ear-deaf::before {
+ content: "\f2a4"; }
+
+.fa-deaf::before {
+ content: "\f2a4"; }
+
+.fa-deafness::before {
+ content: "\f2a4"; }
+
+.fa-hard-of-hearing::before {
+ content: "\f2a4"; }
+
+.fa-road-circle-check::before {
+ content: "\e564"; }
+
+.fa-dice-five::before {
+ content: "\f523"; }
+
+.fa-square-rss::before {
+ content: "\f143"; }
+
+.fa-rss-square::before {
+ content: "\f143"; }
+
+.fa-land-mine-on::before {
+ content: "\e51b"; }
+
+.fa-i-cursor::before {
+ content: "\f246"; }
+
+.fa-stamp::before {
+ content: "\f5bf"; }
+
+.fa-stairs::before {
+ content: "\e289"; }
+
+.fa-i::before {
+ content: "\49"; }
+
+.fa-hryvnia-sign::before {
+ content: "\f6f2"; }
+
+.fa-hryvnia::before {
+ content: "\f6f2"; }
+
+.fa-pills::before {
+ content: "\f484"; }
+
+.fa-face-grin-wide::before {
+ content: "\f581"; }
+
+.fa-grin-alt::before {
+ content: "\f581"; }
+
+.fa-tooth::before {
+ content: "\f5c9"; }
+
+.fa-v::before {
+ content: "\56"; }
+
+.fa-bangladeshi-taka-sign::before {
+ content: "\e2e6"; }
+
+.fa-bicycle::before {
+ content: "\f206"; }
+
+.fa-staff-snake::before {
+ content: "\e579"; }
+
+.fa-rod-asclepius::before {
+ content: "\e579"; }
+
+.fa-rod-snake::before {
+ content: "\e579"; }
+
+.fa-staff-aesculapius::before {
+ content: "\e579"; }
+
+.fa-head-side-cough-slash::before {
+ content: "\e062"; }
+
+.fa-truck-medical::before {
+ content: "\f0f9"; }
+
+.fa-ambulance::before {
+ content: "\f0f9"; }
+
+.fa-wheat-awn-circle-exclamation::before {
+ content: "\e598"; }
+
+.fa-snowman::before {
+ content: "\f7d0"; }
+
+.fa-mortar-pestle::before {
+ content: "\f5a7"; }
+
+.fa-road-barrier::before {
+ content: "\e562"; }
+
+.fa-school::before {
+ content: "\f549"; }
+
+.fa-igloo::before {
+ content: "\f7ae"; }
+
+.fa-joint::before {
+ content: "\f595"; }
+
+.fa-angle-right::before {
+ content: "\f105"; }
+
+.fa-horse::before {
+ content: "\f6f0"; }
+
+.fa-q::before {
+ content: "\51"; }
+
+.fa-g::before {
+ content: "\47"; }
+
+.fa-notes-medical::before {
+ content: "\f481"; }
+
+.fa-temperature-half::before {
+ content: "\f2c9"; }
+
+.fa-temperature-2::before {
+ content: "\f2c9"; }
+
+.fa-thermometer-2::before {
+ content: "\f2c9"; }
+
+.fa-thermometer-half::before {
+ content: "\f2c9"; }
+
+.fa-dong-sign::before {
+ content: "\e169"; }
+
+.fa-capsules::before {
+ content: "\f46b"; }
+
+.fa-poo-storm::before {
+ content: "\f75a"; }
+
+.fa-poo-bolt::before {
+ content: "\f75a"; }
+
+.fa-face-frown-open::before {
+ content: "\f57a"; }
+
+.fa-frown-open::before {
+ content: "\f57a"; }
+
+.fa-hand-point-up::before {
+ content: "\f0a6"; }
+
+.fa-money-bill::before {
+ content: "\f0d6"; }
+
+.fa-bookmark::before {
+ content: "\f02e"; }
+
+.fa-align-justify::before {
+ content: "\f039"; }
+
+.fa-umbrella-beach::before {
+ content: "\f5ca"; }
+
+.fa-helmet-un::before {
+ content: "\e503"; }
+
+.fa-bullseye::before {
+ content: "\f140"; }
+
+.fa-bacon::before {
+ content: "\f7e5"; }
+
+.fa-hand-point-down::before {
+ content: "\f0a7"; }
+
+.fa-arrow-up-from-bracket::before {
+ content: "\e09a"; }
+
+.fa-folder::before {
+ content: "\f07b"; }
+
+.fa-folder-blank::before {
+ content: "\f07b"; }
+
+.fa-file-waveform::before {
+ content: "\f478"; }
+
+.fa-file-medical-alt::before {
+ content: "\f478"; }
+
+.fa-radiation::before {
+ content: "\f7b9"; }
+
+.fa-chart-simple::before {
+ content: "\e473"; }
+
+.fa-mars-stroke::before {
+ content: "\f229"; }
+
+.fa-vial::before {
+ content: "\f492"; }
+
+.fa-gauge::before {
+ content: "\f624"; }
+
+.fa-dashboard::before {
+ content: "\f624"; }
+
+.fa-gauge-med::before {
+ content: "\f624"; }
+
+.fa-tachometer-alt-average::before {
+ content: "\f624"; }
+
+.fa-wand-magic-sparkles::before {
+ content: "\e2ca"; }
+
+.fa-magic-wand-sparkles::before {
+ content: "\e2ca"; }
+
+.fa-e::before {
+ content: "\45"; }
+
+.fa-pen-clip::before {
+ content: "\f305"; }
+
+.fa-pen-alt::before {
+ content: "\f305"; }
+
+.fa-bridge-circle-exclamation::before {
+ content: "\e4ca"; }
+
+.fa-user::before {
+ content: "\f007"; }
+
+.fa-school-circle-check::before {
+ content: "\e56b"; }
+
+.fa-dumpster::before {
+ content: "\f793"; }
+
+.fa-van-shuttle::before {
+ content: "\f5b6"; }
+
+.fa-shuttle-van::before {
+ content: "\f5b6"; }
+
+.fa-building-user::before {
+ content: "\e4da"; }
+
+.fa-square-caret-left::before {
+ content: "\f191"; }
+
+.fa-caret-square-left::before {
+ content: "\f191"; }
+
+.fa-highlighter::before {
+ content: "\f591"; }
+
+.fa-key::before {
+ content: "\f084"; }
+
+.fa-bullhorn::before {
+ content: "\f0a1"; }
+
+.fa-globe::before {
+ content: "\f0ac"; }
+
+.fa-synagogue::before {
+ content: "\f69b"; }
+
+.fa-person-half-dress::before {
+ content: "\e548"; }
+
+.fa-road-bridge::before {
+ content: "\e563"; }
+
+.fa-location-arrow::before {
+ content: "\f124"; }
+
+.fa-c::before {
+ content: "\43"; }
+
+.fa-tablet-button::before {
+ content: "\f10a"; }
+
+.fa-building-lock::before {
+ content: "\e4d6"; }
+
+.fa-pizza-slice::before {
+ content: "\f818"; }
+
+.fa-money-bill-wave::before {
+ content: "\f53a"; }
+
+.fa-chart-area::before {
+ content: "\f1fe"; }
+
+.fa-area-chart::before {
+ content: "\f1fe"; }
+
+.fa-house-flag::before {
+ content: "\e50d"; }
+
+.fa-person-circle-minus::before {
+ content: "\e540"; }
+
+.fa-ban::before {
+ content: "\f05e"; }
+
+.fa-cancel::before {
+ content: "\f05e"; }
+
+.fa-camera-rotate::before {
+ content: "\e0d8"; }
+
+.fa-spray-can-sparkles::before {
+ content: "\f5d0"; }
+
+.fa-air-freshener::before {
+ content: "\f5d0"; }
+
+.fa-star::before {
+ content: "\f005"; }
+
+.fa-repeat::before {
+ content: "\f363"; }
+
+.fa-cross::before {
+ content: "\f654"; }
+
+.fa-box::before {
+ content: "\f466"; }
+
+.fa-venus-mars::before {
+ content: "\f228"; }
+
+.fa-arrow-pointer::before {
+ content: "\f245"; }
+
+.fa-mouse-pointer::before {
+ content: "\f245"; }
+
+.fa-maximize::before {
+ content: "\f31e"; }
+
+.fa-expand-arrows-alt::before {
+ content: "\f31e"; }
+
+.fa-charging-station::before {
+ content: "\f5e7"; }
+
+.fa-shapes::before {
+ content: "\f61f"; }
+
+.fa-triangle-circle-square::before {
+ content: "\f61f"; }
+
+.fa-shuffle::before {
+ content: "\f074"; }
+
+.fa-random::before {
+ content: "\f074"; }
+
+.fa-person-running::before {
+ content: "\f70c"; }
+
+.fa-running::before {
+ content: "\f70c"; }
+
+.fa-mobile-retro::before {
+ content: "\e527"; }
+
+.fa-grip-lines-vertical::before {
+ content: "\f7a5"; }
+
+.fa-spider::before {
+ content: "\f717"; }
+
+.fa-hands-bound::before {
+ content: "\e4f9"; }
+
+.fa-file-invoice-dollar::before {
+ content: "\f571"; }
+
+.fa-plane-circle-exclamation::before {
+ content: "\e556"; }
+
+.fa-x-ray::before {
+ content: "\f497"; }
+
+.fa-spell-check::before {
+ content: "\f891"; }
+
+.fa-slash::before {
+ content: "\f715"; }
+
+.fa-computer-mouse::before {
+ content: "\f8cc"; }
+
+.fa-mouse::before {
+ content: "\f8cc"; }
+
+.fa-arrow-right-to-bracket::before {
+ content: "\f090"; }
+
+.fa-sign-in::before {
+ content: "\f090"; }
+
+.fa-shop-slash::before {
+ content: "\e070"; }
+
+.fa-store-alt-slash::before {
+ content: "\e070"; }
+
+.fa-server::before {
+ content: "\f233"; }
+
+.fa-virus-covid-slash::before {
+ content: "\e4a9"; }
+
+.fa-shop-lock::before {
+ content: "\e4a5"; }
+
+.fa-hourglass-start::before {
+ content: "\f251"; }
+
+.fa-hourglass-1::before {
+ content: "\f251"; }
+
+.fa-blender-phone::before {
+ content: "\f6b6"; }
+
+.fa-building-wheat::before {
+ content: "\e4db"; }
+
+.fa-person-breastfeeding::before {
+ content: "\e53a"; }
+
+.fa-right-to-bracket::before {
+ content: "\f2f6"; }
+
+.fa-sign-in-alt::before {
+ content: "\f2f6"; }
+
+.fa-venus::before {
+ content: "\f221"; }
+
+.fa-passport::before {
+ content: "\f5ab"; }
+
+.fa-heart-pulse::before {
+ content: "\f21e"; }
+
+.fa-heartbeat::before {
+ content: "\f21e"; }
+
+.fa-people-carry-box::before {
+ content: "\f4ce"; }
+
+.fa-people-carry::before {
+ content: "\f4ce"; }
+
+.fa-temperature-high::before {
+ content: "\f769"; }
+
+.fa-microchip::before {
+ content: "\f2db"; }
+
+.fa-crown::before {
+ content: "\f521"; }
+
+.fa-weight-hanging::before {
+ content: "\f5cd"; }
+
+.fa-xmarks-lines::before {
+ content: "\e59a"; }
+
+.fa-file-prescription::before {
+ content: "\f572"; }
+
+.fa-weight-scale::before {
+ content: "\f496"; }
+
+.fa-weight::before {
+ content: "\f496"; }
+
+.fa-user-group::before {
+ content: "\f500"; }
+
+.fa-user-friends::before {
+ content: "\f500"; }
+
+.fa-arrow-up-a-z::before {
+ content: "\f15e"; }
+
+.fa-sort-alpha-up::before {
+ content: "\f15e"; }
+
+.fa-chess-knight::before {
+ content: "\f441"; }
+
+.fa-face-laugh-squint::before {
+ content: "\f59b"; }
+
+.fa-laugh-squint::before {
+ content: "\f59b"; }
+
+.fa-wheelchair::before {
+ content: "\f193"; }
+
+.fa-circle-arrow-up::before {
+ content: "\f0aa"; }
+
+.fa-arrow-circle-up::before {
+ content: "\f0aa"; }
+
+.fa-toggle-on::before {
+ content: "\f205"; }
+
+.fa-person-walking::before {
+ content: "\f554"; }
+
+.fa-walking::before {
+ content: "\f554"; }
+
+.fa-l::before {
+ content: "\4c"; }
+
+.fa-fire::before {
+ content: "\f06d"; }
+
+.fa-bed-pulse::before {
+ content: "\f487"; }
+
+.fa-procedures::before {
+ content: "\f487"; }
+
+.fa-shuttle-space::before {
+ content: "\f197"; }
+
+.fa-space-shuttle::before {
+ content: "\f197"; }
+
+.fa-face-laugh::before {
+ content: "\f599"; }
+
+.fa-laugh::before {
+ content: "\f599"; }
+
+.fa-folder-open::before {
+ content: "\f07c"; }
+
+.fa-heart-circle-plus::before {
+ content: "\e500"; }
+
+.fa-code-fork::before {
+ content: "\e13b"; }
+
+.fa-city::before {
+ content: "\f64f"; }
+
+.fa-microphone-lines::before {
+ content: "\f3c9"; }
+
+.fa-microphone-alt::before {
+ content: "\f3c9"; }
+
+.fa-pepper-hot::before {
+ content: "\f816"; }
+
+.fa-unlock::before {
+ content: "\f09c"; }
+
+.fa-colon-sign::before {
+ content: "\e140"; }
+
+.fa-headset::before {
+ content: "\f590"; }
+
+.fa-store-slash::before {
+ content: "\e071"; }
+
+.fa-road-circle-xmark::before {
+ content: "\e566"; }
+
+.fa-user-minus::before {
+ content: "\f503"; }
+
+.fa-mars-stroke-up::before {
+ content: "\f22a"; }
+
+.fa-mars-stroke-v::before {
+ content: "\f22a"; }
+
+.fa-champagne-glasses::before {
+ content: "\f79f"; }
+
+.fa-glass-cheers::before {
+ content: "\f79f"; }
+
+.fa-clipboard::before {
+ content: "\f328"; }
+
+.fa-house-circle-exclamation::before {
+ content: "\e50a"; }
+
+.fa-file-arrow-up::before {
+ content: "\f574"; }
+
+.fa-file-upload::before {
+ content: "\f574"; }
+
+.fa-wifi::before {
+ content: "\f1eb"; }
+
+.fa-wifi-3::before {
+ content: "\f1eb"; }
+
+.fa-wifi-strong::before {
+ content: "\f1eb"; }
+
+.fa-bath::before {
+ content: "\f2cd"; }
+
+.fa-bathtub::before {
+ content: "\f2cd"; }
+
+.fa-underline::before {
+ content: "\f0cd"; }
+
+.fa-user-pen::before {
+ content: "\f4ff"; }
+
+.fa-user-edit::before {
+ content: "\f4ff"; }
+
+.fa-signature::before {
+ content: "\f5b7"; }
+
+.fa-stroopwafel::before {
+ content: "\f551"; }
+
+.fa-bold::before {
+ content: "\f032"; }
+
+.fa-anchor-lock::before {
+ content: "\e4ad"; }
+
+.fa-building-ngo::before {
+ content: "\e4d7"; }
+
+.fa-manat-sign::before {
+ content: "\e1d5"; }
+
+.fa-not-equal::before {
+ content: "\f53e"; }
+
+.fa-border-top-left::before {
+ content: "\f853"; }
+
+.fa-border-style::before {
+ content: "\f853"; }
+
+.fa-map-location-dot::before {
+ content: "\f5a0"; }
+
+.fa-map-marked-alt::before {
+ content: "\f5a0"; }
+
+.fa-jedi::before {
+ content: "\f669"; }
+
+.fa-square-poll-vertical::before {
+ content: "\f681"; }
+
+.fa-poll::before {
+ content: "\f681"; }
+
+.fa-mug-hot::before {
+ content: "\f7b6"; }
+
+.fa-car-battery::before {
+ content: "\f5df"; }
+
+.fa-battery-car::before {
+ content: "\f5df"; }
+
+.fa-gift::before {
+ content: "\f06b"; }
+
+.fa-dice-two::before {
+ content: "\f528"; }
+
+.fa-chess-queen::before {
+ content: "\f445"; }
+
+.fa-glasses::before {
+ content: "\f530"; }
+
+.fa-chess-board::before {
+ content: "\f43c"; }
+
+.fa-building-circle-check::before {
+ content: "\e4d2"; }
+
+.fa-person-chalkboard::before {
+ content: "\e53d"; }
+
+.fa-mars-stroke-right::before {
+ content: "\f22b"; }
+
+.fa-mars-stroke-h::before {
+ content: "\f22b"; }
+
+.fa-hand-back-fist::before {
+ content: "\f255"; }
+
+.fa-hand-rock::before {
+ content: "\f255"; }
+
+.fa-square-caret-up::before {
+ content: "\f151"; }
+
+.fa-caret-square-up::before {
+ content: "\f151"; }
+
+.fa-cloud-showers-water::before {
+ content: "\e4e4"; }
+
+.fa-chart-bar::before {
+ content: "\f080"; }
+
+.fa-bar-chart::before {
+ content: "\f080"; }
+
+.fa-hands-bubbles::before {
+ content: "\e05e"; }
+
+.fa-hands-wash::before {
+ content: "\e05e"; }
+
+.fa-less-than-equal::before {
+ content: "\f537"; }
+
+.fa-train::before {
+ content: "\f238"; }
+
+.fa-eye-low-vision::before {
+ content: "\f2a8"; }
+
+.fa-low-vision::before {
+ content: "\f2a8"; }
+
+.fa-crow::before {
+ content: "\f520"; }
+
+.fa-sailboat::before {
+ content: "\e445"; }
+
+.fa-window-restore::before {
+ content: "\f2d2"; }
+
+.fa-square-plus::before {
+ content: "\f0fe"; }
+
+.fa-plus-square::before {
+ content: "\f0fe"; }
+
+.fa-torii-gate::before {
+ content: "\f6a1"; }
+
+.fa-frog::before {
+ content: "\f52e"; }
+
+.fa-bucket::before {
+ content: "\e4cf"; }
+
+.fa-image::before {
+ content: "\f03e"; }
+
+.fa-microphone::before {
+ content: "\f130"; }
+
+.fa-cow::before {
+ content: "\f6c8"; }
+
+.fa-caret-up::before {
+ content: "\f0d8"; }
+
+.fa-screwdriver::before {
+ content: "\f54a"; }
+
+.fa-folder-closed::before {
+ content: "\e185"; }
+
+.fa-house-tsunami::before {
+ content: "\e515"; }
+
+.fa-square-nfi::before {
+ content: "\e576"; }
+
+.fa-arrow-up-from-ground-water::before {
+ content: "\e4b5"; }
+
+.fa-martini-glass::before {
+ content: "\f57b"; }
+
+.fa-glass-martini-alt::before {
+ content: "\f57b"; }
+
+.fa-rotate-left::before {
+ content: "\f2ea"; }
+
+.fa-rotate-back::before {
+ content: "\f2ea"; }
+
+.fa-rotate-backward::before {
+ content: "\f2ea"; }
+
+.fa-undo-alt::before {
+ content: "\f2ea"; }
+
+.fa-table-columns::before {
+ content: "\f0db"; }
+
+.fa-columns::before {
+ content: "\f0db"; }
+
+.fa-lemon::before {
+ content: "\f094"; }
+
+.fa-head-side-mask::before {
+ content: "\e063"; }
+
+.fa-handshake::before {
+ content: "\f2b5"; }
+
+.fa-gem::before {
+ content: "\f3a5"; }
+
+.fa-dolly::before {
+ content: "\f472"; }
+
+.fa-dolly-box::before {
+ content: "\f472"; }
+
+.fa-smoking::before {
+ content: "\f48d"; }
+
+.fa-minimize::before {
+ content: "\f78c"; }
+
+.fa-compress-arrows-alt::before {
+ content: "\f78c"; }
+
+.fa-monument::before {
+ content: "\f5a6"; }
+
+.fa-snowplow::before {
+ content: "\f7d2"; }
+
+.fa-angles-right::before {
+ content: "\f101"; }
+
+.fa-angle-double-right::before {
+ content: "\f101"; }
+
+.fa-cannabis::before {
+ content: "\f55f"; }
+
+.fa-circle-play::before {
+ content: "\f144"; }
+
+.fa-play-circle::before {
+ content: "\f144"; }
+
+.fa-tablets::before {
+ content: "\f490"; }
+
+.fa-ethernet::before {
+ content: "\f796"; }
+
+.fa-euro-sign::before {
+ content: "\f153"; }
+
+.fa-eur::before {
+ content: "\f153"; }
+
+.fa-euro::before {
+ content: "\f153"; }
+
+.fa-chair::before {
+ content: "\f6c0"; }
+
+.fa-circle-check::before {
+ content: "\f058"; }
+
+.fa-check-circle::before {
+ content: "\f058"; }
+
+.fa-circle-stop::before {
+ content: "\f28d"; }
+
+.fa-stop-circle::before {
+ content: "\f28d"; }
+
+.fa-compass-drafting::before {
+ content: "\f568"; }
+
+.fa-drafting-compass::before {
+ content: "\f568"; }
+
+.fa-plate-wheat::before {
+ content: "\e55a"; }
+
+.fa-icicles::before {
+ content: "\f7ad"; }
+
+.fa-person-shelter::before {
+ content: "\e54f"; }
+
+.fa-neuter::before {
+ content: "\f22c"; }
+
+.fa-id-badge::before {
+ content: "\f2c1"; }
+
+.fa-marker::before {
+ content: "\f5a1"; }
+
+.fa-face-laugh-beam::before {
+ content: "\f59a"; }
+
+.fa-laugh-beam::before {
+ content: "\f59a"; }
+
+.fa-helicopter-symbol::before {
+ content: "\e502"; }
+
+.fa-universal-access::before {
+ content: "\f29a"; }
+
+.fa-circle-chevron-up::before {
+ content: "\f139"; }
+
+.fa-chevron-circle-up::before {
+ content: "\f139"; }
+
+.fa-lari-sign::before {
+ content: "\e1c8"; }
+
+.fa-volcano::before {
+ content: "\f770"; }
+
+.fa-person-walking-dashed-line-arrow-right::before {
+ content: "\e553"; }
+
+.fa-sterling-sign::before {
+ content: "\f154"; }
+
+.fa-gbp::before {
+ content: "\f154"; }
+
+.fa-pound-sign::before {
+ content: "\f154"; }
+
+.fa-viruses::before {
+ content: "\e076"; }
+
+.fa-square-person-confined::before {
+ content: "\e577"; }
+
+.fa-user-tie::before {
+ content: "\f508"; }
+
+.fa-arrow-down-long::before {
+ content: "\f175"; }
+
+.fa-long-arrow-down::before {
+ content: "\f175"; }
+
+.fa-tent-arrow-down-to-line::before {
+ content: "\e57e"; }
+
+.fa-certificate::before {
+ content: "\f0a3"; }
+
+.fa-reply-all::before {
+ content: "\f122"; }
+
+.fa-mail-reply-all::before {
+ content: "\f122"; }
+
+.fa-suitcase::before {
+ content: "\f0f2"; }
+
+.fa-person-skating::before {
+ content: "\f7c5"; }
+
+.fa-skating::before {
+ content: "\f7c5"; }
+
+.fa-filter-circle-dollar::before {
+ content: "\f662"; }
+
+.fa-funnel-dollar::before {
+ content: "\f662"; }
+
+.fa-camera-retro::before {
+ content: "\f083"; }
+
+.fa-circle-arrow-down::before {
+ content: "\f0ab"; }
+
+.fa-arrow-circle-down::before {
+ content: "\f0ab"; }
+
+.fa-file-import::before {
+ content: "\f56f"; }
+
+.fa-arrow-right-to-file::before {
+ content: "\f56f"; }
+
+.fa-square-arrow-up-right::before {
+ content: "\f14c"; }
+
+.fa-external-link-square::before {
+ content: "\f14c"; }
+
+.fa-box-open::before {
+ content: "\f49e"; }
+
+.fa-scroll::before {
+ content: "\f70e"; }
+
+.fa-spa::before {
+ content: "\f5bb"; }
+
+.fa-location-pin-lock::before {
+ content: "\e51f"; }
+
+.fa-pause::before {
+ content: "\f04c"; }
+
+.fa-hill-avalanche::before {
+ content: "\e507"; }
+
+.fa-temperature-empty::before {
+ content: "\f2cb"; }
+
+.fa-temperature-0::before {
+ content: "\f2cb"; }
+
+.fa-thermometer-0::before {
+ content: "\f2cb"; }
+
+.fa-thermometer-empty::before {
+ content: "\f2cb"; }
+
+.fa-bomb::before {
+ content: "\f1e2"; }
+
+.fa-registered::before {
+ content: "\f25d"; }
+
+.fa-address-card::before {
+ content: "\f2bb"; }
+
+.fa-contact-card::before {
+ content: "\f2bb"; }
+
+.fa-vcard::before {
+ content: "\f2bb"; }
+
+.fa-scale-unbalanced-flip::before {
+ content: "\f516"; }
+
+.fa-balance-scale-right::before {
+ content: "\f516"; }
+
+.fa-subscript::before {
+ content: "\f12c"; }
+
+.fa-diamond-turn-right::before {
+ content: "\f5eb"; }
+
+.fa-directions::before {
+ content: "\f5eb"; }
+
+.fa-burst::before {
+ content: "\e4dc"; }
+
+.fa-house-laptop::before {
+ content: "\e066"; }
+
+.fa-laptop-house::before {
+ content: "\e066"; }
+
+.fa-face-tired::before {
+ content: "\f5c8"; }
+
+.fa-tired::before {
+ content: "\f5c8"; }
+
+.fa-money-bills::before {
+ content: "\e1f3"; }
+
+.fa-smog::before {
+ content: "\f75f"; }
+
+.fa-crutch::before {
+ content: "\f7f7"; }
+
+.fa-cloud-arrow-up::before {
+ content: "\f0ee"; }
+
+.fa-cloud-upload::before {
+ content: "\f0ee"; }
+
+.fa-cloud-upload-alt::before {
+ content: "\f0ee"; }
+
+.fa-palette::before {
+ content: "\f53f"; }
+
+.fa-arrows-turn-right::before {
+ content: "\e4c0"; }
+
+.fa-vest::before {
+ content: "\e085"; }
+
+.fa-ferry::before {
+ content: "\e4ea"; }
+
+.fa-arrows-down-to-people::before {
+ content: "\e4b9"; }
+
+.fa-seedling::before {
+ content: "\f4d8"; }
+
+.fa-sprout::before {
+ content: "\f4d8"; }
+
+.fa-left-right::before {
+ content: "\f337"; }
+
+.fa-arrows-alt-h::before {
+ content: "\f337"; }
+
+.fa-boxes-packing::before {
+ content: "\e4c7"; }
+
+.fa-circle-arrow-left::before {
+ content: "\f0a8"; }
+
+.fa-arrow-circle-left::before {
+ content: "\f0a8"; }
+
+.fa-group-arrows-rotate::before {
+ content: "\e4f6"; }
+
+.fa-bowl-food::before {
+ content: "\e4c6"; }
+
+.fa-candy-cane::before {
+ content: "\f786"; }
+
+.fa-arrow-down-wide-short::before {
+ content: "\f160"; }
+
+.fa-sort-amount-asc::before {
+ content: "\f160"; }
+
+.fa-sort-amount-down::before {
+ content: "\f160"; }
+
+.fa-cloud-bolt::before {
+ content: "\f76c"; }
+
+.fa-thunderstorm::before {
+ content: "\f76c"; }
+
+.fa-text-slash::before {
+ content: "\f87d"; }
+
+.fa-remove-format::before {
+ content: "\f87d"; }
+
+.fa-face-smile-wink::before {
+ content: "\f4da"; }
+
+.fa-smile-wink::before {
+ content: "\f4da"; }
+
+.fa-file-word::before {
+ content: "\f1c2"; }
+
+.fa-file-powerpoint::before {
+ content: "\f1c4"; }
+
+.fa-arrows-left-right::before {
+ content: "\f07e"; }
+
+.fa-arrows-h::before {
+ content: "\f07e"; }
+
+.fa-house-lock::before {
+ content: "\e510"; }
+
+.fa-cloud-arrow-down::before {
+ content: "\f0ed"; }
+
+.fa-cloud-download::before {
+ content: "\f0ed"; }
+
+.fa-cloud-download-alt::before {
+ content: "\f0ed"; }
+
+.fa-children::before {
+ content: "\e4e1"; }
+
+.fa-chalkboard::before {
+ content: "\f51b"; }
+
+.fa-blackboard::before {
+ content: "\f51b"; }
+
+.fa-user-large-slash::before {
+ content: "\f4fa"; }
+
+.fa-user-alt-slash::before {
+ content: "\f4fa"; }
+
+.fa-envelope-open::before {
+ content: "\f2b6"; }
+
+.fa-handshake-simple-slash::before {
+ content: "\e05f"; }
+
+.fa-handshake-alt-slash::before {
+ content: "\e05f"; }
+
+.fa-mattress-pillow::before {
+ content: "\e525"; }
+
+.fa-guarani-sign::before {
+ content: "\e19a"; }
+
+.fa-arrows-rotate::before {
+ content: "\f021"; }
+
+.fa-refresh::before {
+ content: "\f021"; }
+
+.fa-sync::before {
+ content: "\f021"; }
+
+.fa-fire-extinguisher::before {
+ content: "\f134"; }
+
+.fa-cruzeiro-sign::before {
+ content: "\e152"; }
+
+.fa-greater-than-equal::before {
+ content: "\f532"; }
+
+.fa-shield-halved::before {
+ content: "\f3ed"; }
+
+.fa-shield-alt::before {
+ content: "\f3ed"; }
+
+.fa-book-atlas::before {
+ content: "\f558"; }
+
+.fa-atlas::before {
+ content: "\f558"; }
+
+.fa-virus::before {
+ content: "\e074"; }
+
+.fa-envelope-circle-check::before {
+ content: "\e4e8"; }
+
+.fa-layer-group::before {
+ content: "\f5fd"; }
+
+.fa-arrows-to-dot::before {
+ content: "\e4be"; }
+
+.fa-archway::before {
+ content: "\f557"; }
+
+.fa-heart-circle-check::before {
+ content: "\e4fd"; }
+
+.fa-house-chimney-crack::before {
+ content: "\f6f1"; }
+
+.fa-house-damage::before {
+ content: "\f6f1"; }
+
+.fa-file-zipper::before {
+ content: "\f1c6"; }
+
+.fa-file-archive::before {
+ content: "\f1c6"; }
+
+.fa-square::before {
+ content: "\f0c8"; }
+
+.fa-martini-glass-empty::before {
+ content: "\f000"; }
+
+.fa-glass-martini::before {
+ content: "\f000"; }
+
+.fa-couch::before {
+ content: "\f4b8"; }
+
+.fa-cedi-sign::before {
+ content: "\e0df"; }
+
+.fa-italic::before {
+ content: "\f033"; }
+
+.fa-church::before {
+ content: "\f51d"; }
+
+.fa-comments-dollar::before {
+ content: "\f653"; }
+
+.fa-democrat::before {
+ content: "\f747"; }
+
+.fa-z::before {
+ content: "\5a"; }
+
+.fa-person-skiing::before {
+ content: "\f7c9"; }
+
+.fa-skiing::before {
+ content: "\f7c9"; }
+
+.fa-road-lock::before {
+ content: "\e567"; }
+
+.fa-a::before {
+ content: "\41"; }
+
+.fa-temperature-arrow-down::before {
+ content: "\e03f"; }
+
+.fa-temperature-down::before {
+ content: "\e03f"; }
+
+.fa-feather-pointed::before {
+ content: "\f56b"; }
+
+.fa-feather-alt::before {
+ content: "\f56b"; }
+
+.fa-p::before {
+ content: "\50"; }
+
+.fa-snowflake::before {
+ content: "\f2dc"; }
+
+.fa-newspaper::before {
+ content: "\f1ea"; }
+
+.fa-rectangle-ad::before {
+ content: "\f641"; }
+
+.fa-ad::before {
+ content: "\f641"; }
+
+.fa-circle-arrow-right::before {
+ content: "\f0a9"; }
+
+.fa-arrow-circle-right::before {
+ content: "\f0a9"; }
+
+.fa-filter-circle-xmark::before {
+ content: "\e17b"; }
+
+.fa-locust::before {
+ content: "\e520"; }
+
+.fa-sort::before {
+ content: "\f0dc"; }
+
+.fa-unsorted::before {
+ content: "\f0dc"; }
+
+.fa-list-ol::before {
+ content: "\f0cb"; }
+
+.fa-list-1-2::before {
+ content: "\f0cb"; }
+
+.fa-list-numeric::before {
+ content: "\f0cb"; }
+
+.fa-person-dress-burst::before {
+ content: "\e544"; }
+
+.fa-money-check-dollar::before {
+ content: "\f53d"; }
+
+.fa-money-check-alt::before {
+ content: "\f53d"; }
+
+.fa-vector-square::before {
+ content: "\f5cb"; }
+
+.fa-bread-slice::before {
+ content: "\f7ec"; }
+
+.fa-language::before {
+ content: "\f1ab"; }
+
+.fa-face-kiss-wink-heart::before {
+ content: "\f598"; }
+
+.fa-kiss-wink-heart::before {
+ content: "\f598"; }
+
+.fa-filter::before {
+ content: "\f0b0"; }
+
+.fa-question::before {
+ content: "\3f"; }
+
+.fa-file-signature::before {
+ content: "\f573"; }
+
+.fa-up-down-left-right::before {
+ content: "\f0b2"; }
+
+.fa-arrows-alt::before {
+ content: "\f0b2"; }
+
+.fa-house-chimney-user::before {
+ content: "\e065"; }
+
+.fa-hand-holding-heart::before {
+ content: "\f4be"; }
+
+.fa-puzzle-piece::before {
+ content: "\f12e"; }
+
+.fa-money-check::before {
+ content: "\f53c"; }
+
+.fa-star-half-stroke::before {
+ content: "\f5c0"; }
+
+.fa-star-half-alt::before {
+ content: "\f5c0"; }
+
+.fa-code::before {
+ content: "\f121"; }
+
+.fa-whiskey-glass::before {
+ content: "\f7a0"; }
+
+.fa-glass-whiskey::before {
+ content: "\f7a0"; }
+
+.fa-building-circle-exclamation::before {
+ content: "\e4d3"; }
+
+.fa-magnifying-glass-chart::before {
+ content: "\e522"; }
+
+.fa-arrow-up-right-from-square::before {
+ content: "\f08e"; }
+
+.fa-external-link::before {
+ content: "\f08e"; }
+
+.fa-cubes-stacked::before {
+ content: "\e4e6"; }
+
+.fa-won-sign::before {
+ content: "\f159"; }
+
+.fa-krw::before {
+ content: "\f159"; }
+
+.fa-won::before {
+ content: "\f159"; }
+
+.fa-virus-covid::before {
+ content: "\e4a8"; }
+
+.fa-austral-sign::before {
+ content: "\e0a9"; }
+
+.fa-f::before {
+ content: "\46"; }
+
+.fa-leaf::before {
+ content: "\f06c"; }
+
+.fa-road::before {
+ content: "\f018"; }
+
+.fa-taxi::before {
+ content: "\f1ba"; }
+
+.fa-cab::before {
+ content: "\f1ba"; }
+
+.fa-person-circle-plus::before {
+ content: "\e541"; }
+
+.fa-chart-pie::before {
+ content: "\f200"; }
+
+.fa-pie-chart::before {
+ content: "\f200"; }
+
+.fa-bolt-lightning::before {
+ content: "\e0b7"; }
+
+.fa-sack-xmark::before {
+ content: "\e56a"; }
+
+.fa-file-excel::before {
+ content: "\f1c3"; }
+
+.fa-file-contract::before {
+ content: "\f56c"; }
+
+.fa-fish-fins::before {
+ content: "\e4f2"; }
+
+.fa-building-flag::before {
+ content: "\e4d5"; }
+
+.fa-face-grin-beam::before {
+ content: "\f582"; }
+
+.fa-grin-beam::before {
+ content: "\f582"; }
+
+.fa-object-ungroup::before {
+ content: "\f248"; }
+
+.fa-poop::before {
+ content: "\f619"; }
+
+.fa-location-pin::before {
+ content: "\f041"; }
+
+.fa-map-marker::before {
+ content: "\f041"; }
+
+.fa-kaaba::before {
+ content: "\f66b"; }
+
+.fa-toilet-paper::before {
+ content: "\f71e"; }
+
+.fa-helmet-safety::before {
+ content: "\f807"; }
+
+.fa-hard-hat::before {
+ content: "\f807"; }
+
+.fa-hat-hard::before {
+ content: "\f807"; }
+
+.fa-eject::before {
+ content: "\f052"; }
+
+.fa-circle-right::before {
+ content: "\f35a"; }
+
+.fa-arrow-alt-circle-right::before {
+ content: "\f35a"; }
+
+.fa-plane-circle-check::before {
+ content: "\e555"; }
+
+.fa-face-rolling-eyes::before {
+ content: "\f5a5"; }
+
+.fa-meh-rolling-eyes::before {
+ content: "\f5a5"; }
+
+.fa-object-group::before {
+ content: "\f247"; }
+
+.fa-chart-line::before {
+ content: "\f201"; }
+
+.fa-line-chart::before {
+ content: "\f201"; }
+
+.fa-mask-ventilator::before {
+ content: "\e524"; }
+
+.fa-arrow-right::before {
+ content: "\f061"; }
+
+.fa-signs-post::before {
+ content: "\f277"; }
+
+.fa-map-signs::before {
+ content: "\f277"; }
+
+.fa-cash-register::before {
+ content: "\f788"; }
+
+.fa-person-circle-question::before {
+ content: "\e542"; }
+
+.fa-h::before {
+ content: "\48"; }
+
+.fa-tarp::before {
+ content: "\e57b"; }
+
+.fa-screwdriver-wrench::before {
+ content: "\f7d9"; }
+
+.fa-tools::before {
+ content: "\f7d9"; }
+
+.fa-arrows-to-eye::before {
+ content: "\e4bf"; }
+
+.fa-plug-circle-bolt::before {
+ content: "\e55b"; }
+
+.fa-heart::before {
+ content: "\f004"; }
+
+.fa-mars-and-venus::before {
+ content: "\f224"; }
+
+.fa-house-user::before {
+ content: "\e1b0"; }
+
+.fa-home-user::before {
+ content: "\e1b0"; }
+
+.fa-dumpster-fire::before {
+ content: "\f794"; }
+
+.fa-house-crack::before {
+ content: "\e3b1"; }
+
+.fa-martini-glass-citrus::before {
+ content: "\f561"; }
+
+.fa-cocktail::before {
+ content: "\f561"; }
+
+.fa-face-surprise::before {
+ content: "\f5c2"; }
+
+.fa-surprise::before {
+ content: "\f5c2"; }
+
+.fa-bottle-water::before {
+ content: "\e4c5"; }
+
+.fa-circle-pause::before {
+ content: "\f28b"; }
+
+.fa-pause-circle::before {
+ content: "\f28b"; }
+
+.fa-toilet-paper-slash::before {
+ content: "\e072"; }
+
+.fa-apple-whole::before {
+ content: "\f5d1"; }
+
+.fa-apple-alt::before {
+ content: "\f5d1"; }
+
+.fa-kitchen-set::before {
+ content: "\e51a"; }
+
+.fa-r::before {
+ content: "\52"; }
+
+.fa-temperature-quarter::before {
+ content: "\f2ca"; }
+
+.fa-temperature-1::before {
+ content: "\f2ca"; }
+
+.fa-thermometer-1::before {
+ content: "\f2ca"; }
+
+.fa-thermometer-quarter::before {
+ content: "\f2ca"; }
+
+.fa-cube::before {
+ content: "\f1b2"; }
+
+.fa-bitcoin-sign::before {
+ content: "\e0b4"; }
+
+.fa-shield-dog::before {
+ content: "\e573"; }
+
+.fa-solar-panel::before {
+ content: "\f5ba"; }
+
+.fa-lock-open::before {
+ content: "\f3c1"; }
+
+.fa-elevator::before {
+ content: "\e16d"; }
+
+.fa-money-bill-transfer::before {
+ content: "\e528"; }
+
+.fa-money-bill-trend-up::before {
+ content: "\e529"; }
+
+.fa-house-flood-water-circle-arrow-right::before {
+ content: "\e50f"; }
+
+.fa-square-poll-horizontal::before {
+ content: "\f682"; }
+
+.fa-poll-h::before {
+ content: "\f682"; }
+
+.fa-circle::before {
+ content: "\f111"; }
+
+.fa-backward-fast::before {
+ content: "\f049"; }
+
+.fa-fast-backward::before {
+ content: "\f049"; }
+
+.fa-recycle::before {
+ content: "\f1b8"; }
+
+.fa-user-astronaut::before {
+ content: "\f4fb"; }
+
+.fa-plane-slash::before {
+ content: "\e069"; }
+
+.fa-trademark::before {
+ content: "\f25c"; }
+
+.fa-basketball::before {
+ content: "\f434"; }
+
+.fa-basketball-ball::before {
+ content: "\f434"; }
+
+.fa-satellite-dish::before {
+ content: "\f7c0"; }
+
+.fa-circle-up::before {
+ content: "\f35b"; }
+
+.fa-arrow-alt-circle-up::before {
+ content: "\f35b"; }
+
+.fa-mobile-screen-button::before {
+ content: "\f3cd"; }
+
+.fa-mobile-alt::before {
+ content: "\f3cd"; }
+
+.fa-volume-high::before {
+ content: "\f028"; }
+
+.fa-volume-up::before {
+ content: "\f028"; }
+
+.fa-users-rays::before {
+ content: "\e593"; }
+
+.fa-wallet::before {
+ content: "\f555"; }
+
+.fa-clipboard-check::before {
+ content: "\f46c"; }
+
+.fa-file-audio::before {
+ content: "\f1c7"; }
+
+.fa-burger::before {
+ content: "\f805"; }
+
+.fa-hamburger::before {
+ content: "\f805"; }
+
+.fa-wrench::before {
+ content: "\f0ad"; }
+
+.fa-bugs::before {
+ content: "\e4d0"; }
+
+.fa-rupee-sign::before {
+ content: "\f156"; }
+
+.fa-rupee::before {
+ content: "\f156"; }
+
+.fa-file-image::before {
+ content: "\f1c5"; }
+
+.fa-circle-question::before {
+ content: "\f059"; }
+
+.fa-question-circle::before {
+ content: "\f059"; }
+
+.fa-plane-departure::before {
+ content: "\f5b0"; }
+
+.fa-handshake-slash::before {
+ content: "\e060"; }
+
+.fa-book-bookmark::before {
+ content: "\e0bb"; }
+
+.fa-code-branch::before {
+ content: "\f126"; }
+
+.fa-hat-cowboy::before {
+ content: "\f8c0"; }
+
+.fa-bridge::before {
+ content: "\e4c8"; }
+
+.fa-phone-flip::before {
+ content: "\f879"; }
+
+.fa-phone-alt::before {
+ content: "\f879"; }
+
+.fa-truck-front::before {
+ content: "\e2b7"; }
+
+.fa-cat::before {
+ content: "\f6be"; }
+
+.fa-anchor-circle-exclamation::before {
+ content: "\e4ab"; }
+
+.fa-truck-field::before {
+ content: "\e58d"; }
+
+.fa-route::before {
+ content: "\f4d7"; }
+
+.fa-clipboard-question::before {
+ content: "\e4e3"; }
+
+.fa-panorama::before {
+ content: "\e209"; }
+
+.fa-comment-medical::before {
+ content: "\f7f5"; }
+
+.fa-teeth-open::before {
+ content: "\f62f"; }
+
+.fa-file-circle-minus::before {
+ content: "\e4ed"; }
+
+.fa-tags::before {
+ content: "\f02c"; }
+
+.fa-wine-glass::before {
+ content: "\f4e3"; }
+
+.fa-forward-fast::before {
+ content: "\f050"; }
+
+.fa-fast-forward::before {
+ content: "\f050"; }
+
+.fa-face-meh-blank::before {
+ content: "\f5a4"; }
+
+.fa-meh-blank::before {
+ content: "\f5a4"; }
+
+.fa-square-parking::before {
+ content: "\f540"; }
+
+.fa-parking::before {
+ content: "\f540"; }
+
+.fa-house-signal::before {
+ content: "\e012"; }
+
+.fa-bars-progress::before {
+ content: "\f828"; }
+
+.fa-tasks-alt::before {
+ content: "\f828"; }
+
+.fa-faucet-drip::before {
+ content: "\e006"; }
+
+.fa-cart-flatbed::before {
+ content: "\f474"; }
+
+.fa-dolly-flatbed::before {
+ content: "\f474"; }
+
+.fa-ban-smoking::before {
+ content: "\f54d"; }
+
+.fa-smoking-ban::before {
+ content: "\f54d"; }
+
+.fa-terminal::before {
+ content: "\f120"; }
+
+.fa-mobile-button::before {
+ content: "\f10b"; }
+
+.fa-house-medical-flag::before {
+ content: "\e514"; }
+
+.fa-basket-shopping::before {
+ content: "\f291"; }
+
+.fa-shopping-basket::before {
+ content: "\f291"; }
+
+.fa-tape::before {
+ content: "\f4db"; }
+
+.fa-bus-simple::before {
+ content: "\f55e"; }
+
+.fa-bus-alt::before {
+ content: "\f55e"; }
+
+.fa-eye::before {
+ content: "\f06e"; }
+
+.fa-face-sad-cry::before {
+ content: "\f5b3"; }
+
+.fa-sad-cry::before {
+ content: "\f5b3"; }
+
+.fa-audio-description::before {
+ content: "\f29e"; }
+
+.fa-person-military-to-person::before {
+ content: "\e54c"; }
+
+.fa-file-shield::before {
+ content: "\e4f0"; }
+
+.fa-user-slash::before {
+ content: "\f506"; }
+
+.fa-pen::before {
+ content: "\f304"; }
+
+.fa-tower-observation::before {
+ content: "\e586"; }
+
+.fa-file-code::before {
+ content: "\f1c9"; }
+
+.fa-signal::before {
+ content: "\f012"; }
+
+.fa-signal-5::before {
+ content: "\f012"; }
+
+.fa-signal-perfect::before {
+ content: "\f012"; }
+
+.fa-bus::before {
+ content: "\f207"; }
+
+.fa-heart-circle-xmark::before {
+ content: "\e501"; }
+
+.fa-house-chimney::before {
+ content: "\e3af"; }
+
+.fa-home-lg::before {
+ content: "\e3af"; }
+
+.fa-window-maximize::before {
+ content: "\f2d0"; }
+
+.fa-face-frown::before {
+ content: "\f119"; }
+
+.fa-frown::before {
+ content: "\f119"; }
+
+.fa-prescription::before {
+ content: "\f5b1"; }
+
+.fa-shop::before {
+ content: "\f54f"; }
+
+.fa-store-alt::before {
+ content: "\f54f"; }
+
+.fa-floppy-disk::before {
+ content: "\f0c7"; }
+
+.fa-save::before {
+ content: "\f0c7"; }
+
+.fa-vihara::before {
+ content: "\f6a7"; }
+
+.fa-scale-unbalanced::before {
+ content: "\f515"; }
+
+.fa-balance-scale-left::before {
+ content: "\f515"; }
+
+.fa-sort-up::before {
+ content: "\f0de"; }
+
+.fa-sort-asc::before {
+ content: "\f0de"; }
+
+.fa-comment-dots::before {
+ content: "\f4ad"; }
+
+.fa-commenting::before {
+ content: "\f4ad"; }
+
+.fa-plant-wilt::before {
+ content: "\e5aa"; }
+
+.fa-diamond::before {
+ content: "\f219"; }
+
+.fa-face-grin-squint::before {
+ content: "\f585"; }
+
+.fa-grin-squint::before {
+ content: "\f585"; }
+
+.fa-hand-holding-dollar::before {
+ content: "\f4c0"; }
+
+.fa-hand-holding-usd::before {
+ content: "\f4c0"; }
+
+.fa-bacterium::before {
+ content: "\e05a"; }
+
+.fa-hand-pointer::before {
+ content: "\f25a"; }
+
+.fa-drum-steelpan::before {
+ content: "\f56a"; }
+
+.fa-hand-scissors::before {
+ content: "\f257"; }
+
+.fa-hands-praying::before {
+ content: "\f684"; }
+
+.fa-praying-hands::before {
+ content: "\f684"; }
+
+.fa-arrow-rotate-right::before {
+ content: "\f01e"; }
+
+.fa-arrow-right-rotate::before {
+ content: "\f01e"; }
+
+.fa-arrow-rotate-forward::before {
+ content: "\f01e"; }
+
+.fa-redo::before {
+ content: "\f01e"; }
+
+.fa-biohazard::before {
+ content: "\f780"; }
+
+.fa-location-crosshairs::before {
+ content: "\f601"; }
+
+.fa-location::before {
+ content: "\f601"; }
+
+.fa-mars-double::before {
+ content: "\f227"; }
+
+.fa-child-dress::before {
+ content: "\e59c"; }
+
+.fa-users-between-lines::before {
+ content: "\e591"; }
+
+.fa-lungs-virus::before {
+ content: "\e067"; }
+
+.fa-face-grin-tears::before {
+ content: "\f588"; }
+
+.fa-grin-tears::before {
+ content: "\f588"; }
+
+.fa-phone::before {
+ content: "\f095"; }
+
+.fa-calendar-xmark::before {
+ content: "\f273"; }
+
+.fa-calendar-times::before {
+ content: "\f273"; }
+
+.fa-child-reaching::before {
+ content: "\e59d"; }
+
+.fa-head-side-virus::before {
+ content: "\e064"; }
+
+.fa-user-gear::before {
+ content: "\f4fe"; }
+
+.fa-user-cog::before {
+ content: "\f4fe"; }
+
+.fa-arrow-up-1-9::before {
+ content: "\f163"; }
+
+.fa-sort-numeric-up::before {
+ content: "\f163"; }
+
+.fa-door-closed::before {
+ content: "\f52a"; }
+
+.fa-shield-virus::before {
+ content: "\e06c"; }
+
+.fa-dice-six::before {
+ content: "\f526"; }
+
+.fa-mosquito-net::before {
+ content: "\e52c"; }
+
+.fa-bridge-water::before {
+ content: "\e4ce"; }
+
+.fa-person-booth::before {
+ content: "\f756"; }
+
+.fa-text-width::before {
+ content: "\f035"; }
+
+.fa-hat-wizard::before {
+ content: "\f6e8"; }
+
+.fa-pen-fancy::before {
+ content: "\f5ac"; }
+
+.fa-person-digging::before {
+ content: "\f85e"; }
+
+.fa-digging::before {
+ content: "\f85e"; }
+
+.fa-trash::before {
+ content: "\f1f8"; }
+
+.fa-gauge-simple::before {
+ content: "\f629"; }
+
+.fa-gauge-simple-med::before {
+ content: "\f629"; }
+
+.fa-tachometer-average::before {
+ content: "\f629"; }
+
+.fa-book-medical::before {
+ content: "\f7e6"; }
+
+.fa-poo::before {
+ content: "\f2fe"; }
+
+.fa-quote-right::before {
+ content: "\f10e"; }
+
+.fa-quote-right-alt::before {
+ content: "\f10e"; }
+
+.fa-shirt::before {
+ content: "\f553"; }
+
+.fa-t-shirt::before {
+ content: "\f553"; }
+
+.fa-tshirt::before {
+ content: "\f553"; }
+
+.fa-cubes::before {
+ content: "\f1b3"; }
+
+.fa-divide::before {
+ content: "\f529"; }
+
+.fa-tenge-sign::before {
+ content: "\f7d7"; }
+
+.fa-tenge::before {
+ content: "\f7d7"; }
+
+.fa-headphones::before {
+ content: "\f025"; }
+
+.fa-hands-holding::before {
+ content: "\f4c2"; }
+
+.fa-hands-clapping::before {
+ content: "\e1a8"; }
+
+.fa-republican::before {
+ content: "\f75e"; }
+
+.fa-arrow-left::before {
+ content: "\f060"; }
+
+.fa-person-circle-xmark::before {
+ content: "\e543"; }
+
+.fa-ruler::before {
+ content: "\f545"; }
+
+.fa-align-left::before {
+ content: "\f036"; }
+
+.fa-dice-d6::before {
+ content: "\f6d1"; }
+
+.fa-restroom::before {
+ content: "\f7bd"; }
+
+.fa-j::before {
+ content: "\4a"; }
+
+.fa-users-viewfinder::before {
+ content: "\e595"; }
+
+.fa-file-video::before {
+ content: "\f1c8"; }
+
+.fa-up-right-from-square::before {
+ content: "\f35d"; }
+
+.fa-external-link-alt::before {
+ content: "\f35d"; }
+
+.fa-table-cells::before {
+ content: "\f00a"; }
+
+.fa-th::before {
+ content: "\f00a"; }
+
+.fa-file-pdf::before {
+ content: "\f1c1"; }
+
+.fa-book-bible::before {
+ content: "\f647"; }
+
+.fa-bible::before {
+ content: "\f647"; }
+
+.fa-o::before {
+ content: "\4f"; }
+
+.fa-suitcase-medical::before {
+ content: "\f0fa"; }
+
+.fa-medkit::before {
+ content: "\f0fa"; }
+
+.fa-user-secret::before {
+ content: "\f21b"; }
+
+.fa-otter::before {
+ content: "\f700"; }
+
+.fa-person-dress::before {
+ content: "\f182"; }
+
+.fa-female::before {
+ content: "\f182"; }
+
+.fa-comment-dollar::before {
+ content: "\f651"; }
+
+.fa-business-time::before {
+ content: "\f64a"; }
+
+.fa-briefcase-clock::before {
+ content: "\f64a"; }
+
+.fa-table-cells-large::before {
+ content: "\f009"; }
+
+.fa-th-large::before {
+ content: "\f009"; }
+
+.fa-book-tanakh::before {
+ content: "\f827"; }
+
+.fa-tanakh::before {
+ content: "\f827"; }
+
+.fa-phone-volume::before {
+ content: "\f2a0"; }
+
+.fa-volume-control-phone::before {
+ content: "\f2a0"; }
+
+.fa-hat-cowboy-side::before {
+ content: "\f8c1"; }
+
+.fa-clipboard-user::before {
+ content: "\f7f3"; }
+
+.fa-child::before {
+ content: "\f1ae"; }
+
+.fa-lira-sign::before {
+ content: "\f195"; }
+
+.fa-satellite::before {
+ content: "\f7bf"; }
+
+.fa-plane-lock::before {
+ content: "\e558"; }
+
+.fa-tag::before {
+ content: "\f02b"; }
+
+.fa-comment::before {
+ content: "\f075"; }
+
+.fa-cake-candles::before {
+ content: "\f1fd"; }
+
+.fa-birthday-cake::before {
+ content: "\f1fd"; }
+
+.fa-cake::before {
+ content: "\f1fd"; }
+
+.fa-envelope::before {
+ content: "\f0e0"; }
+
+.fa-angles-up::before {
+ content: "\f102"; }
+
+.fa-angle-double-up::before {
+ content: "\f102"; }
+
+.fa-paperclip::before {
+ content: "\f0c6"; }
+
+.fa-arrow-right-to-city::before {
+ content: "\e4b3"; }
+
+.fa-ribbon::before {
+ content: "\f4d6"; }
+
+.fa-lungs::before {
+ content: "\f604"; }
+
+.fa-arrow-up-9-1::before {
+ content: "\f887"; }
+
+.fa-sort-numeric-up-alt::before {
+ content: "\f887"; }
+
+.fa-litecoin-sign::before {
+ content: "\e1d3"; }
+
+.fa-border-none::before {
+ content: "\f850"; }
+
+.fa-circle-nodes::before {
+ content: "\e4e2"; }
+
+.fa-parachute-box::before {
+ content: "\f4cd"; }
+
+.fa-indent::before {
+ content: "\f03c"; }
+
+.fa-truck-field-un::before {
+ content: "\e58e"; }
+
+.fa-hourglass::before {
+ content: "\f254"; }
+
+.fa-hourglass-empty::before {
+ content: "\f254"; }
+
+.fa-mountain::before {
+ content: "\f6fc"; }
+
+.fa-user-doctor::before {
+ content: "\f0f0"; }
+
+.fa-user-md::before {
+ content: "\f0f0"; }
+
+.fa-circle-info::before {
+ content: "\f05a"; }
+
+.fa-info-circle::before {
+ content: "\f05a"; }
+
+.fa-cloud-meatball::before {
+ content: "\f73b"; }
+
+.fa-camera::before {
+ content: "\f030"; }
+
+.fa-camera-alt::before {
+ content: "\f030"; }
+
+.fa-square-virus::before {
+ content: "\e578"; }
+
+.fa-meteor::before {
+ content: "\f753"; }
+
+.fa-car-on::before {
+ content: "\e4dd"; }
+
+.fa-sleigh::before {
+ content: "\f7cc"; }
+
+.fa-arrow-down-1-9::before {
+ content: "\f162"; }
+
+.fa-sort-numeric-asc::before {
+ content: "\f162"; }
+
+.fa-sort-numeric-down::before {
+ content: "\f162"; }
+
+.fa-hand-holding-droplet::before {
+ content: "\f4c1"; }
+
+.fa-hand-holding-water::before {
+ content: "\f4c1"; }
+
+.fa-water::before {
+ content: "\f773"; }
+
+.fa-calendar-check::before {
+ content: "\f274"; }
+
+.fa-braille::before {
+ content: "\f2a1"; }
+
+.fa-prescription-bottle-medical::before {
+ content: "\f486"; }
+
+.fa-prescription-bottle-alt::before {
+ content: "\f486"; }
+
+.fa-landmark::before {
+ content: "\f66f"; }
+
+.fa-truck::before {
+ content: "\f0d1"; }
+
+.fa-crosshairs::before {
+ content: "\f05b"; }
+
+.fa-person-cane::before {
+ content: "\e53c"; }
+
+.fa-tent::before {
+ content: "\e57d"; }
+
+.fa-vest-patches::before {
+ content: "\e086"; }
+
+.fa-check-double::before {
+ content: "\f560"; }
+
+.fa-arrow-down-a-z::before {
+ content: "\f15d"; }
+
+.fa-sort-alpha-asc::before {
+ content: "\f15d"; }
+
+.fa-sort-alpha-down::before {
+ content: "\f15d"; }
+
+.fa-money-bill-wheat::before {
+ content: "\e52a"; }
+
+.fa-cookie::before {
+ content: "\f563"; }
+
+.fa-arrow-rotate-left::before {
+ content: "\f0e2"; }
+
+.fa-arrow-left-rotate::before {
+ content: "\f0e2"; }
+
+.fa-arrow-rotate-back::before {
+ content: "\f0e2"; }
+
+.fa-arrow-rotate-backward::before {
+ content: "\f0e2"; }
+
+.fa-undo::before {
+ content: "\f0e2"; }
+
+.fa-hard-drive::before {
+ content: "\f0a0"; }
+
+.fa-hdd::before {
+ content: "\f0a0"; }
+
+.fa-face-grin-squint-tears::before {
+ content: "\f586"; }
+
+.fa-grin-squint-tears::before {
+ content: "\f586"; }
+
+.fa-dumbbell::before {
+ content: "\f44b"; }
+
+.fa-rectangle-list::before {
+ content: "\f022"; }
+
+.fa-list-alt::before {
+ content: "\f022"; }
+
+.fa-tarp-droplet::before {
+ content: "\e57c"; }
+
+.fa-house-medical-circle-check::before {
+ content: "\e511"; }
+
+.fa-person-skiing-nordic::before {
+ content: "\f7ca"; }
+
+.fa-skiing-nordic::before {
+ content: "\f7ca"; }
+
+.fa-calendar-plus::before {
+ content: "\f271"; }
+
+.fa-plane-arrival::before {
+ content: "\f5af"; }
+
+.fa-circle-left::before {
+ content: "\f359"; }
+
+.fa-arrow-alt-circle-left::before {
+ content: "\f359"; }
+
+.fa-train-subway::before {
+ content: "\f239"; }
+
+.fa-subway::before {
+ content: "\f239"; }
+
+.fa-chart-gantt::before {
+ content: "\e0e4"; }
+
+.fa-indian-rupee-sign::before {
+ content: "\e1bc"; }
+
+.fa-indian-rupee::before {
+ content: "\e1bc"; }
+
+.fa-inr::before {
+ content: "\e1bc"; }
+
+.fa-crop-simple::before {
+ content: "\f565"; }
+
+.fa-crop-alt::before {
+ content: "\f565"; }
+
+.fa-money-bill-1::before {
+ content: "\f3d1"; }
+
+.fa-money-bill-alt::before {
+ content: "\f3d1"; }
+
+.fa-left-long::before {
+ content: "\f30a"; }
+
+.fa-long-arrow-alt-left::before {
+ content: "\f30a"; }
+
+.fa-dna::before {
+ content: "\f471"; }
+
+.fa-virus-slash::before {
+ content: "\e075"; }
+
+.fa-minus::before {
+ content: "\f068"; }
+
+.fa-subtract::before {
+ content: "\f068"; }
+
+.fa-chess::before {
+ content: "\f439"; }
+
+.fa-arrow-left-long::before {
+ content: "\f177"; }
+
+.fa-long-arrow-left::before {
+ content: "\f177"; }
+
+.fa-plug-circle-check::before {
+ content: "\e55c"; }
+
+.fa-street-view::before {
+ content: "\f21d"; }
+
+.fa-franc-sign::before {
+ content: "\e18f"; }
+
+.fa-volume-off::before {
+ content: "\f026"; }
+
+.fa-hands-asl-interpreting::before {
+ content: "\f2a3"; }
+
+.fa-american-sign-language-interpreting::before {
+ content: "\f2a3"; }
+
+.fa-asl-interpreting::before {
+ content: "\f2a3"; }
+
+.fa-hands-american-sign-language-interpreting::before {
+ content: "\f2a3"; }
+
+.fa-gear::before {
+ content: "\f013"; }
+
+.fa-cog::before {
+ content: "\f013"; }
+
+.fa-droplet-slash::before {
+ content: "\f5c7"; }
+
+.fa-tint-slash::before {
+ content: "\f5c7"; }
+
+.fa-mosque::before {
+ content: "\f678"; }
+
+.fa-mosquito::before {
+ content: "\e52b"; }
+
+.fa-star-of-david::before {
+ content: "\f69a"; }
+
+.fa-person-military-rifle::before {
+ content: "\e54b"; }
+
+.fa-cart-shopping::before {
+ content: "\f07a"; }
+
+.fa-shopping-cart::before {
+ content: "\f07a"; }
+
+.fa-vials::before {
+ content: "\f493"; }
+
+.fa-plug-circle-plus::before {
+ content: "\e55f"; }
+
+.fa-place-of-worship::before {
+ content: "\f67f"; }
+
+.fa-grip-vertical::before {
+ content: "\f58e"; }
+
+.fa-arrow-turn-up::before {
+ content: "\f148"; }
+
+.fa-level-up::before {
+ content: "\f148"; }
+
+.fa-u::before {
+ content: "\55"; }
+
+.fa-square-root-variable::before {
+ content: "\f698"; }
+
+.fa-square-root-alt::before {
+ content: "\f698"; }
+
+.fa-clock::before {
+ content: "\f017"; }
+
+.fa-clock-four::before {
+ content: "\f017"; }
+
+.fa-backward-step::before {
+ content: "\f048"; }
+
+.fa-step-backward::before {
+ content: "\f048"; }
+
+.fa-pallet::before {
+ content: "\f482"; }
+
+.fa-faucet::before {
+ content: "\e005"; }
+
+.fa-baseball-bat-ball::before {
+ content: "\f432"; }
+
+.fa-s::before {
+ content: "\53"; }
+
+.fa-timeline::before {
+ content: "\e29c"; }
+
+.fa-keyboard::before {
+ content: "\f11c"; }
+
+.fa-caret-down::before {
+ content: "\f0d7"; }
+
+.fa-house-chimney-medical::before {
+ content: "\f7f2"; }
+
+.fa-clinic-medical::before {
+ content: "\f7f2"; }
+
+.fa-temperature-three-quarters::before {
+ content: "\f2c8"; }
+
+.fa-temperature-3::before {
+ content: "\f2c8"; }
+
+.fa-thermometer-3::before {
+ content: "\f2c8"; }
+
+.fa-thermometer-three-quarters::before {
+ content: "\f2c8"; }
+
+.fa-mobile-screen::before {
+ content: "\f3cf"; }
+
+.fa-mobile-android-alt::before {
+ content: "\f3cf"; }
+
+.fa-plane-up::before {
+ content: "\e22d"; }
+
+.fa-piggy-bank::before {
+ content: "\f4d3"; }
+
+.fa-battery-half::before {
+ content: "\f242"; }
+
+.fa-battery-3::before {
+ content: "\f242"; }
+
+.fa-mountain-city::before {
+ content: "\e52e"; }
+
+.fa-coins::before {
+ content: "\f51e"; }
+
+.fa-khanda::before {
+ content: "\f66d"; }
+
+.fa-sliders::before {
+ content: "\f1de"; }
+
+.fa-sliders-h::before {
+ content: "\f1de"; }
+
+.fa-folder-tree::before {
+ content: "\f802"; }
+
+.fa-network-wired::before {
+ content: "\f6ff"; }
+
+.fa-map-pin::before {
+ content: "\f276"; }
+
+.fa-hamsa::before {
+ content: "\f665"; }
+
+.fa-cent-sign::before {
+ content: "\e3f5"; }
+
+.fa-flask::before {
+ content: "\f0c3"; }
+
+.fa-person-pregnant::before {
+ content: "\e31e"; }
+
+.fa-wand-sparkles::before {
+ content: "\f72b"; }
+
+.fa-ellipsis-vertical::before {
+ content: "\f142"; }
+
+.fa-ellipsis-v::before {
+ content: "\f142"; }
+
+.fa-ticket::before {
+ content: "\f145"; }
+
+.fa-power-off::before {
+ content: "\f011"; }
+
+.fa-right-long::before {
+ content: "\f30b"; }
+
+.fa-long-arrow-alt-right::before {
+ content: "\f30b"; }
+
+.fa-flag-usa::before {
+ content: "\f74d"; }
+
+.fa-laptop-file::before {
+ content: "\e51d"; }
+
+.fa-tty::before {
+ content: "\f1e4"; }
+
+.fa-teletype::before {
+ content: "\f1e4"; }
+
+.fa-diagram-next::before {
+ content: "\e476"; }
+
+.fa-person-rifle::before {
+ content: "\e54e"; }
+
+.fa-house-medical-circle-exclamation::before {
+ content: "\e512"; }
+
+.fa-closed-captioning::before {
+ content: "\f20a"; }
+
+.fa-person-hiking::before {
+ content: "\f6ec"; }
+
+.fa-hiking::before {
+ content: "\f6ec"; }
+
+.fa-venus-double::before {
+ content: "\f226"; }
+
+.fa-images::before {
+ content: "\f302"; }
+
+.fa-calculator::before {
+ content: "\f1ec"; }
+
+.fa-people-pulling::before {
+ content: "\e535"; }
+
+.fa-n::before {
+ content: "\4e"; }
+
+.fa-cable-car::before {
+ content: "\f7da"; }
+
+.fa-tram::before {
+ content: "\f7da"; }
+
+.fa-cloud-rain::before {
+ content: "\f73d"; }
+
+.fa-building-circle-xmark::before {
+ content: "\e4d4"; }
+
+.fa-ship::before {
+ content: "\f21a"; }
+
+.fa-arrows-down-to-line::before {
+ content: "\e4b8"; }
+
+.fa-download::before {
+ content: "\f019"; }
+
+.fa-face-grin::before {
+ content: "\f580"; }
+
+.fa-grin::before {
+ content: "\f580"; }
+
+.fa-delete-left::before {
+ content: "\f55a"; }
+
+.fa-backspace::before {
+ content: "\f55a"; }
+
+.fa-eye-dropper::before {
+ content: "\f1fb"; }
+
+.fa-eye-dropper-empty::before {
+ content: "\f1fb"; }
+
+.fa-eyedropper::before {
+ content: "\f1fb"; }
+
+.fa-file-circle-check::before {
+ content: "\e5a0"; }
+
+.fa-forward::before {
+ content: "\f04e"; }
+
+.fa-mobile::before {
+ content: "\f3ce"; }
+
+.fa-mobile-android::before {
+ content: "\f3ce"; }
+
+.fa-mobile-phone::before {
+ content: "\f3ce"; }
+
+.fa-face-meh::before {
+ content: "\f11a"; }
+
+.fa-meh::before {
+ content: "\f11a"; }
+
+.fa-align-center::before {
+ content: "\f037"; }
+
+.fa-book-skull::before {
+ content: "\f6b7"; }
+
+.fa-book-dead::before {
+ content: "\f6b7"; }
+
+.fa-id-card::before {
+ content: "\f2c2"; }
+
+.fa-drivers-license::before {
+ content: "\f2c2"; }
+
+.fa-outdent::before {
+ content: "\f03b"; }
+
+.fa-dedent::before {
+ content: "\f03b"; }
+
+.fa-heart-circle-exclamation::before {
+ content: "\e4fe"; }
+
+.fa-house::before {
+ content: "\f015"; }
+
+.fa-home::before {
+ content: "\f015"; }
+
+.fa-home-alt::before {
+ content: "\f015"; }
+
+.fa-home-lg-alt::before {
+ content: "\f015"; }
+
+.fa-calendar-week::before {
+ content: "\f784"; }
+
+.fa-laptop-medical::before {
+ content: "\f812"; }
+
+.fa-b::before {
+ content: "\42"; }
+
+.fa-file-medical::before {
+ content: "\f477"; }
+
+.fa-dice-one::before {
+ content: "\f525"; }
+
+.fa-kiwi-bird::before {
+ content: "\f535"; }
+
+.fa-arrow-right-arrow-left::before {
+ content: "\f0ec"; }
+
+.fa-exchange::before {
+ content: "\f0ec"; }
+
+.fa-rotate-right::before {
+ content: "\f2f9"; }
+
+.fa-redo-alt::before {
+ content: "\f2f9"; }
+
+.fa-rotate-forward::before {
+ content: "\f2f9"; }
+
+.fa-utensils::before {
+ content: "\f2e7"; }
+
+.fa-cutlery::before {
+ content: "\f2e7"; }
+
+.fa-arrow-up-wide-short::before {
+ content: "\f161"; }
+
+.fa-sort-amount-up::before {
+ content: "\f161"; }
+
+.fa-mill-sign::before {
+ content: "\e1ed"; }
+
+.fa-bowl-rice::before {
+ content: "\e2eb"; }
+
+.fa-skull::before {
+ content: "\f54c"; }
+
+.fa-tower-broadcast::before {
+ content: "\f519"; }
+
+.fa-broadcast-tower::before {
+ content: "\f519"; }
+
+.fa-truck-pickup::before {
+ content: "\f63c"; }
+
+.fa-up-long::before {
+ content: "\f30c"; }
+
+.fa-long-arrow-alt-up::before {
+ content: "\f30c"; }
+
+.fa-stop::before {
+ content: "\f04d"; }
+
+.fa-code-merge::before {
+ content: "\f387"; }
+
+.fa-upload::before {
+ content: "\f093"; }
+
+.fa-hurricane::before {
+ content: "\f751"; }
+
+.fa-mound::before {
+ content: "\e52d"; }
+
+.fa-toilet-portable::before {
+ content: "\e583"; }
+
+.fa-compact-disc::before {
+ content: "\f51f"; }
+
+.fa-file-arrow-down::before {
+ content: "\f56d"; }
+
+.fa-file-download::before {
+ content: "\f56d"; }
+
+.fa-caravan::before {
+ content: "\f8ff"; }
+
+.fa-shield-cat::before {
+ content: "\e572"; }
+
+.fa-bolt::before {
+ content: "\f0e7"; }
+
+.fa-zap::before {
+ content: "\f0e7"; }
+
+.fa-glass-water::before {
+ content: "\e4f4"; }
+
+.fa-oil-well::before {
+ content: "\e532"; }
+
+.fa-vault::before {
+ content: "\e2c5"; }
+
+.fa-mars::before {
+ content: "\f222"; }
+
+.fa-toilet::before {
+ content: "\f7d8"; }
+
+.fa-plane-circle-xmark::before {
+ content: "\e557"; }
+
+.fa-yen-sign::before {
+ content: "\f157"; }
+
+.fa-cny::before {
+ content: "\f157"; }
+
+.fa-jpy::before {
+ content: "\f157"; }
+
+.fa-rmb::before {
+ content: "\f157"; }
+
+.fa-yen::before {
+ content: "\f157"; }
+
+.fa-ruble-sign::before {
+ content: "\f158"; }
+
+.fa-rouble::before {
+ content: "\f158"; }
+
+.fa-rub::before {
+ content: "\f158"; }
+
+.fa-ruble::before {
+ content: "\f158"; }
+
+.fa-sun::before {
+ content: "\f185"; }
+
+.fa-guitar::before {
+ content: "\f7a6"; }
+
+.fa-face-laugh-wink::before {
+ content: "\f59c"; }
+
+.fa-laugh-wink::before {
+ content: "\f59c"; }
+
+.fa-horse-head::before {
+ content: "\f7ab"; }
+
+.fa-bore-hole::before {
+ content: "\e4c3"; }
+
+.fa-industry::before {
+ content: "\f275"; }
+
+.fa-circle-down::before {
+ content: "\f358"; }
+
+.fa-arrow-alt-circle-down::before {
+ content: "\f358"; }
+
+.fa-arrows-turn-to-dots::before {
+ content: "\e4c1"; }
+
+.fa-florin-sign::before {
+ content: "\e184"; }
+
+.fa-arrow-down-short-wide::before {
+ content: "\f884"; }
+
+.fa-sort-amount-desc::before {
+ content: "\f884"; }
+
+.fa-sort-amount-down-alt::before {
+ content: "\f884"; }
+
+.fa-less-than::before {
+ content: "\3c"; }
+
+.fa-angle-down::before {
+ content: "\f107"; }
+
+.fa-car-tunnel::before {
+ content: "\e4de"; }
+
+.fa-head-side-cough::before {
+ content: "\e061"; }
+
+.fa-grip-lines::before {
+ content: "\f7a4"; }
+
+.fa-thumbs-down::before {
+ content: "\f165"; }
+
+.fa-user-lock::before {
+ content: "\f502"; }
+
+.fa-arrow-right-long::before {
+ content: "\f178"; }
+
+.fa-long-arrow-right::before {
+ content: "\f178"; }
+
+.fa-anchor-circle-xmark::before {
+ content: "\e4ac"; }
+
+.fa-ellipsis::before {
+ content: "\f141"; }
+
+.fa-ellipsis-h::before {
+ content: "\f141"; }
+
+.fa-chess-pawn::before {
+ content: "\f443"; }
+
+.fa-kit-medical::before {
+ content: "\f479"; }
+
+.fa-first-aid::before {
+ content: "\f479"; }
+
+.fa-person-through-window::before {
+ content: "\e5a9"; }
+
+.fa-toolbox::before {
+ content: "\f552"; }
+
+.fa-hands-holding-circle::before {
+ content: "\e4fb"; }
+
+.fa-bug::before {
+ content: "\f188"; }
+
+.fa-credit-card::before {
+ content: "\f09d"; }
+
+.fa-credit-card-alt::before {
+ content: "\f09d"; }
+
+.fa-car::before {
+ content: "\f1b9"; }
+
+.fa-automobile::before {
+ content: "\f1b9"; }
+
+.fa-hand-holding-hand::before {
+ content: "\e4f7"; }
+
+.fa-book-open-reader::before {
+ content: "\f5da"; }
+
+.fa-book-reader::before {
+ content: "\f5da"; }
+
+.fa-mountain-sun::before {
+ content: "\e52f"; }
+
+.fa-arrows-left-right-to-line::before {
+ content: "\e4ba"; }
+
+.fa-dice-d20::before {
+ content: "\f6cf"; }
+
+.fa-truck-droplet::before {
+ content: "\e58c"; }
+
+.fa-file-circle-xmark::before {
+ content: "\e5a1"; }
+
+.fa-temperature-arrow-up::before {
+ content: "\e040"; }
+
+.fa-temperature-up::before {
+ content: "\e040"; }
+
+.fa-medal::before {
+ content: "\f5a2"; }
+
+.fa-bed::before {
+ content: "\f236"; }
+
+.fa-square-h::before {
+ content: "\f0fd"; }
+
+.fa-h-square::before {
+ content: "\f0fd"; }
+
+.fa-podcast::before {
+ content: "\f2ce"; }
+
+.fa-temperature-full::before {
+ content: "\f2c7"; }
+
+.fa-temperature-4::before {
+ content: "\f2c7"; }
+
+.fa-thermometer-4::before {
+ content: "\f2c7"; }
+
+.fa-thermometer-full::before {
+ content: "\f2c7"; }
+
+.fa-bell::before {
+ content: "\f0f3"; }
+
+.fa-superscript::before {
+ content: "\f12b"; }
+
+.fa-plug-circle-xmark::before {
+ content: "\e560"; }
+
+.fa-star-of-life::before {
+ content: "\f621"; }
+
+.fa-phone-slash::before {
+ content: "\f3dd"; }
+
+.fa-paint-roller::before {
+ content: "\f5aa"; }
+
+.fa-handshake-angle::before {
+ content: "\f4c4"; }
+
+.fa-hands-helping::before {
+ content: "\f4c4"; }
+
+.fa-location-dot::before {
+ content: "\f3c5"; }
+
+.fa-map-marker-alt::before {
+ content: "\f3c5"; }
+
+.fa-file::before {
+ content: "\f15b"; }
+
+.fa-greater-than::before {
+ content: "\3e"; }
+
+.fa-person-swimming::before {
+ content: "\f5c4"; }
+
+.fa-swimmer::before {
+ content: "\f5c4"; }
+
+.fa-arrow-down::before {
+ content: "\f063"; }
+
+.fa-droplet::before {
+ content: "\f043"; }
+
+.fa-tint::before {
+ content: "\f043"; }
+
+.fa-eraser::before {
+ content: "\f12d"; }
+
+.fa-earth-americas::before {
+ content: "\f57d"; }
+
+.fa-earth::before {
+ content: "\f57d"; }
+
+.fa-earth-america::before {
+ content: "\f57d"; }
+
+.fa-globe-americas::before {
+ content: "\f57d"; }
+
+.fa-person-burst::before {
+ content: "\e53b"; }
+
+.fa-dove::before {
+ content: "\f4ba"; }
+
+.fa-battery-empty::before {
+ content: "\f244"; }
+
+.fa-battery-0::before {
+ content: "\f244"; }
+
+.fa-socks::before {
+ content: "\f696"; }
+
+.fa-inbox::before {
+ content: "\f01c"; }
+
+.fa-section::before {
+ content: "\e447"; }
+
+.fa-gauge-high::before {
+ content: "\f625"; }
+
+.fa-tachometer-alt::before {
+ content: "\f625"; }
+
+.fa-tachometer-alt-fast::before {
+ content: "\f625"; }
+
+.fa-envelope-open-text::before {
+ content: "\f658"; }
+
+.fa-hospital::before {
+ content: "\f0f8"; }
+
+.fa-hospital-alt::before {
+ content: "\f0f8"; }
+
+.fa-hospital-wide::before {
+ content: "\f0f8"; }
+
+.fa-wine-bottle::before {
+ content: "\f72f"; }
+
+.fa-chess-rook::before {
+ content: "\f447"; }
+
+.fa-bars-staggered::before {
+ content: "\f550"; }
+
+.fa-reorder::before {
+ content: "\f550"; }
+
+.fa-stream::before {
+ content: "\f550"; }
+
+.fa-dharmachakra::before {
+ content: "\f655"; }
+
+.fa-hotdog::before {
+ content: "\f80f"; }
+
+.fa-person-walking-with-cane::before {
+ content: "\f29d"; }
+
+.fa-blind::before {
+ content: "\f29d"; }
+
+.fa-drum::before {
+ content: "\f569"; }
+
+.fa-ice-cream::before {
+ content: "\f810"; }
+
+.fa-heart-circle-bolt::before {
+ content: "\e4fc"; }
+
+.fa-fax::before {
+ content: "\f1ac"; }
+
+.fa-paragraph::before {
+ content: "\f1dd"; }
+
+.fa-check-to-slot::before {
+ content: "\f772"; }
+
+.fa-vote-yea::before {
+ content: "\f772"; }
+
+.fa-star-half::before {
+ content: "\f089"; }
+
+.fa-boxes-stacked::before {
+ content: "\f468"; }
+
+.fa-boxes::before {
+ content: "\f468"; }
+
+.fa-boxes-alt::before {
+ content: "\f468"; }
+
+.fa-link::before {
+ content: "\f0c1"; }
+
+.fa-chain::before {
+ content: "\f0c1"; }
+
+.fa-ear-listen::before {
+ content: "\f2a2"; }
+
+.fa-assistive-listening-systems::before {
+ content: "\f2a2"; }
+
+.fa-tree-city::before {
+ content: "\e587"; }
+
+.fa-play::before {
+ content: "\f04b"; }
+
+.fa-font::before {
+ content: "\f031"; }
+
+.fa-rupiah-sign::before {
+ content: "\e23d"; }
+
+.fa-magnifying-glass::before {
+ content: "\f002"; }
+
+.fa-search::before {
+ content: "\f002"; }
+
+.fa-table-tennis-paddle-ball::before {
+ content: "\f45d"; }
+
+.fa-ping-pong-paddle-ball::before {
+ content: "\f45d"; }
+
+.fa-table-tennis::before {
+ content: "\f45d"; }
+
+.fa-person-dots-from-line::before {
+ content: "\f470"; }
+
+.fa-diagnoses::before {
+ content: "\f470"; }
+
+.fa-trash-can-arrow-up::before {
+ content: "\f82a"; }
+
+.fa-trash-restore-alt::before {
+ content: "\f82a"; }
+
+.fa-naira-sign::before {
+ content: "\e1f6"; }
+
+.fa-cart-arrow-down::before {
+ content: "\f218"; }
+
+.fa-walkie-talkie::before {
+ content: "\f8ef"; }
+
+.fa-file-pen::before {
+ content: "\f31c"; }
+
+.fa-file-edit::before {
+ content: "\f31c"; }
+
+.fa-receipt::before {
+ content: "\f543"; }
+
+.fa-square-pen::before {
+ content: "\f14b"; }
+
+.fa-pen-square::before {
+ content: "\f14b"; }
+
+.fa-pencil-square::before {
+ content: "\f14b"; }
+
+.fa-suitcase-rolling::before {
+ content: "\f5c1"; }
+
+.fa-person-circle-exclamation::before {
+ content: "\e53f"; }
+
+.fa-chevron-down::before {
+ content: "\f078"; }
+
+.fa-battery-full::before {
+ content: "\f240"; }
+
+.fa-battery::before {
+ content: "\f240"; }
+
+.fa-battery-5::before {
+ content: "\f240"; }
+
+.fa-skull-crossbones::before {
+ content: "\f714"; }
+
+.fa-code-compare::before {
+ content: "\e13a"; }
+
+.fa-list-ul::before {
+ content: "\f0ca"; }
+
+.fa-list-dots::before {
+ content: "\f0ca"; }
+
+.fa-school-lock::before {
+ content: "\e56f"; }
+
+.fa-tower-cell::before {
+ content: "\e585"; }
+
+.fa-down-long::before {
+ content: "\f309"; }
+
+.fa-long-arrow-alt-down::before {
+ content: "\f309"; }
+
+.fa-ranking-star::before {
+ content: "\e561"; }
+
+.fa-chess-king::before {
+ content: "\f43f"; }
+
+.fa-person-harassing::before {
+ content: "\e549"; }
+
+.fa-brazilian-real-sign::before {
+ content: "\e46c"; }
+
+.fa-landmark-dome::before {
+ content: "\f752"; }
+
+.fa-landmark-alt::before {
+ content: "\f752"; }
+
+.fa-arrow-up::before {
+ content: "\f062"; }
+
+.fa-tv::before {
+ content: "\f26c"; }
+
+.fa-television::before {
+ content: "\f26c"; }
+
+.fa-tv-alt::before {
+ content: "\f26c"; }
+
+.fa-shrimp::before {
+ content: "\e448"; }
+
+.fa-list-check::before {
+ content: "\f0ae"; }
+
+.fa-tasks::before {
+ content: "\f0ae"; }
+
+.fa-jug-detergent::before {
+ content: "\e519"; }
+
+.fa-circle-user::before {
+ content: "\f2bd"; }
+
+.fa-user-circle::before {
+ content: "\f2bd"; }
+
+.fa-user-shield::before {
+ content: "\f505"; }
+
+.fa-wind::before {
+ content: "\f72e"; }
+
+.fa-car-burst::before {
+ content: "\f5e1"; }
+
+.fa-car-crash::before {
+ content: "\f5e1"; }
+
+.fa-y::before {
+ content: "\59"; }
+
+.fa-person-snowboarding::before {
+ content: "\f7ce"; }
+
+.fa-snowboarding::before {
+ content: "\f7ce"; }
+
+.fa-truck-fast::before {
+ content: "\f48b"; }
+
+.fa-shipping-fast::before {
+ content: "\f48b"; }
+
+.fa-fish::before {
+ content: "\f578"; }
+
+.fa-user-graduate::before {
+ content: "\f501"; }
+
+.fa-circle-half-stroke::before {
+ content: "\f042"; }
+
+.fa-adjust::before {
+ content: "\f042"; }
+
+.fa-clapperboard::before {
+ content: "\e131"; }
+
+.fa-circle-radiation::before {
+ content: "\f7ba"; }
+
+.fa-radiation-alt::before {
+ content: "\f7ba"; }
+
+.fa-baseball::before {
+ content: "\f433"; }
+
+.fa-baseball-ball::before {
+ content: "\f433"; }
+
+.fa-jet-fighter-up::before {
+ content: "\e518"; }
+
+.fa-diagram-project::before {
+ content: "\f542"; }
+
+.fa-project-diagram::before {
+ content: "\f542"; }
+
+.fa-copy::before {
+ content: "\f0c5"; }
+
+.fa-volume-xmark::before {
+ content: "\f6a9"; }
+
+.fa-volume-mute::before {
+ content: "\f6a9"; }
+
+.fa-volume-times::before {
+ content: "\f6a9"; }
+
+.fa-hand-sparkles::before {
+ content: "\e05d"; }
+
+.fa-grip::before {
+ content: "\f58d"; }
+
+.fa-grip-horizontal::before {
+ content: "\f58d"; }
+
+.fa-share-from-square::before {
+ content: "\f14d"; }
+
+.fa-share-square::before {
+ content: "\f14d"; }
+
+.fa-child-combatant::before {
+ content: "\e4e0"; }
+
+.fa-child-rifle::before {
+ content: "\e4e0"; }
+
+.fa-gun::before {
+ content: "\e19b"; }
+
+.fa-square-phone::before {
+ content: "\f098"; }
+
+.fa-phone-square::before {
+ content: "\f098"; }
+
+.fa-plus::before {
+ content: "\2b"; }
+
+.fa-add::before {
+ content: "\2b"; }
+
+.fa-expand::before {
+ content: "\f065"; }
+
+.fa-computer::before {
+ content: "\e4e5"; }
+
+.fa-xmark::before {
+ content: "\f00d"; }
+
+.fa-close::before {
+ content: "\f00d"; }
+
+.fa-multiply::before {
+ content: "\f00d"; }
+
+.fa-remove::before {
+ content: "\f00d"; }
+
+.fa-times::before {
+ content: "\f00d"; }
+
+.fa-arrows-up-down-left-right::before {
+ content: "\f047"; }
+
+.fa-arrows::before {
+ content: "\f047"; }
+
+.fa-chalkboard-user::before {
+ content: "\f51c"; }
+
+.fa-chalkboard-teacher::before {
+ content: "\f51c"; }
+
+.fa-peso-sign::before {
+ content: "\e222"; }
+
+.fa-building-shield::before {
+ content: "\e4d8"; }
+
+.fa-baby::before {
+ content: "\f77c"; }
+
+.fa-users-line::before {
+ content: "\e592"; }
+
+.fa-quote-left::before {
+ content: "\f10d"; }
+
+.fa-quote-left-alt::before {
+ content: "\f10d"; }
+
+.fa-tractor::before {
+ content: "\f722"; }
+
+.fa-trash-arrow-up::before {
+ content: "\f829"; }
+
+.fa-trash-restore::before {
+ content: "\f829"; }
+
+.fa-arrow-down-up-lock::before {
+ content: "\e4b0"; }
+
+.fa-lines-leaning::before {
+ content: "\e51e"; }
+
+.fa-ruler-combined::before {
+ content: "\f546"; }
+
+.fa-copyright::before {
+ content: "\f1f9"; }
+
+.fa-equals::before {
+ content: "\3d"; }
+
+.fa-blender::before {
+ content: "\f517"; }
+
+.fa-teeth::before {
+ content: "\f62e"; }
+
+.fa-shekel-sign::before {
+ content: "\f20b"; }
+
+.fa-ils::before {
+ content: "\f20b"; }
+
+.fa-shekel::before {
+ content: "\f20b"; }
+
+.fa-sheqel::before {
+ content: "\f20b"; }
+
+.fa-sheqel-sign::before {
+ content: "\f20b"; }
+
+.fa-map::before {
+ content: "\f279"; }
+
+.fa-rocket::before {
+ content: "\f135"; }
+
+.fa-photo-film::before {
+ content: "\f87c"; }
+
+.fa-photo-video::before {
+ content: "\f87c"; }
+
+.fa-folder-minus::before {
+ content: "\f65d"; }
+
+.fa-store::before {
+ content: "\f54e"; }
+
+.fa-arrow-trend-up::before {
+ content: "\e098"; }
+
+.fa-plug-circle-minus::before {
+ content: "\e55e"; }
+
+.fa-sign-hanging::before {
+ content: "\f4d9"; }
+
+.fa-sign::before {
+ content: "\f4d9"; }
+
+.fa-bezier-curve::before {
+ content: "\f55b"; }
+
+.fa-bell-slash::before {
+ content: "\f1f6"; }
+
+.fa-tablet::before {
+ content: "\f3fb"; }
+
+.fa-tablet-android::before {
+ content: "\f3fb"; }
+
+.fa-school-flag::before {
+ content: "\e56e"; }
+
+.fa-fill::before {
+ content: "\f575"; }
+
+.fa-angle-up::before {
+ content: "\f106"; }
+
+.fa-drumstick-bite::before {
+ content: "\f6d7"; }
+
+.fa-holly-berry::before {
+ content: "\f7aa"; }
+
+.fa-chevron-left::before {
+ content: "\f053"; }
+
+.fa-bacteria::before {
+ content: "\e059"; }
+
+.fa-hand-lizard::before {
+ content: "\f258"; }
+
+.fa-notdef::before {
+ content: "\e1fe"; }
+
+.fa-disease::before {
+ content: "\f7fa"; }
+
+.fa-briefcase-medical::before {
+ content: "\f469"; }
+
+.fa-genderless::before {
+ content: "\f22d"; }
+
+.fa-chevron-right::before {
+ content: "\f054"; }
+
+.fa-retweet::before {
+ content: "\f079"; }
+
+.fa-car-rear::before {
+ content: "\f5de"; }
+
+.fa-car-alt::before {
+ content: "\f5de"; }
+
+.fa-pump-soap::before {
+ content: "\e06b"; }
+
+.fa-video-slash::before {
+ content: "\f4e2"; }
+
+.fa-battery-quarter::before {
+ content: "\f243"; }
+
+.fa-battery-2::before {
+ content: "\f243"; }
+
+.fa-radio::before {
+ content: "\f8d7"; }
+
+.fa-baby-carriage::before {
+ content: "\f77d"; }
+
+.fa-carriage-baby::before {
+ content: "\f77d"; }
+
+.fa-traffic-light::before {
+ content: "\f637"; }
+
+.fa-thermometer::before {
+ content: "\f491"; }
+
+.fa-vr-cardboard::before {
+ content: "\f729"; }
+
+.fa-hand-middle-finger::before {
+ content: "\f806"; }
+
+.fa-percent::before {
+ content: "\25"; }
+
+.fa-percentage::before {
+ content: "\25"; }
+
+.fa-truck-moving::before {
+ content: "\f4df"; }
+
+.fa-glass-water-droplet::before {
+ content: "\e4f5"; }
+
+.fa-display::before {
+ content: "\e163"; }
+
+.fa-face-smile::before {
+ content: "\f118"; }
+
+.fa-smile::before {
+ content: "\f118"; }
+
+.fa-thumbtack::before {
+ content: "\f08d"; }
+
+.fa-thumb-tack::before {
+ content: "\f08d"; }
+
+.fa-trophy::before {
+ content: "\f091"; }
+
+.fa-person-praying::before {
+ content: "\f683"; }
+
+.fa-pray::before {
+ content: "\f683"; }
+
+.fa-hammer::before {
+ content: "\f6e3"; }
+
+.fa-hand-peace::before {
+ content: "\f25b"; }
+
+.fa-rotate::before {
+ content: "\f2f1"; }
+
+.fa-sync-alt::before {
+ content: "\f2f1"; }
+
+.fa-spinner::before {
+ content: "\f110"; }
+
+.fa-robot::before {
+ content: "\f544"; }
+
+.fa-peace::before {
+ content: "\f67c"; }
+
+.fa-gears::before {
+ content: "\f085"; }
+
+.fa-cogs::before {
+ content: "\f085"; }
+
+.fa-warehouse::before {
+ content: "\f494"; }
+
+.fa-arrow-up-right-dots::before {
+ content: "\e4b7"; }
+
+.fa-splotch::before {
+ content: "\f5bc"; }
+
+.fa-face-grin-hearts::before {
+ content: "\f584"; }
+
+.fa-grin-hearts::before {
+ content: "\f584"; }
+
+.fa-dice-four::before {
+ content: "\f524"; }
+
+.fa-sim-card::before {
+ content: "\f7c4"; }
+
+.fa-transgender::before {
+ content: "\f225"; }
+
+.fa-transgender-alt::before {
+ content: "\f225"; }
+
+.fa-mercury::before {
+ content: "\f223"; }
+
+.fa-arrow-turn-down::before {
+ content: "\f149"; }
+
+.fa-level-down::before {
+ content: "\f149"; }
+
+.fa-person-falling-burst::before {
+ content: "\e547"; }
+
+.fa-award::before {
+ content: "\f559"; }
+
+.fa-ticket-simple::before {
+ content: "\f3ff"; }
+
+.fa-ticket-alt::before {
+ content: "\f3ff"; }
+
+.fa-building::before {
+ content: "\f1ad"; }
+
+.fa-angles-left::before {
+ content: "\f100"; }
+
+.fa-angle-double-left::before {
+ content: "\f100"; }
+
+.fa-qrcode::before {
+ content: "\f029"; }
+
+.fa-clock-rotate-left::before {
+ content: "\f1da"; }
+
+.fa-history::before {
+ content: "\f1da"; }
+
+.fa-face-grin-beam-sweat::before {
+ content: "\f583"; }
+
+.fa-grin-beam-sweat::before {
+ content: "\f583"; }
+
+.fa-file-export::before {
+ content: "\f56e"; }
+
+.fa-arrow-right-from-file::before {
+ content: "\f56e"; }
+
+.fa-shield::before {
+ content: "\f132"; }
+
+.fa-shield-blank::before {
+ content: "\f132"; }
+
+.fa-arrow-up-short-wide::before {
+ content: "\f885"; }
+
+.fa-sort-amount-up-alt::before {
+ content: "\f885"; }
+
+.fa-house-medical::before {
+ content: "\e3b2"; }
+
+.fa-golf-ball-tee::before {
+ content: "\f450"; }
+
+.fa-golf-ball::before {
+ content: "\f450"; }
+
+.fa-circle-chevron-left::before {
+ content: "\f137"; }
+
+.fa-chevron-circle-left::before {
+ content: "\f137"; }
+
+.fa-house-chimney-window::before {
+ content: "\e00d"; }
+
+.fa-pen-nib::before {
+ content: "\f5ad"; }
+
+.fa-tent-arrow-turn-left::before {
+ content: "\e580"; }
+
+.fa-tents::before {
+ content: "\e582"; }
+
+.fa-wand-magic::before {
+ content: "\f0d0"; }
+
+.fa-magic::before {
+ content: "\f0d0"; }
+
+.fa-dog::before {
+ content: "\f6d3"; }
+
+.fa-carrot::before {
+ content: "\f787"; }
+
+.fa-moon::before {
+ content: "\f186"; }
+
+.fa-wine-glass-empty::before {
+ content: "\f5ce"; }
+
+.fa-wine-glass-alt::before {
+ content: "\f5ce"; }
+
+.fa-cheese::before {
+ content: "\f7ef"; }
+
+.fa-yin-yang::before {
+ content: "\f6ad"; }
+
+.fa-music::before {
+ content: "\f001"; }
+
+.fa-code-commit::before {
+ content: "\f386"; }
+
+.fa-temperature-low::before {
+ content: "\f76b"; }
+
+.fa-person-biking::before {
+ content: "\f84a"; }
+
+.fa-biking::before {
+ content: "\f84a"; }
+
+.fa-broom::before {
+ content: "\f51a"; }
+
+.fa-shield-heart::before {
+ content: "\e574"; }
+
+.fa-gopuram::before {
+ content: "\f664"; }
+
+.fa-earth-oceania::before {
+ content: "\e47b"; }
+
+.fa-globe-oceania::before {
+ content: "\e47b"; }
+
+.fa-square-xmark::before {
+ content: "\f2d3"; }
+
+.fa-times-square::before {
+ content: "\f2d3"; }
+
+.fa-xmark-square::before {
+ content: "\f2d3"; }
+
+.fa-hashtag::before {
+ content: "\23"; }
+
+.fa-up-right-and-down-left-from-center::before {
+ content: "\f424"; }
+
+.fa-expand-alt::before {
+ content: "\f424"; }
+
+.fa-oil-can::before {
+ content: "\f613"; }
+
+.fa-t::before {
+ content: "\54"; }
+
+.fa-hippo::before {
+ content: "\f6ed"; }
+
+.fa-chart-column::before {
+ content: "\e0e3"; }
+
+.fa-infinity::before {
+ content: "\f534"; }
+
+.fa-vial-circle-check::before {
+ content: "\e596"; }
+
+.fa-person-arrow-down-to-line::before {
+ content: "\e538"; }
+
+.fa-voicemail::before {
+ content: "\f897"; }
+
+.fa-fan::before {
+ content: "\f863"; }
+
+.fa-person-walking-luggage::before {
+ content: "\e554"; }
+
+.fa-up-down::before {
+ content: "\f338"; }
+
+.fa-arrows-alt-v::before {
+ content: "\f338"; }
+
+.fa-cloud-moon-rain::before {
+ content: "\f73c"; }
+
+.fa-calendar::before {
+ content: "\f133"; }
+
+.fa-trailer::before {
+ content: "\e041"; }
+
+.fa-bahai::before {
+ content: "\f666"; }
+
+.fa-haykal::before {
+ content: "\f666"; }
+
+.fa-sd-card::before {
+ content: "\f7c2"; }
+
+.fa-dragon::before {
+ content: "\f6d5"; }
+
+.fa-shoe-prints::before {
+ content: "\f54b"; }
+
+.fa-circle-plus::before {
+ content: "\f055"; }
+
+.fa-plus-circle::before {
+ content: "\f055"; }
+
+.fa-face-grin-tongue-wink::before {
+ content: "\f58b"; }
+
+.fa-grin-tongue-wink::before {
+ content: "\f58b"; }
+
+.fa-hand-holding::before {
+ content: "\f4bd"; }
+
+.fa-plug-circle-exclamation::before {
+ content: "\e55d"; }
+
+.fa-link-slash::before {
+ content: "\f127"; }
+
+.fa-chain-broken::before {
+ content: "\f127"; }
+
+.fa-chain-slash::before {
+ content: "\f127"; }
+
+.fa-unlink::before {
+ content: "\f127"; }
+
+.fa-clone::before {
+ content: "\f24d"; }
+
+.fa-person-walking-arrow-loop-left::before {
+ content: "\e551"; }
+
+.fa-arrow-up-z-a::before {
+ content: "\f882"; }
+
+.fa-sort-alpha-up-alt::before {
+ content: "\f882"; }
+
+.fa-fire-flame-curved::before {
+ content: "\f7e4"; }
+
+.fa-fire-alt::before {
+ content: "\f7e4"; }
+
+.fa-tornado::before {
+ content: "\f76f"; }
+
+.fa-file-circle-plus::before {
+ content: "\e494"; }
+
+.fa-book-quran::before {
+ content: "\f687"; }
+
+.fa-quran::before {
+ content: "\f687"; }
+
+.fa-anchor::before {
+ content: "\f13d"; }
+
+.fa-border-all::before {
+ content: "\f84c"; }
+
+.fa-face-angry::before {
+ content: "\f556"; }
+
+.fa-angry::before {
+ content: "\f556"; }
+
+.fa-cookie-bite::before {
+ content: "\f564"; }
+
+.fa-arrow-trend-down::before {
+ content: "\e097"; }
+
+.fa-rss::before {
+ content: "\f09e"; }
+
+.fa-feed::before {
+ content: "\f09e"; }
+
+.fa-draw-polygon::before {
+ content: "\f5ee"; }
+
+.fa-scale-balanced::before {
+ content: "\f24e"; }
+
+.fa-balance-scale::before {
+ content: "\f24e"; }
+
+.fa-gauge-simple-high::before {
+ content: "\f62a"; }
+
+.fa-tachometer::before {
+ content: "\f62a"; }
+
+.fa-tachometer-fast::before {
+ content: "\f62a"; }
+
+.fa-shower::before {
+ content: "\f2cc"; }
+
+.fa-desktop::before {
+ content: "\f390"; }
+
+.fa-desktop-alt::before {
+ content: "\f390"; }
+
+.fa-m::before {
+ content: "\4d"; }
+
+.fa-table-list::before {
+ content: "\f00b"; }
+
+.fa-th-list::before {
+ content: "\f00b"; }
+
+.fa-comment-sms::before {
+ content: "\f7cd"; }
+
+.fa-sms::before {
+ content: "\f7cd"; }
+
+.fa-book::before {
+ content: "\f02d"; }
+
+.fa-user-plus::before {
+ content: "\f234"; }
+
+.fa-check::before {
+ content: "\f00c"; }
+
+.fa-battery-three-quarters::before {
+ content: "\f241"; }
+
+.fa-battery-4::before {
+ content: "\f241"; }
+
+.fa-house-circle-check::before {
+ content: "\e509"; }
+
+.fa-angle-left::before {
+ content: "\f104"; }
+
+.fa-diagram-successor::before {
+ content: "\e47a"; }
+
+.fa-truck-arrow-right::before {
+ content: "\e58b"; }
+
+.fa-arrows-split-up-and-left::before {
+ content: "\e4bc"; }
+
+.fa-hand-fist::before {
+ content: "\f6de"; }
+
+.fa-fist-raised::before {
+ content: "\f6de"; }
+
+.fa-cloud-moon::before {
+ content: "\f6c3"; }
+
+.fa-briefcase::before {
+ content: "\f0b1"; }
+
+.fa-person-falling::before {
+ content: "\e546"; }
+
+.fa-image-portrait::before {
+ content: "\f3e0"; }
+
+.fa-portrait::before {
+ content: "\f3e0"; }
+
+.fa-user-tag::before {
+ content: "\f507"; }
+
+.fa-rug::before {
+ content: "\e569"; }
+
+.fa-earth-europe::before {
+ content: "\f7a2"; }
+
+.fa-globe-europe::before {
+ content: "\f7a2"; }
+
+.fa-cart-flatbed-suitcase::before {
+ content: "\f59d"; }
+
+.fa-luggage-cart::before {
+ content: "\f59d"; }
+
+.fa-rectangle-xmark::before {
+ content: "\f410"; }
+
+.fa-rectangle-times::before {
+ content: "\f410"; }
+
+.fa-times-rectangle::before {
+ content: "\f410"; }
+
+.fa-window-close::before {
+ content: "\f410"; }
+
+.fa-baht-sign::before {
+ content: "\e0ac"; }
+
+.fa-book-open::before {
+ content: "\f518"; }
+
+.fa-book-journal-whills::before {
+ content: "\f66a"; }
+
+.fa-journal-whills::before {
+ content: "\f66a"; }
+
+.fa-handcuffs::before {
+ content: "\e4f8"; }
+
+.fa-triangle-exclamation::before {
+ content: "\f071"; }
+
+.fa-exclamation-triangle::before {
+ content: "\f071"; }
+
+.fa-warning::before {
+ content: "\f071"; }
+
+.fa-database::before {
+ content: "\f1c0"; }
+
+.fa-share::before {
+ content: "\f064"; }
+
+.fa-arrow-turn-right::before {
+ content: "\f064"; }
+
+.fa-mail-forward::before {
+ content: "\f064"; }
+
+.fa-bottle-droplet::before {
+ content: "\e4c4"; }
+
+.fa-mask-face::before {
+ content: "\e1d7"; }
+
+.fa-hill-rockslide::before {
+ content: "\e508"; }
+
+.fa-right-left::before {
+ content: "\f362"; }
+
+.fa-exchange-alt::before {
+ content: "\f362"; }
+
+.fa-paper-plane::before {
+ content: "\f1d8"; }
+
+.fa-road-circle-exclamation::before {
+ content: "\e565"; }
+
+.fa-dungeon::before {
+ content: "\f6d9"; }
+
+.fa-align-right::before {
+ content: "\f038"; }
+
+.fa-money-bill-1-wave::before {
+ content: "\f53b"; }
+
+.fa-money-bill-wave-alt::before {
+ content: "\f53b"; }
+
+.fa-life-ring::before {
+ content: "\f1cd"; }
+
+.fa-hands::before {
+ content: "\f2a7"; }
+
+.fa-sign-language::before {
+ content: "\f2a7"; }
+
+.fa-signing::before {
+ content: "\f2a7"; }
+
+.fa-calendar-day::before {
+ content: "\f783"; }
+
+.fa-water-ladder::before {
+ content: "\f5c5"; }
+
+.fa-ladder-water::before {
+ content: "\f5c5"; }
+
+.fa-swimming-pool::before {
+ content: "\f5c5"; }
+
+.fa-arrows-up-down::before {
+ content: "\f07d"; }
+
+.fa-arrows-v::before {
+ content: "\f07d"; }
+
+.fa-face-grimace::before {
+ content: "\f57f"; }
+
+.fa-grimace::before {
+ content: "\f57f"; }
+
+.fa-wheelchair-move::before {
+ content: "\e2ce"; }
+
+.fa-wheelchair-alt::before {
+ content: "\e2ce"; }
+
+.fa-turn-down::before {
+ content: "\f3be"; }
+
+.fa-level-down-alt::before {
+ content: "\f3be"; }
+
+.fa-person-walking-arrow-right::before {
+ content: "\e552"; }
+
+.fa-square-envelope::before {
+ content: "\f199"; }
+
+.fa-envelope-square::before {
+ content: "\f199"; }
+
+.fa-dice::before {
+ content: "\f522"; }
+
+.fa-bowling-ball::before {
+ content: "\f436"; }
+
+.fa-brain::before {
+ content: "\f5dc"; }
+
+.fa-bandage::before {
+ content: "\f462"; }
+
+.fa-band-aid::before {
+ content: "\f462"; }
+
+.fa-calendar-minus::before {
+ content: "\f272"; }
+
+.fa-circle-xmark::before {
+ content: "\f057"; }
+
+.fa-times-circle::before {
+ content: "\f057"; }
+
+.fa-xmark-circle::before {
+ content: "\f057"; }
+
+.fa-gifts::before {
+ content: "\f79c"; }
+
+.fa-hotel::before {
+ content: "\f594"; }
+
+.fa-earth-asia::before {
+ content: "\f57e"; }
+
+.fa-globe-asia::before {
+ content: "\f57e"; }
+
+.fa-id-card-clip::before {
+ content: "\f47f"; }
+
+.fa-id-card-alt::before {
+ content: "\f47f"; }
+
+.fa-magnifying-glass-plus::before {
+ content: "\f00e"; }
+
+.fa-search-plus::before {
+ content: "\f00e"; }
+
+.fa-thumbs-up::before {
+ content: "\f164"; }
+
+.fa-user-clock::before {
+ content: "\f4fd"; }
+
+.fa-hand-dots::before {
+ content: "\f461"; }
+
+.fa-allergies::before {
+ content: "\f461"; }
+
+.fa-file-invoice::before {
+ content: "\f570"; }
+
+.fa-window-minimize::before {
+ content: "\f2d1"; }
+
+.fa-mug-saucer::before {
+ content: "\f0f4"; }
+
+.fa-coffee::before {
+ content: "\f0f4"; }
+
+.fa-brush::before {
+ content: "\f55d"; }
+
+.fa-mask::before {
+ content: "\f6fa"; }
+
+.fa-magnifying-glass-minus::before {
+ content: "\f010"; }
+
+.fa-search-minus::before {
+ content: "\f010"; }
+
+.fa-ruler-vertical::before {
+ content: "\f548"; }
+
+.fa-user-large::before {
+ content: "\f406"; }
+
+.fa-user-alt::before {
+ content: "\f406"; }
+
+.fa-train-tram::before {
+ content: "\e5b4"; }
+
+.fa-user-nurse::before {
+ content: "\f82f"; }
+
+.fa-syringe::before {
+ content: "\f48e"; }
+
+.fa-cloud-sun::before {
+ content: "\f6c4"; }
+
+.fa-stopwatch-20::before {
+ content: "\e06f"; }
+
+.fa-square-full::before {
+ content: "\f45c"; }
+
+.fa-magnet::before {
+ content: "\f076"; }
+
+.fa-jar::before {
+ content: "\e516"; }
+
+.fa-note-sticky::before {
+ content: "\f249"; }
+
+.fa-sticky-note::before {
+ content: "\f249"; }
+
+.fa-bug-slash::before {
+ content: "\e490"; }
+
+.fa-arrow-up-from-water-pump::before {
+ content: "\e4b6"; }
+
+.fa-bone::before {
+ content: "\f5d7"; }
+
+.fa-user-injured::before {
+ content: "\f728"; }
+
+.fa-face-sad-tear::before {
+ content: "\f5b4"; }
+
+.fa-sad-tear::before {
+ content: "\f5b4"; }
+
+.fa-plane::before {
+ content: "\f072"; }
+
+.fa-tent-arrows-down::before {
+ content: "\e581"; }
+
+.fa-exclamation::before {
+ content: "\21"; }
+
+.fa-arrows-spin::before {
+ content: "\e4bb"; }
+
+.fa-print::before {
+ content: "\f02f"; }
+
+.fa-turkish-lira-sign::before {
+ content: "\e2bb"; }
+
+.fa-try::before {
+ content: "\e2bb"; }
+
+.fa-turkish-lira::before {
+ content: "\e2bb"; }
+
+.fa-dollar-sign::before {
+ content: "\24"; }
+
+.fa-dollar::before {
+ content: "\24"; }
+
+.fa-usd::before {
+ content: "\24"; }
+
+.fa-x::before {
+ content: "\58"; }
+
+.fa-magnifying-glass-dollar::before {
+ content: "\f688"; }
+
+.fa-search-dollar::before {
+ content: "\f688"; }
+
+.fa-users-gear::before {
+ content: "\f509"; }
+
+.fa-users-cog::before {
+ content: "\f509"; }
+
+.fa-person-military-pointing::before {
+ content: "\e54a"; }
+
+.fa-building-columns::before {
+ content: "\f19c"; }
+
+.fa-bank::before {
+ content: "\f19c"; }
+
+.fa-institution::before {
+ content: "\f19c"; }
+
+.fa-museum::before {
+ content: "\f19c"; }
+
+.fa-university::before {
+ content: "\f19c"; }
+
+.fa-umbrella::before {
+ content: "\f0e9"; }
+
+.fa-trowel::before {
+ content: "\e589"; }
+
+.fa-d::before {
+ content: "\44"; }
+
+.fa-stapler::before {
+ content: "\e5af"; }
+
+.fa-masks-theater::before {
+ content: "\f630"; }
+
+.fa-theater-masks::before {
+ content: "\f630"; }
+
+.fa-kip-sign::before {
+ content: "\e1c4"; }
+
+.fa-hand-point-left::before {
+ content: "\f0a5"; }
+
+.fa-handshake-simple::before {
+ content: "\f4c6"; }
+
+.fa-handshake-alt::before {
+ content: "\f4c6"; }
+
+.fa-jet-fighter::before {
+ content: "\f0fb"; }
+
+.fa-fighter-jet::before {
+ content: "\f0fb"; }
+
+.fa-square-share-nodes::before {
+ content: "\f1e1"; }
+
+.fa-share-alt-square::before {
+ content: "\f1e1"; }
+
+.fa-barcode::before {
+ content: "\f02a"; }
+
+.fa-plus-minus::before {
+ content: "\e43c"; }
+
+.fa-video::before {
+ content: "\f03d"; }
+
+.fa-video-camera::before {
+ content: "\f03d"; }
+
+.fa-graduation-cap::before {
+ content: "\f19d"; }
+
+.fa-mortar-board::before {
+ content: "\f19d"; }
+
+.fa-hand-holding-medical::before {
+ content: "\e05c"; }
+
+.fa-person-circle-check::before {
+ content: "\e53e"; }
+
+.fa-turn-up::before {
+ content: "\f3bf"; }
+
+.fa-level-up-alt::before {
+ content: "\f3bf"; }
+
+.sr-only,
+.fa-sr-only {
+ position: absolute;
+ width: 1px;
+ height: 1px;
+ padding: 0;
+ margin: -1px;
+ overflow: hidden;
+ clip: rect(0, 0, 0, 0);
+ white-space: nowrap;
+ border-width: 0; }
+
+.sr-only-focusable:not(:focus),
+.fa-sr-only-focusable:not(:focus) {
+ position: absolute;
+ width: 1px;
+ height: 1px;
+ padding: 0;
+ margin: -1px;
+ overflow: hidden;
+ clip: rect(0, 0, 0, 0);
+ white-space: nowrap;
+ border-width: 0; }
diff --git a/asset/css/horizontal-key-value.less b/asset/css/horizontal-key-value.less
new file mode 100644
index 0000000..24ff54c
--- /dev/null
+++ b/asset/css/horizontal-key-value.less
@@ -0,0 +1,17 @@
+.horizontal-key-value {
+ display: flex;
+ padding: .25em 0;
+ align-items: baseline;
+
+ .key {
+ color: var(--default-text-color-light, @default-text-color-light);
+ flex: 0 0 auto;
+ white-space: nowrap;
+ width: 12em;
+ }
+
+ .value {
+ color: var(--default-text-color, @default-text-color);
+ flex: 1 1 auto;
+ }
+}
diff --git a/asset/css/icinga-icons.less b/asset/css/icinga-icons.less
new file mode 100644
index 0000000..5b631f9
--- /dev/null
+++ b/asset/css/icinga-icons.less
@@ -0,0 +1,64 @@
+@font-face {
+ font-family: 'Icinga-Icons';
+ src: url('@{iplWebAssets}/font/icinga-icons/fonts/Icinga-Icons.ttf') format('truetype'),
+ url('@{iplWebAssets}/font/icinga-icons/fonts/Icinga-Icons.woff') format('woff'),
+ url('@{iplWebAssets}/font/icinga-icons/fonts/Icinga-Icons.svg') format('svg');
+ font-weight: normal;
+ font-style: normal;
+ font-display: block;
+}
+
+[class^="iicon-"]:before, [class*=" iicon-"]:before {
+ /* use !important to prevent issues with browser extensions that change fonts */
+ font-family: 'Icinga-Icons';
+ speak: none;
+ font-style: normal;
+ font-weight: normal;
+ font-variant: normal;
+ text-transform: none;
+ line-height: 1em;
+
+ /* Better Font Rendering =========== */
+ -webkit-font-smoothing: antialiased;
+ -moz-osx-font-smoothing: grayscale;
+}
+
+.iicon-certificate:before {
+ content: "\e906";
+}
+.iicon-filter-check-circle:before {
+ content: "\e90b";
+}
+.iicon-ca-check-circle:before {
+ content: "\e908";
+}
+.iicon-refresh-cert:before {
+ content: "\e909";
+}
+.iicon-th-list:before {
+ content: "\e90a";
+}
+.iicon-icinga:before {
+ content: "\e907";
+}
+.iicon-minimal:before,
+.iicon-list-view-minimal:before {
+ content: "\e900";
+}
+.iicon-detailed:before,
+.iicon-list-view-detailed:before {
+ content: "\e901";
+}
+.iicon-default:before,
+.iicon-list-view-default:before {
+ content: "\e902";
+}
+.iicon-grid:before {
+ content: "\e903";
+}
+.iicon-bracket-open:before {
+ content: "\e904";
+}
+.iicon-bracket-close:before {
+ content: "\e905";
+}
diff --git a/asset/css/icons-base.less b/asset/css/icons-base.less
new file mode 100644
index 0000000..301c505
--- /dev/null
+++ b/asset/css/icons-base.less
@@ -0,0 +1,12 @@
+i.icon {
+ vertical-align: middle; // Firefox will place icons weird otherwise
+
+ &:before {
+ display: inline-block;
+ min-width: 1em;
+ margin-right: .2em;
+
+ text-align: center;
+ text-decoration: inherit;
+ }
+}
diff --git a/asset/css/list/item-list.less b/asset/css/list/item-list.less
new file mode 100644
index 0000000..c5c0bd2
--- /dev/null
+++ b/asset/css/list/item-list.less
@@ -0,0 +1,85 @@
+// Style
+
+.item-list {
+ list-style-type: none;
+}
+
+// Layout
+
+.item-list {
+ margin: 0;
+ padding: 0;
+
+ .list-item {
+ display: flex;
+
+ .main {
+ flex: 1 1 auto;
+ padding: .5em 0;
+ width: 0;
+ margin-left: .5em;
+ }
+
+ .visual {
+ display: flex;
+ align-items: center;
+ flex-direction: column;
+ }
+
+ .caption {
+ height: 3em;
+ text-overflow: ellipsis;
+ overflow: hidden;
+
+ .line-clamp();
+
+ img {
+ max-height: 1em;
+ }
+ }
+
+ header {
+ display: flex;
+ align-items: flex-start;
+ justify-content: space-between;
+ }
+
+ footer {
+ display: flex;
+ justify-content: space-between;
+ }
+ }
+
+ > .empty-state-bar {
+ margin: 0 1em;
+ }
+}
+
+.item-list.default-layout .list-item {
+ .title {
+ display: inline-flex;
+ align-items: baseline;
+ white-space: nowrap;
+ min-width: 0;
+
+ > * {
+ margin: 0 .28125em; // 0 calculated &nbsp; width
+
+ &:first-child {
+ margin-left: 0;
+ }
+
+ &:last-child {
+ margin-right: 0;
+ }
+ }
+
+ .subject {
+ .text-ellipsis();
+ }
+ }
+}
+
+.controls .list-item:not(:last-child) {
+ margin-bottom: .5em;
+}
diff --git a/asset/css/list/item-table.less b/asset/css/list/item-table.less
new file mode 100644
index 0000000..68b7d2f
--- /dev/null
+++ b/asset/css/list/item-table.less
@@ -0,0 +1,95 @@
+// Style
+
+ul.item-table {
+ list-style-type: none;
+}
+
+.table-row {
+ color: @default-text-color-light;
+
+ .title {
+ .subject {
+ color: @default-text-color;
+ }
+
+ a {
+ font-weight: bold;
+
+ &:hover {
+ color: @list-item-title-hover-color;
+ text-decoration: none;
+ }
+ }
+ }
+}
+
+@media print {
+ .item-table li.page-break-follows:not(:last-of-type) {
+ .col {
+ border-bottom: none;
+ }
+
+ .visual {
+ margin-bottom: 0;
+ }
+ }
+}
+
+// Layout
+
+.table-row {
+ .title {
+ display: flex;
+
+ .visual {
+ width: 2.5em;
+ padding: .5em 0;
+ margin-top: -.5em;
+ margin-bottom: -.5em;
+ }
+
+ .content {
+ flex: 1 1 auto;
+ width: 0;
+
+ > * {
+ .text-ellipsis();
+ }
+ }
+ }
+
+ .col {
+ white-space: nowrap;
+ }
+}
+
+ul.item-table {
+ display: grid;
+
+ > .table-row {
+ .col:not(.title) {
+ display: grid;
+ align-items: center;
+ }
+ }
+}
+
+ul.item-table {
+ padding: 0;
+ margin: 0;
+}
+
+div.item-table {
+ > .empty-state-bar {
+ margin: 0 1em;
+ }
+}
+
+div.table-row {
+ display: flex;
+ column-gap: 1em;
+
+ .title {
+ flex: 1 1 auto;
+ }
+}
diff --git a/asset/css/list/list-item.less b/asset/css/list/list-item.less
new file mode 100644
index 0000000..56a43a3
--- /dev/null
+++ b/asset/css/list/list-item.less
@@ -0,0 +1,85 @@
+// Style
+
+.list-item {
+ color: @default-text-color-light;
+
+ &:not(:first-child) > .main {
+ border-top: 1px solid @list-item-separation-bg;
+ }
+
+ &:not(:first-child) .visual {
+ margin-top: 1px;
+ }
+
+ .caption {
+ i {
+ opacity: 0.8;
+ }
+
+ a {
+ color: @default-text-color;
+ }
+ }
+
+ .title {
+ .subject {
+ color: @default-text-color;
+ }
+
+ a {
+ color: @default-text-color;
+ font-weight: bold;
+
+ &:hover {
+ color: @list-item-title-hover-color;
+ text-decoration: none;
+ }
+ }
+ }
+
+ footer {
+ padding-top: .5em;
+ }
+}
+
+@media print {
+ .list-item.page-break-follows + .list-item {
+ .main {
+ border-top: 1px solid transparent;
+ }
+ }
+}
+
+// Layout
+
+.list-item {
+ .visual {
+ padding: .5em 0;
+ width: 2.5em;
+ }
+
+ .caption {
+ p {
+ display: inline-block;
+ }
+ }
+
+ .title {
+ margin-right: 1em;
+
+ p {
+ margin: 0;
+ }
+ }
+
+ time {
+ white-space: nowrap;
+ }
+
+ footer {
+ > * {
+ font-size: .857em;
+ line-height: 1.5*.857em;
+ }
+ }
+}
diff --git a/asset/css/mixin/card.less b/asset/css/mixin/card.less
new file mode 100644
index 0000000..3823ba2
--- /dev/null
+++ b/asset/css/mixin/card.less
@@ -0,0 +1,23 @@
+.card() {
+ &.card {
+ .rounded-corners(.5em);
+ border: 1px solid var(--card-border-color, @card-border-color);
+
+ .card-header {
+ display: flex;
+ align-items: baseline;
+ justify-content: space-between;
+ padding: .5em;
+
+ border-bottom: 1px solid var(--card-border-color, @card-border-color);
+
+ .meta span {
+ font-size: 11/12em;
+ }
+ }
+
+ .card-body {
+ padding: .5em;
+ }
+ }
+}
diff --git a/asset/css/mixin/mixins.less b/asset/css/mixin/mixins.less
new file mode 100644
index 0000000..ca30dd0
--- /dev/null
+++ b/asset/css/mixin/mixins.less
@@ -0,0 +1,37 @@
+.rounded-corners(@border-radius: 0.4em) {
+ border-radius: @border-radius;
+
+ -webkit-background-clip: padding-box;
+ -moz-background-clip: padding;
+ background-clip: padding-box;
+}
+
+.appearance(@appearance) {
+ -webkit-appearance: @appearance;
+ -moz-appearance: @appearance;
+ -ms-appearance: @appearance;
+ appearance: @appearance;
+}
+
+.box-shadow(@x: 0.2em; @y: 0.2em; @blur: 0.2em; @spread: 0; @color: rgba(83, 83, 83, 0.25)) {
+ -webkit-box-shadow: @arguments;
+ -moz-box-shadow: @arguments;
+ box-shadow: @arguments;
+}
+
+.line-clamp(@numOfLines: 2) when (@numOfLines > 1) {
+ display: -webkit-box;
+ -webkit-line-clamp: @numOfLines;
+ -webkit-box-orient: vertical;
+}
+.line-clamp(@numOfLines: 2) when (@numOfLines = "reset") {
+ display: revert;
+ -webkit-line-clamp: initial;
+ -webkit-box-orient: initial;
+}
+
+.text-ellipsis() {
+ white-space: nowrap;
+ overflow: hidden;
+ text-overflow: ellipsis;
+}
diff --git a/asset/css/mixin/state-badges.less b/asset/css/mixin/state-badges.less
new file mode 100644
index 0000000..4be2d07
--- /dev/null
+++ b/asset/css/mixin/state-badges.less
@@ -0,0 +1,31 @@
+.state-badges() {
+ &.state-badges {
+ padding: 0;
+
+ ul {
+ padding: 0;
+ }
+
+ li {
+ display: inline-block;
+ }
+
+ li > ul > li:first-child:not(:last-child) .state-badge {
+ border-bottom-right-radius: 0;
+ border-top-right-radius: 0;
+ }
+
+ li > ul > li:last-child:not(:first-child) .state-badge {
+ border-bottom-left-radius: 0;
+ border-top-left-radius: 0;
+ }
+
+ > li:not(:last-child) {
+ margin-right: .25em;
+ }
+
+ li > ul > li + li {
+ margin-left: 1px;
+ }
+ }
+}
diff --git a/asset/css/primary-submit-btn-duplicate.less b/asset/css/primary-submit-btn-duplicate.less
new file mode 100644
index 0000000..aae545f
--- /dev/null
+++ b/asset/css/primary-submit-btn-duplicate.less
@@ -0,0 +1,16 @@
+/**
+ Automatically set CSS class for duplicated submit buttons
+ used for implicit form submission that should be invisible
+ and not take up any space. `display: none` is not an option,
+ because at least Safari will then ignore the element completely
+ when submitting a form.
+ */
+.primary-submit-btn-duplicate {
+ border: 0;
+ height: 0;
+ margin: 0;
+ padding: 0;
+ visibility: hidden;
+ width: 0;
+ position: absolute;
+}
diff --git a/asset/css/schedule-element.less b/asset/css/schedule-element.less
new file mode 100644
index 0000000..1905a05
--- /dev/null
+++ b/asset/css/schedule-element.less
@@ -0,0 +1,210 @@
+// Schedule form element
+
+.schedule-element {
+ @input-border-radius: .25em;
+
+ .ordinal {
+ display: flex;
+ flex-wrap: wrap;
+
+ .radio-label {
+ flex: 1 1 auto;
+ }
+
+ select {
+ flex: 1 1 auto;
+
+ &:first-of-type {
+ margin-right: 1em;
+ }
+
+ &:disabled {
+ color: @schedule-element-fields-disabled-color;
+ }
+ }
+ }
+
+ .radio-label {
+ width: 100%;
+ margin-bottom: .5em;
+ display: flex;
+ align-items: center; // To center the radio element on safari
+ }
+
+ .number-specifier > input[type="number"] {
+ width: 5em;
+ margin: 0 1em;
+ }
+
+ .monthly, .ordinal:not(.annually) {
+ padding: .5em;
+ margin-left: -.5em;
+ border: 1px solid @schedule-element-fields-border-color;
+ .rounded-corners(.75em);
+ }
+
+ .schedule-element-fields {
+ list-style-type: none;
+ margin: 0;
+ padding: 0;
+ .rounded-corners(.25em);
+ overflow: hidden;
+ display:flex;
+ flex-wrap: wrap;
+
+ &.disabled { // When the "On the" radio button is checked
+ pointer-events: none;
+
+ label {
+ color: @schedule-element-fields-disabled-color;
+ background-color: @schedule-element-fields-disabled-bg;
+ }
+
+ input:checked + label {
+ background: @schedule-element-fields-disabled-selected-bg;
+ color: @schedule-element-fields-disabled-color;
+ }
+ }
+
+ li {
+ width: calc(100% / 7); /* default for week based cols makes sense */
+
+ label {
+ display: block;
+ width: 100%;
+ cursor: pointer;
+ text-align: center;
+ padding: .75em 0;
+ background: @schedule-element-fields-bg;
+ color: @schedule-element-fields-color;
+
+ &:hover {
+ background-color: @schedule-element-fields-hover-bg;
+ }
+
+ &:focus {
+ outline: none;
+ }
+ }
+
+ input:checked + label {
+ background-color: @schedule-element-fields-selected-bg;
+ color: @schedule-element-fields-selected-color;
+ }
+
+ input:checked + label:hover {
+ background-color: @schedule-element-fields-selected-hover-bg;
+ border-color: @schedule-element-fields-selected-hover-bg;
+ }
+ }
+
+ &.multiple-fields {
+ li:not(:last-child) label {
+ border-right: 1px solid @schedule-element-fields-border-color;
+ }
+
+ input:focus + label {
+ box-shadow: inset 0 0 0 3px @schedule-element-fields-outline-color;
+ }
+
+ input:checked:focus + label {
+ box-shadow: inset 0 0 0 3px @schedule-element-fields-selected-outline-color;
+ }
+ }
+
+ &.single-fields {
+ li {
+ padding-right: 1px;
+ }
+
+ li label {
+ .rounded-corners(.25em);
+ margin-right: 1px;
+ margin-bottom: 1px;
+ }
+
+ li label {
+ border-right: none;
+ }
+
+ &:focus-within {
+ outline: 3px solid @schedule-element-fields-outline-color;
+ outline-offset: 2px;
+ }
+
+ &:focus-within + .note {
+ display: block;
+ }
+
+ input:checked + label:hover {
+ background-color: @schedule-element-fields-selected-bg;
+ }
+ }
+ }
+
+ .note {
+ display: none;
+ padding: .5em;
+ background: @schedule-element-keyboard-note-bg;
+ .rounded-corners(.25em);
+ text-align: center;
+ margin-top: 1em;
+ line-height: 1.25;
+ }
+
+ /* .weekly */
+ .weekly { }
+
+ /* .monthly styles */
+ .monthly {
+ li label {
+ border-top: 1px solid @schedule-element-fields-border-color;
+ }
+
+ li:first-child,
+ li:nth-child(2),
+ li:nth-child(3),
+ li:nth-child(4),
+ li:nth-child(5),
+ li:nth-child(6),
+ li:nth-child(7) {
+ label {
+ border-top: none;
+ }
+ }
+
+ /* last of row should not have a border */
+ .schedule-element-fields li:nth-child(7n) label {
+ border-right: none;
+ }
+ }
+
+
+ /* .annually styles */
+ .annually {
+ li {
+ width: 25%; // 100% / 4 elements
+ }
+
+ li:nth-child(4n) label {
+ margin-right: 0;
+ }
+
+ .toggle-slider-controls {
+ display: flex;
+ column-gap: 1em;
+ align-items: center;
+ margin-top: 1em;
+ margin-bottom: -.6em;
+ }
+ }
+}
+
+.schedule-recurrences {
+ line-height: 1.1em;
+ padding-top: 0.5625em;
+
+ p {
+ color: @schedule-element-fields-disabled-color;
+ }
+}
diff --git a/asset/css/search-bar.less b/asset/css/search-bar.less
new file mode 100644
index 0000000..6ad1aec
--- /dev/null
+++ b/asset/css/search-bar.less
@@ -0,0 +1,232 @@
+// Style
+.search-bar {
+ .rounded-corners(.25em);
+ background: var(--searchbar-bg, @searchbar-bg);
+
+ // Reset all input styles
+ input, [type="button"] {
+ .appearance(none);
+ border: none;
+ background: none;
+ }
+
+ // Submit button styles
+ input[type=submit],
+ button[type=submit],
+ button:not([type]) {
+ background: var(--primary-button-bg, @primary-button-bg);
+ color: var(--primary-button-color, @primary-button-color);
+ border-top-right-radius: .25em;
+ border-bottom-right-radius: .25em;
+ }
+
+ // General input styles
+ input:focus {
+ outline-offset: -1px;
+ }
+
+ // Hide the submit button, it must exist, but shouldn't be shown to the user
+ input[type=submit][value="hidden"] {
+ display: none;
+ }
+
+ // Left-most search dropdown style
+ button.search-options {
+ i.icon:before {
+ font-size: 1.2em;
+ margin-right: 0;
+ color: var(--control-color, @control-color);
+ }
+
+ &:disabled {
+ i.icon:before {
+ color: var(--control-disabled-color, @control-disabled-color);
+ }
+ }
+ }
+
+ // Term styles
+ .filter-condition {
+ button {
+ border-radius: .4em 0 0 .4em;
+ background-color: var(--search-condition-remove-bg, @search-condition-remove-bg);
+ color: var(--search-condition-remove-color, @search-condition-remove-color);
+
+ &:after {
+ content: "";
+ position: absolute;
+ width: .4em;
+ height: 100%;
+ right: 0;
+ top: 0;
+
+ background-color: var(--searchbar-bg, @searchbar-bg);
+ border: .2em solid var(--search-condition-remove-bg, @search-condition-remove-bg);
+ border-width: 0 0 0 .2em;
+ border-top-left-radius: .4em;
+ border-bottom-left-radius: .4em;
+ }
+ }
+
+ input {
+ background-color: var(--search-term-bg, @search-term-bg);
+ color: var(--search-term-color, @search-term-color);
+ }
+ }
+
+ .terms > .filter-condition:first-child button {
+ border-radius: 0 .4em .4em 0;
+
+ &:before {
+ content: "";
+ position: absolute;
+ width: .4em;
+ height: 100%;
+ left: 0;
+ top: 0;
+
+ background-color: var(--searchbar-bg, @searchbar-bg);
+ border: .2em solid var(--search-condition-remove-bg, @search-condition-remove-bg);
+ border-width: 0 .2em 0 0;
+ border-top-right-radius: .4em;
+ border-bottom-right-radius: .4em;
+ }
+
+ &:after {
+ content: none;
+ }
+ }
+
+ .logical_operator,
+ .grouping_operator_open,
+ .grouping_operator_close {
+ input {
+ .rounded-corners();
+ background-color: var(--search-logical-operator-bg, @search-logical-operator-bg);
+ color: var(--search-logical-operator-color, @search-logical-operator-color);
+ }
+ }
+
+ .operator,
+ .logical_operator,
+ .grouping_operator_open,
+ .grouping_operator_close {
+ input {
+ text-align: center;
+ }
+ }
+
+ .column input {
+ .rounded-corners(.4em);
+ }
+ .column:not(:last-of-type),
+ .column.last-term {
+ input {
+ border-top-right-radius: 0;
+ border-bottom-right-radius: 0;
+ }
+ }
+
+ .operator:last-of-type:not(.last-term) input {
+ .rounded-corners(.4em);
+ border-top-left-radius: 0;
+ border-bottom-left-radius: 0;
+ }
+
+ .value input {
+ .rounded-corners(.4em);
+ border-top-left-radius: 0;
+ border-bottom-left-radius: 0;
+ }
+
+ .highlighted input {
+ background-color: var(--search-term-highlighted-bg, @search-term-highlighted-bg);
+ color: var(--search-term-highlighted-color, @search-term-highlighted-color);
+ }
+
+ ul.comma-separated {
+ display: inline;
+ padding: 0;
+
+ list-style-type: none;
+
+ li {
+ display: inline;
+
+ &:not(:first-of-type):before {
+ display: inline;
+ content: ', ';
+ }
+ }
+ }
+}
+
+// Layout
+.search-bar {
+ height: 2em;
+ display: flex;
+ position: relative; // Required for the suggestions
+
+ button.search-options {
+ line-height: 1em;
+ }
+
+ .filter-input-area {
+ padding: 2/12em; // 2 (px) desired / default font size (px)
+ }
+
+ .terms {
+ .filter-chain,
+ .filter-condition {
+ display: inline;
+ }
+
+ .filter-condition {
+ position: relative;
+
+ button {
+ display: none;
+ z-index: 1;
+ width: ~"calc(2em + 2px)";
+ padding: .15em .6em .15em .4em;
+ position: absolute;
+ left: ~"calc(-2em - 2px)"; // That's min-width + margin-right of an operator
+ line-height: 16/12; // 16 (px) desired / default font size (px)
+
+ i:before {
+ margin-right: 0;
+ }
+ }
+
+ &:not(._hover_delay):hover button {
+ display: inline;
+ }
+ }
+
+ > .filter-condition:first-child button {
+ padding: .15em .4em .15em .6em;
+ left: auto;
+ right: ~"calc(-2em - 1px)"; // That's min-width + margin-left of an operator
+ }
+
+ label {
+ &.logical_operator,
+ &.grouping_operator_open,
+ &.grouping_operator_close {
+ margin-left: 1px; // adds up to 2px with the previous term
+ margin-right: 2px;
+ }
+ }
+ }
+
+ &.disabled {
+ .terms .filter-condition:hover button {
+ display: none;
+ }
+ }
+
+ .search-suggestions {
+ // 2 (px) desired / default font-size to match .filter-input outline-offset (-1px) + outline-width (3px)
+ margin-top: 2/12em;
+ }
+}
diff --git a/asset/css/search-base.less b/asset/css/search-base.less
new file mode 100644
index 0000000..e4af764
--- /dev/null
+++ b/asset/css/search-base.less
@@ -0,0 +1,269 @@
+// Style
+
+.search-bar .filter-input-area,
+.term-input-area:not(.vertical) {
+ // Scrollbar style
+
+ // Firefox
+ scrollbar-width: thin;
+ scrollbar-color: var(--searchbar-scrollbar-bg, @searchbar-scrollbar-bg) transparent;
+
+ &::-webkit-scrollbar {
+ display: none;
+ height: .5em;
+ }
+
+ &:hover::-webkit-scrollbar {
+ display: initial;
+ }
+
+ &::-webkit-scrollbar-thumb {
+ border-radius: .25em;
+ background: var(--searchbar-scrollbar-bg, @searchbar-scrollbar-bg);
+ }
+}
+
+.search-bar,
+.term-input-area {
+ [data-index] input:invalid {
+ background-color: var(--search-term-invalid-bg, @search-term-invalid-bg);
+ color: var(--search-term-invalid-color, @search-term-invalid-color);
+ }
+
+ [data-index] input:disabled {
+ background-color: var(--search-term-disabled-bg, @search-term-disabled-bg);
+ }
+
+ .selected input {
+ background-color: var(--search-term-selected-bg, @search-term-selected-bg);
+ color: var(--search-term-selected-color, @search-term-selected-color);
+ font-style: italic;
+ }
+}
+
+.search-suggestions {
+ background: var(--suggestions-bg, @suggestions-bg);
+ color: var(--suggestions-color, @suggestions-color);
+ border: 1px solid var(--suggestions-border-color, @suggestions-border-color);
+ border-bottom-right-radius: .5em;
+ border-bottom-left-radius: .5em;
+
+ > ul {
+ list-style-type: none;
+
+ > li {
+ border-top: 1px solid var(--suggestions-separation-bg, @suggestions-separation-bg);
+ }
+ > li.suggestion-title + li {
+ border: none;
+ }
+ > li:not(.default) + li.suggestion-title {
+ border: none;
+ }
+ }
+
+ .default {
+ color: var(--suggestions-default-opt-color, @suggestions-default-opt-color);
+ font-style: italic;
+
+ [type="button"] {
+ background-color: var(--suggestions-default-opt-bg, @suggestions-default-opt-bg);
+ }
+ }
+
+ .suggestion-title {
+ font-size: 80%;
+ }
+
+ .failure-message {
+ font-weight: bold;
+
+ em {
+ font-weight: normal;
+ color: var(--suggestions-failure-message-color, @suggestions-failure-message-color);
+ }
+ }
+
+ .nothing-to-suggest {
+ color: var(--suggestions-color, @suggestions-color);
+ }
+
+ .relation-path {
+ padding: 0 .2em;
+ background-color: var(--suggestions-relation-path-bg, @suggestions-relation-path-bg);
+ }
+
+ [type="button"] {
+ .appearance(none);
+ border: none;
+ background: none;
+ }
+
+ [type="button"]:focus,
+ [type="button"].selected {
+ background: var(--suggestions-focus-bg, @suggestions-focus-bg);
+ color: var(--suggestions-focus-color, @suggestions-focus-color);
+ outline: none;
+
+ .relation-path {
+ background-color: var(--suggestions-relation-path-focus-bg, @suggestions-relation-path-focus-bg);
+ }
+ }
+
+ [type="button"]:not(:focus):hover,
+ [type="button"]:not(.selected):hover {
+ background: var(--suggestions-hover-bg, @suggestions-hover-bg);
+ }
+}
+
+// Layout
+.search-bar .filter-input-area,
+.term-input-area:not(.vertical) {
+ overflow: auto hidden;
+ overflow-x: overlay; // Not invalid, but proprietary feature by chrome/webkit
+ display: flex;
+ flex-wrap: nowrap;
+ width: 100%;
+ height: ~"calc(2em + 10px)"; // Search bar height + approximate scrollbar height
+
+ // Lets inputs grow based on their contents, Inspired by https://css-tricks.com/auto-growing-inputs-textareas/
+ label {
+ position: relative;
+ display: inline-block;
+ min-width: 2em;
+ height: 100%;
+
+ &::after,
+ input {
+ width: auto;
+ padding: .25em .5em;
+ resize: none;
+ }
+
+ input {
+ width: 100%;
+ position: absolute;
+ top: 0;
+ line-height: 20/12; // 20 (px) desired / default font size (px)
+ }
+
+ &::after {
+ height: 0;
+ content: attr(data-label);
+ visibility: hidden;
+ white-space: nowrap;
+ padding: 0 7/12em; // 7 (px) desired / default font size (px)
+ }
+ }
+
+ > label {
+ flex: 1 0 auto;
+
+ &::after,
+ input {
+ max-width: none;
+ min-width: 8em;
+ }
+ }
+
+ > .terms {
+ display: inline;
+ flex-shrink: 0;
+
+ label {
+ margin-right: 1px;
+ }
+ }
+}
+
+.term-input-area.vertical {
+ display: flex;
+ flex-direction: column-reverse;
+
+ > .terms {
+ @gap: 1px;
+ @termsPerRow: 2;
+
+ display: flex;
+ flex-wrap: wrap;
+ gap: @gap;
+ margin-top: @gap;
+
+ label {
+ @termWidth: 100%/@termsPerRow;
+ @totalGapWidthPerRow: (@termsPerRow - 1) * @gap;
+
+ min-width: ~"calc(@{termWidth} - (@{totalGapWidthPerRow} / @{termsPerRow}))";
+ flex: 1 1 auto;
+
+ input {
+ text-overflow: ellipsis;
+ }
+ }
+ }
+}
+
+.term-input-area {
+ label input:focus {
+ @labelPad: 7/12em;
+ outline-width: 3px;
+ outline-offset: ~"calc(-@{labelPad} + 3px)";
+ }
+}
+
+.search-suggestions {
+ z-index: 2; // Required so that nothing else can overlap it (such as opaque elements and the impact overlay)
+ position: absolute;
+ overflow: auto;
+ min-width: 5em;
+
+ &:empty {
+ display: none;
+ }
+
+ > ul {
+ margin: 0;
+ padding: 0;
+
+ li.suggestion-title {
+ padding: 1.25em .625em 0 .625em;
+ }
+
+ li.failure-message {
+ padding: .5em 1em;
+
+ em {
+ margin-right: .5em;
+ }
+ }
+
+ li.nothing-to-suggest {
+ padding: .5em 1em;
+ }
+ }
+
+ [type="button"] {
+ padding: .5em 1em;
+ display: block;
+ width: 100%;
+ text-align: left;
+
+ &[data-class="operator"], &[data-class="logical_operator"] {
+ text-align: center;
+ }
+
+ &.has-details {
+ display: flex;
+ align-items: baseline;
+ justify-content: space-between;
+ }
+
+ .relation-path {
+ margin-left: .5em;
+
+ &::first-line {
+ font-size: .8em;
+ }
+ }
+ }
+}
diff --git a/asset/css/search-editor.less b/asset/css/search-editor.less
new file mode 100644
index 0000000..d32d31c
--- /dev/null
+++ b/asset/css/search-editor.less
@@ -0,0 +1,268 @@
+// Style
+
+.search-editor {
+ ul, ol {
+ list-style-type: none;
+ }
+
+ fieldset {
+ border: none;
+ }
+
+ button, input[type="submit"] {
+ .appearance(none);
+ background: none;
+
+ &:not(.cancel-button) {
+ border: none;
+ }
+ }
+
+ select:not([multiple]) {
+ .appearance(none);
+ padding-right: 1.5625em;
+ background-image: url('@{iplWebAssets}/img/select-icon-text-color.svg');
+ background-repeat: no-repeat;
+ background-position: right center;
+ background-size: contain;
+ .rounded-corners(0);
+ }
+
+ i.icon:before {
+ color: var(--search-editor-control-color, @search-editor-control-color);
+ }
+
+ .drag-initiator {
+ cursor: grab;
+ }
+
+ input[type="text"], select {
+ border: none;
+ background: var(--search-term-bg, @search-term-bg);
+ color: var(--search-term-color, @search-term-color);
+ text-overflow: ellipsis;
+ }
+
+ :not(fieldset) > select {
+ .rounded-corners();
+ }
+
+ fieldset > input[data-type="column"] {
+ .rounded-corners(.4em 0 0 .4em);
+ }
+
+ fieldset > input[data-type="value"] {
+ .rounded-corners(0 .4em .4em 0);
+ }
+
+ .search-error {
+ input:invalid {
+ background: var(--search-term-invalid-bg, @search-term-invalid-bg);
+ color: var(--search-term-invalid-color, @search-term-invalid-color);
+ }
+
+ .search-errors {
+ color: var(--search-editor-error-color, @search-editor-error-color);
+ font-weight: bold;
+ }
+ }
+
+ li > select:not([multiple]) {
+ background-color: var(--search-logical-operator-bg, @search-logical-operator-bg);
+ color: var(--search-logical-operator-color, @search-logical-operator-color);
+ .rounded-corners();
+ }
+
+ .sortable-ghost {
+ border: dashed .2em var(--search-editor-drag-outline-color, @search-editor-drag-outline-color);
+
+ fieldset {
+ opacity: .5;
+ }
+ }
+
+ .buttons {
+ ul {
+ .rounded-corners();
+ .box-shadow(0, 0, .5em);
+ border: 1px solid var(--search-editor-context-menu-border-color, @search-editor-context-menu-border-color);
+ background: var(--search-editor-context-menu-bg, @search-editor-context-menu-bg);
+
+ li:not(:first-child) {
+ border-top: 1px solid var(--search-editor-context-menu-border-color, @search-editor-context-menu-border-color);
+ }
+
+ button:hover {
+ background: var(--primary-button-bg, @primary-button-bg);
+ color: var(--primary-button-color, @primary-button-color);
+ }
+
+ // Add rounded corners to buttons as well, otherwise their
+ // background is not rounded and overlaps the list's corners
+ :first-child button {
+ .rounded-corners();
+ border-bottom-left-radius: 0;
+ border-bottom-right-radius: 0;
+ }
+ :last-child button {
+ .rounded-corners();
+ border-top-left-radius: 0;
+ border-top-right-radius: 0;
+ }
+
+ &:before {
+ // The left pointing arrow
+ border-bottom: 1px solid var(--search-editor-context-menu-border-color, @search-editor-context-menu-border-color);
+ border-left: 1px solid var(--search-editor-context-menu-border-color, @search-editor-context-menu-border-color);
+ background: var(--search-editor-context-menu-bg, @search-editor-context-menu-bg);
+ }
+ }
+
+ &:hover i.icon:before {
+ .rounded-corners();
+ background: var(--primary-button-bg, @primary-button-bg);
+ color: var(--primary-button-color, @primary-button-color);
+ }
+ }
+
+ input[type="submit"] {
+ .rounded-corners();
+ background: var(--primary-button-bg, @primary-button-bg);
+ color: var(--primary-button-color, @primary-button-color);
+
+ &:hover {
+ background: var(--primary-button-hover-bg, @primary-button-hover-bg);
+ }
+ }
+}
+
+// Layout
+
+.search-editor-opener + a.modal-opener {
+ display: none;
+}
+
+.search-editor {
+ padding: 1em;
+
+ @item-spacing: .5em;
+
+ ul, ol {
+ width: 100%;
+ margin: 0;
+ padding: 0;
+ }
+
+ li {
+ display: flex;
+
+ > :not(:first-child) {
+ margin-left: @item-spacing;
+ }
+ }
+
+ ol {
+ padding-left: 1em;
+ padding-bottom: @item-spacing;
+
+ > li:first-child,
+ > :not(.filter-chain) + li {
+ margin-top: @item-spacing;
+ }
+ }
+
+ input[type="text"], select {
+ padding: 0 .5em;
+ }
+
+ li > select {
+ margin-right: auto;
+ }
+
+ fieldset {
+ display: flex;
+ flex: 1 1 auto;
+ margin: 0;
+ padding: 0;
+
+ input[data-type="value"] {
+ flex: 1 1 auto;
+ }
+
+ > :not(:first-child) {
+ margin-left: .1em;
+ }
+ }
+
+ input, button, select {
+ height: 28/12em; // Target Pixels @ default font size / default font size
+ }
+
+ .search-errors {
+ margin-left: .5em;
+ }
+
+ i.icon:before {
+ margin: 0;
+ font-size: 1.5em;
+ line-height: 1.5;
+ }
+
+ .buttons {
+ position: relative;
+
+ ul {
+ position: absolute;
+ right: 32/12em; // Target distance @ default font size / default font size
+ z-index: 1;
+ width: auto;
+ padding: 0;
+
+ display: none;
+
+ button {
+ z-index: 1;
+ width: 100%;
+ text-align: left;
+ white-space: nowrap;
+ }
+
+ &:before {
+ // The left pointing arrow
+ content: "";
+ display: block;
+ height: 1em;
+ transform: rotate(-135deg);
+ width: 1em;
+ z-index: 1;
+
+ position: absolute;
+ top: ((28/12)/2)-.5em; // ((First row pixels @ default font size / default font size) / 2) - own half width
+ right: -.5em;
+ }
+ }
+
+ &:hover ul {
+ display: block;
+ }
+
+ i.icon:before {
+ padding: ((28/18)-1)/2em; // (Container pixels / default font size) - line height / (padding-top,padding-bottom)
+ line-height: 1;
+ }
+ }
+
+ .cancel-button {
+ margin-top: 2em - @item-spacing;
+ }
+
+ input[type="submit"] {
+ float: right;
+ width: 6em;
+ margin-top: 2em - @item-spacing;
+ }
+
+ input[type="submit"]:not(:last-of-type) {
+ display: none;
+ }
+}
diff --git a/asset/css/state-badge.less b/asset/css/state-badge.less
new file mode 100644
index 0000000..25097a8
--- /dev/null
+++ b/asset/css/state-badge.less
@@ -0,0 +1,52 @@
+.state-badge {
+ .rounded-corners();
+ color: var(--default-text-color-inverted, @default-text-color-inverted);
+ display: inline-block;
+ font-size: 1em;
+ min-width: 2em;
+ padding: .25em;
+ text-align: center;
+
+ &.handled {
+ opacity: .8;
+ }
+
+ &.state-critical {
+ background-color: var(--state-critical, @state-critical);
+ }
+
+ &.state-down {
+ background-color: var(--state-down, @state-down);
+ }
+
+ &.state-ok {
+ background-color: var(--state-ok, @state-ok);
+ }
+
+ &.state-pending {
+ background-color: var(--state-pending, @state-pending);
+ }
+
+ &.state-unknown {
+ background-color: var(--state-unknown, @state-unknown);
+ }
+
+ &.state-up {
+ background-color: var(--state-up, @state-up);
+ }
+
+ &.state-warning {
+ background-color: var(--state-warning, @state-warning);
+ }
+
+ &.state-none {
+ background-color: var(--state-none, @state-none);
+ color: var(--text-color-light, @text-color-light);
+ }
+}
+
+a .state-badge {
+ &:not(.disabled):hover {
+ filter: brightness(80%);
+ }
+}
diff --git a/asset/css/variables.less b/asset/css/variables.less
new file mode 100644
index 0000000..a500c5e
--- /dev/null
+++ b/asset/css/variables.less
@@ -0,0 +1,216 @@
+/*
+ RECOMMENDATION:
+ Please do not use the base color variables directly,
+ define a new variable instead that assigns the value of this base variable.
+ Examples:
+ - @base-color: red;
+ - @my-new-var: @base-color;
+ - @my-second-new-var: @base-color;
+
+ Do not use the same variable for different use cases, but define a new variable for each use case.
+
+ NOTICE:
+ Color vars identification:
+ - Vars with `-bg` suffix are background-color vars. Please use only for setting bg-color.
+ - Vars with `-color` suffix are color vars. Please use only for setting fg-color.
+
+ MODE SUPPORT:
+ The standard LESS variables represent the dark mode. The LESS detached ruleset `@iplWebLightRules`
+ contains CSS variables that represent the light mode. It must be used explicitly to have any effect.
+ If you use media queries to support modes, just call the ruleset inside your media query:
+
+ @media (prefers-color-scheme: light) {
+ @iplWebLightRules();
+ }
+*/
+
+@default-bg: #282E39;
+
+@base-gray: #c4c4c4;
+@base-gray-light: #5c5c5c;
+@base-gray-lighter: #4b4b4b;
+@base-gray-semilight: #888;
+@base-disabled: #9a9a9a;
+
+@base-primary-color: #00C3ED;
+@base-primary-bg: #00C3ED;
+@base-primary-dark: #0081a6;
+@base-primary-light: fade(@base-primary-bg, 50%);
+
+@default-text-color: #fff;
+@default-text-color-light: fade(@default-text-color, 75%);
+@default-text-color-inverted: @default-bg;
+@default-input-bg: #404d72;
+
+@state-ok: #44bb77;
+@state-up: @state-ok;
+@state-warning: #ffaa44;
+@state-critical: #ff5566;
+@state-down: @state-critical;
+@state-pending: #77aaff;
+@state-unknown: #aa44ff;
+@state-none: @base-gray-light;
+
+@primary-button-color: @default-text-color-inverted;
+@primary-button-bg: @base-primary-bg;
+@primary-button-hover-bg: @base-primary-dark;
+
+@search-term-bg: @base-gray;
+@search-term-color: @default-text-color-inverted;
+@search-term-selected-bg: @base-disabled;
+@search-term-invalid-bg: @state-critical;
+@search-term-invalid-color: @default-text-color-inverted;
+@search-term-disabled-bg: @base-disabled;
+@search-term-selected-color: @base-gray-light;
+@search-term-highlighted-bg: @base-primary-bg;
+@search-term-highlighted-color: @default-text-color-inverted;
+
+@search-condition-remove-bg: @state-critical;
+@search-condition-remove-color: @default-text-color-inverted;
+
+@search-logical-operator-bg: @base-gray-light;
+@search-logical-operator-color: @default-text-color-light;
+
+@searchbar-bg: @default-input-bg;
+@searchbar-scrollbar-bg: @base-gray-light;
+
+@search-editor-error-color: @state-critical;
+@search-editor-control-color: @base-gray-light;
+@search-editor-logical-op-bg: @base-gray-light;
+@search-editor-context-menu-border-color: @base-gray-light;
+@search-editor-context-menu-bg: @default-bg;
+@search-editor-drag-outline-color: @base-gray;
+
+@control-color: @base-primary-color;
+@control-hover-bg: @base-gray-lighter;
+@control-disabled-color: @base-disabled;
+@controls-separator-bg: @base-gray-lighter;
+
+@cancel-button-bg: none;
+@cancel-button-border-color: @state-critical;
+@cancel-button-color: @state-critical;
+@cancel-button-hover-bg: @state-critical;
+@cancel-button-hover-color: @default-text-color-inverted;
+
+@suggestions-bg: @default-bg;
+@suggestions-color: @default-text-color-light;
+@suggestions-focus-bg: @base-primary-bg;
+@suggestions-focus-color: @default-text-color-inverted;
+@suggestions-default-opt-bg: fade(@base-primary-bg, 10%);
+@suggestions-default-opt-color: @default-text-color-light;
+@suggestions-hover-bg: fade(@base-primary-bg, 30%);
+@suggestions-border-color: @base-gray-light;
+@suggestions-separation-bg: @base-gray-lighter;
+@suggestions-failure-message-color: @default-text-color-light;
+@suggestions-relation-path-bg: @base-gray-light;
+@suggestions-relation-path-focus-bg: @base-gray;
+
+@card-border-color: @base-gray-light;
+
+@schedule-element-fields-bg: @default-input-bg;
+@schedule-element-fields-color: @base-primary-color;
+@schedule-element-fields-border-color: @base-gray-light;
+@schedule-element-fields-selected-bg: @primary-button-bg;
+@schedule-element-fields-selected-color: @default-text-color-inverted;
+@schedule-element-fields-hover-bg: @base-primary-light;
+@schedule-element-fields-outline-color: fade(@base-primary-bg, 50%);
+@schedule-element-fields-selected-outline-color: fade(#fff, 50%);
+@schedule-element-fields-selected-hover-bg: @primary-button-hover-bg;
+@schedule-element-fields-disabled-color: @base-gray;
+@schedule-element-fields-disabled-bg: @base-gray-lighter;
+@schedule-element-fields-disabled-selected-bg: @base-gray-light;
+@schedule-element-keyboard-note-bg: @base-gray-light;
+
+@empty-state-color: @base-gray-semilight;
+@empty-state-bar-bg: @base-gray-lighter;
+
+@list-item-title-hover-color: @base-primary-color;
+@list-item-separation-bg: @base-gray-light;
+
+@iplWebLightRules: {
+ :root {
+ --base-gray: #819398;
+ --base-gray-light: #d0d3da;
+ --base-gray-lighter: #e8ecef;
+ --base-gray-semilight: #94a5a6;
+ --base-disabled: var(--base-gray-light);
+
+ --base-remove-bg: @state-critical;
+
+ --default-text-color: #535353;
+ --default-text-color-light: fade(#535353, 75%); // --default-text-color
+ --default-text-color-inverted: #F5F9FA;
+ --default-input-bg: #DEECF1;
+
+ --primary-button-color: var(--default-text-color-inverted);
+ --primary-button-bg: @primary-button-bg;
+ --primary-button-hover-bg: @primary-button-hover-bg;
+
+ --searchbar-bg: var(--default-input-bg);
+ --searchbar-scrollbar-bg: var(--base-gray-light);
+
+ --search-term-bg: var(--base-gray-light);
+ --search-term-color: var(--default-text-color);
+ --search-term-selected-bg: var(--base-disabled);
+ --search-term-invalid-bg: var(--base-remove-bg);
+ --search-term-invalid-color: var(--default-text-color-inverted);
+ --search-term-disabled-bg: var(--base-gray-light);
+ --search-term-selected-color: var(--base-gray);
+ --search-term-highlighted-bg: var(--primary-button-bg);
+ --search-term-highlighted-color: var(--default-text-color-inverted);
+
+ --search-condition-remove-bg: var(--base-remove-bg);
+ --search-condition-remove-color: var(--default-text-color-inverted);
+
+ --search-logical-operator-bg: fade(#819398, 50%); // --base-gray
+ --search-logical-operator-color: var(--default-text-color-light);
+
+ --search-editor-error-color: var(--base-remove-bg);
+ --search-editor-control-color: var(--base-gray-light);
+ --search-editor-logical-op-bg: var(--base-gray-light);
+ --search-editor-context-menu-border-color: var(--base-gray-light);
+ --search-editor-context-menu-bg: var(--default-text-color-inverted);
+ --search-editor-drag-outline-color: var(--base-gray);
+
+ --control-color: var(--primary-button-bg);
+ --control-hover-bg: var(--base-gray-lighter);
+ --control-disabled-color: var(--base-gray-light);
+
+ --cancel-button-hover-color: var(--default-text-color-inverted);
+
+ --suggestions-bg: var(--default-text-color-inverted);
+ --suggestions-color: var(--default-text-color-light);
+ --suggestions-focus-bg: var(--primary-button-bg);
+ --suggestions-focus-color: var(--default-text-color-inverted);
+ --suggestions-default-opt-bg: fade(@primary-button-bg, 10%);
+ --suggestions-default-opt-color: var(--default-text-color-light);
+ --suggestions-hover-bg: fade(@primary-button-bg, 30%);
+ --suggestions-border-color: var(--base-gray-light);
+ --suggestions-separation-bg: var(--base-gray-lighter);
+ --suggestions-failure-message-color: var(--default-text-color-light);
+ --suggestions-relation-path-bg: var(--base-gray-lighter);
+ --suggestions-relation-path-focus-bg: var(--base-gray);
+
+ --card-border-color: var(--base-gray-light);
+
+ --schedule-element-fields-bg: var(--default-input-bg);
+ --schedule-element-fields-color: var(--base-primary-color);
+ --schedule-element-fields-border-color: var(--base-gray-light);
+ --schedule-element-fields-selected-bg: var(--primary-button-bg);
+ --schedule-element-fields-selected-color: var(--default-text-color-inverted);
+ --schedule-element-fields-hover-bg: @base-primary-light;
+ --schedule-element-fields-outline-color: fade(@base-primary-bg, 50%);
+ --schedule-element-fields-selected-outline-color: fade(#fff, 50%);
+ --schedule-element-fields-selected-hover-bg: var(--primary-button-hover-bg);
+ --schedule-element-fields-disabled-color: var(--base-gray);
+ --schedule-element-fields-disabled-bg: var(--base-gray-lighter);
+ --schedule-element-fields-disabled-selected-bg: var(--base-gray-light);
+ --schedule-element-keyboard-note-bg: var(--base-gray-light);
+
+ --empty-state-color: var(--base-gray-semilight);
+ --empty-state-bar-bg: var(--base-gray-lighter);
+
+ --list-item-title-hover-color: var(--base-primary-color);
+ --list-item-separation-bg: var(--base-gray-light);
+ }
+};
diff --git a/asset/css/vendor/flatpickr.css b/asset/css/vendor/flatpickr.css
new file mode 100644
index 0000000..be7168c
--- /dev/null
+++ b/asset/css/vendor/flatpickr.css
@@ -0,0 +1,791 @@
+.flatpickr-calendar {
+ background: transparent;
+ opacity: 0;
+ display: none;
+ text-align: center;
+ visibility: hidden;
+ padding: 0;
+ -webkit-animation: none;
+ animation: none;
+ direction: ltr;
+ border: 0;
+ font-size: 14px;
+ line-height: 24px;
+ border-radius: 5px;
+ position: absolute;
+ width: 307.875px;
+ -webkit-box-sizing: border-box;
+ box-sizing: border-box;
+ -ms-touch-action: manipulation;
+ touch-action: manipulation;
+ background: #fff;
+ -webkit-box-shadow: 1px 0 0 #e6e6e6, -1px 0 0 #e6e6e6, 0 1px 0 #e6e6e6, 0 -1px 0 #e6e6e6, 0 3px 13px rgba(0,0,0,0.08);
+ box-shadow: 1px 0 0 #e6e6e6, -1px 0 0 #e6e6e6, 0 1px 0 #e6e6e6, 0 -1px 0 #e6e6e6, 0 3px 13px rgba(0,0,0,0.08);
+}
+.flatpickr-calendar.open,
+.flatpickr-calendar.inline {
+ opacity: 1;
+ max-height: 640px;
+ visibility: visible;
+}
+.flatpickr-calendar.open {
+ display: inline-block;
+ z-index: 99999;
+}
+.flatpickr-calendar.animate.open {
+ -webkit-animation: fpFadeInDown 300ms cubic-bezier(0.23, 1, 0.32, 1);
+ animation: fpFadeInDown 300ms cubic-bezier(0.23, 1, 0.32, 1);
+}
+.flatpickr-calendar.inline {
+ display: block;
+ position: relative;
+ top: 2px;
+}
+.flatpickr-calendar.static {
+ position: absolute;
+ top: calc(100% + 2px);
+}
+.flatpickr-calendar.static.open {
+ z-index: 999;
+ display: block;
+}
+.flatpickr-calendar.multiMonth .flatpickr-days .dayContainer:nth-child(n+1) .flatpickr-day.inRange:nth-child(7n+7) {
+ -webkit-box-shadow: none !important;
+ box-shadow: none !important;
+}
+.flatpickr-calendar.multiMonth .flatpickr-days .dayContainer:nth-child(n+2) .flatpickr-day.inRange:nth-child(7n+1) {
+ -webkit-box-shadow: -2px 0 0 #e6e6e6, 5px 0 0 #e6e6e6;
+ box-shadow: -2px 0 0 #e6e6e6, 5px 0 0 #e6e6e6;
+}
+.flatpickr-calendar .hasWeeks .dayContainer,
+.flatpickr-calendar .hasTime .dayContainer {
+ border-bottom: 0;
+ border-bottom-right-radius: 0;
+ border-bottom-left-radius: 0;
+}
+.flatpickr-calendar .hasWeeks .dayContainer {
+ border-left: 0;
+}
+.flatpickr-calendar.hasTime .flatpickr-time {
+ height: 40px;
+ border-top: 1px solid #e6e6e6;
+}
+.flatpickr-calendar.noCalendar.hasTime .flatpickr-time {
+ height: auto;
+}
+.flatpickr-calendar:before,
+.flatpickr-calendar:after {
+ position: absolute;
+ display: block;
+ pointer-events: none;
+ border: solid transparent;
+ content: '';
+ height: 0;
+ width: 0;
+ left: 22px;
+}
+.flatpickr-calendar.rightMost:before,
+.flatpickr-calendar.arrowRight:before,
+.flatpickr-calendar.rightMost:after,
+.flatpickr-calendar.arrowRight:after {
+ left: auto;
+ right: 22px;
+}
+.flatpickr-calendar.arrowCenter:before,
+.flatpickr-calendar.arrowCenter:after {
+ left: 50%;
+ right: 50%;
+}
+.flatpickr-calendar:before {
+ border-width: 5px;
+ margin: 0 -5px;
+}
+.flatpickr-calendar:after {
+ border-width: 4px;
+ margin: 0 -4px;
+}
+.flatpickr-calendar.arrowTop:before,
+.flatpickr-calendar.arrowTop:after {
+ bottom: 100%;
+}
+.flatpickr-calendar.arrowTop:before {
+ border-bottom-color: #e6e6e6;
+}
+.flatpickr-calendar.arrowTop:after {
+ border-bottom-color: #fff;
+}
+.flatpickr-calendar.arrowBottom:before,
+.flatpickr-calendar.arrowBottom:after {
+ top: 100%;
+}
+.flatpickr-calendar.arrowBottom:before {
+ border-top-color: #e6e6e6;
+}
+.flatpickr-calendar.arrowBottom:after {
+ border-top-color: #fff;
+}
+.flatpickr-calendar:focus {
+ outline: 0;
+}
+.flatpickr-wrapper {
+ position: relative;
+ display: inline-block;
+}
+.flatpickr-months {
+ display: -webkit-box;
+ display: -webkit-flex;
+ display: -ms-flexbox;
+ display: flex;
+}
+.flatpickr-months .flatpickr-month {
+ background: transparent;
+ color: rgba(0,0,0,0.9);
+ fill: rgba(0,0,0,0.9);
+ height: 34px;
+ line-height: 1;
+ text-align: center;
+ position: relative;
+ -webkit-user-select: none;
+ -moz-user-select: none;
+ -ms-user-select: none;
+ user-select: none;
+ overflow: hidden;
+ -webkit-box-flex: 1;
+ -webkit-flex: 1;
+ -ms-flex: 1;
+ flex: 1;
+}
+.flatpickr-months .flatpickr-prev-month,
+.flatpickr-months .flatpickr-next-month {
+ text-decoration: none;
+ cursor: pointer;
+ position: absolute;
+ top: 0;
+ height: 34px;
+ padding: 10px;
+ z-index: 3;
+ color: rgba(0,0,0,0.9);
+ fill: rgba(0,0,0,0.9);
+}
+.flatpickr-months .flatpickr-prev-month.flatpickr-disabled,
+.flatpickr-months .flatpickr-next-month.flatpickr-disabled {
+ display: none;
+}
+.flatpickr-months .flatpickr-prev-month i,
+.flatpickr-months .flatpickr-next-month i {
+ position: relative;
+}
+.flatpickr-months .flatpickr-prev-month.flatpickr-prev-month,
+.flatpickr-months .flatpickr-next-month.flatpickr-prev-month {
+ /*
+ /*rtl:begin:ignore*/
+ /*
+ */
+ left: 0;
+ /*
+ /*rtl:end:ignore*/
+ /*
+ */
+}
+/*
+ /*rtl:begin:ignore*/
+/*
+ /*rtl:end:ignore*/
+.flatpickr-months .flatpickr-prev-month.flatpickr-next-month,
+.flatpickr-months .flatpickr-next-month.flatpickr-next-month {
+ /*
+ /*rtl:begin:ignore*/
+ /*
+ */
+ right: 0;
+ /*
+ /*rtl:end:ignore*/
+ /*
+ */
+}
+/*
+ /*rtl:begin:ignore*/
+/*
+ /*rtl:end:ignore*/
+.flatpickr-months .flatpickr-prev-month:hover,
+.flatpickr-months .flatpickr-next-month:hover {
+ color: #959ea9;
+}
+.flatpickr-months .flatpickr-prev-month:hover svg,
+.flatpickr-months .flatpickr-next-month:hover svg {
+ fill: #f64747;
+}
+.flatpickr-months .flatpickr-prev-month svg,
+.flatpickr-months .flatpickr-next-month svg {
+ width: 14px;
+ height: 14px;
+}
+.flatpickr-months .flatpickr-prev-month svg path,
+.flatpickr-months .flatpickr-next-month svg path {
+ -webkit-transition: fill 0.1s;
+ transition: fill 0.1s;
+ fill: inherit;
+}
+.numInputWrapper {
+ position: relative;
+ height: auto;
+}
+.numInputWrapper input,
+.numInputWrapper span {
+ display: inline-block;
+}
+.numInputWrapper input {
+ width: 100%;
+}
+.numInputWrapper input::-ms-clear {
+ display: none;
+}
+.numInputWrapper input::-webkit-outer-spin-button,
+.numInputWrapper input::-webkit-inner-spin-button {
+ margin: 0;
+ -webkit-appearance: none;
+}
+.numInputWrapper span {
+ position: absolute;
+ right: 0;
+ width: 14px;
+ padding: 0 4px 0 2px;
+ height: 50%;
+ line-height: 50%;
+ opacity: 0;
+ cursor: pointer;
+ border: 1px solid rgba(57,57,57,0.15);
+ -webkit-box-sizing: border-box;
+ box-sizing: border-box;
+}
+.numInputWrapper span:hover {
+ background: rgba(0,0,0,0.1);
+}
+.numInputWrapper span:active {
+ background: rgba(0,0,0,0.2);
+}
+.numInputWrapper span:after {
+ display: block;
+ content: "";
+ position: absolute;
+}
+.numInputWrapper span.arrowUp {
+ top: 0;
+ border-bottom: 0;
+}
+.numInputWrapper span.arrowUp:after {
+ border-left: 4px solid transparent;
+ border-right: 4px solid transparent;
+ border-bottom: 4px solid rgba(57,57,57,0.6);
+ top: 26%;
+}
+.numInputWrapper span.arrowDown {
+ top: 50%;
+}
+.numInputWrapper span.arrowDown:after {
+ border-left: 4px solid transparent;
+ border-right: 4px solid transparent;
+ border-top: 4px solid rgba(57,57,57,0.6);
+ top: 40%;
+}
+.numInputWrapper span svg {
+ width: inherit;
+ height: auto;
+}
+.numInputWrapper span svg path {
+ fill: rgba(0,0,0,0.5);
+}
+.numInputWrapper:hover {
+ background: rgba(0,0,0,0.05);
+}
+.numInputWrapper:hover span {
+ opacity: 1;
+}
+.flatpickr-current-month {
+ font-size: 135%;
+ line-height: inherit;
+ font-weight: 300;
+ color: inherit;
+ position: absolute;
+ width: 75%;
+ left: 12.5%;
+ padding: 7.48px 0 0 0;
+ line-height: 1;
+ height: 34px;
+ display: inline-block;
+ text-align: center;
+ -webkit-transform: translate3d(0px, 0px, 0px);
+ transform: translate3d(0px, 0px, 0px);
+}
+.flatpickr-current-month span.cur-month {
+ font-family: inherit;
+ font-weight: 700;
+ color: inherit;
+ display: inline-block;
+ margin-left: 0.5ch;
+ padding: 0;
+}
+.flatpickr-current-month span.cur-month:hover {
+ background: rgba(0,0,0,0.05);
+}
+.flatpickr-current-month .numInputWrapper {
+ width: 6ch;
+ width: 7ch\0;
+ display: inline-block;
+}
+.flatpickr-current-month .numInputWrapper span.arrowUp:after {
+ border-bottom-color: rgba(0,0,0,0.9);
+}
+.flatpickr-current-month .numInputWrapper span.arrowDown:after {
+ border-top-color: rgba(0,0,0,0.9);
+}
+.flatpickr-current-month input.cur-year {
+ background: transparent;
+ -webkit-box-sizing: border-box;
+ box-sizing: border-box;
+ color: inherit;
+ cursor: text;
+ padding: 0 0 0 0.5ch;
+ margin: 0;
+ display: inline-block;
+ font-size: inherit;
+ font-family: inherit;
+ font-weight: 300;
+ line-height: inherit;
+ height: auto;
+ border: 0;
+ border-radius: 0;
+ vertical-align: initial;
+ -webkit-appearance: textfield;
+ -moz-appearance: textfield;
+ appearance: textfield;
+}
+.flatpickr-current-month input.cur-year:focus {
+ outline: 0;
+}
+.flatpickr-current-month input.cur-year[disabled],
+.flatpickr-current-month input.cur-year[disabled]:hover {
+ font-size: 100%;
+ color: rgba(0,0,0,0.5);
+ background: transparent;
+ pointer-events: none;
+}
+.flatpickr-current-month .flatpickr-monthDropdown-months {
+ appearance: menulist;
+ background: transparent;
+ border: none;
+ border-radius: 0;
+ box-sizing: border-box;
+ color: inherit;
+ cursor: pointer;
+ font-size: inherit;
+ font-family: inherit;
+ font-weight: 300;
+ height: auto;
+ line-height: inherit;
+ margin: -1px 0 0 0;
+ outline: none;
+ padding: 0 0 0 0.5ch;
+ position: relative;
+ vertical-align: initial;
+ -webkit-box-sizing: border-box;
+ -webkit-appearance: menulist;
+ -moz-appearance: menulist;
+ width: auto;
+}
+.flatpickr-current-month .flatpickr-monthDropdown-months:focus,
+.flatpickr-current-month .flatpickr-monthDropdown-months:active {
+ outline: none;
+}
+.flatpickr-current-month .flatpickr-monthDropdown-months:hover {
+ background: rgba(0,0,0,0.05);
+}
+.flatpickr-current-month .flatpickr-monthDropdown-months .flatpickr-monthDropdown-month {
+ background-color: transparent;
+ outline: none;
+ padding: 0;
+}
+.flatpickr-weekdays {
+ background: transparent;
+ text-align: center;
+ overflow: hidden;
+ width: 100%;
+ display: -webkit-box;
+ display: -webkit-flex;
+ display: -ms-flexbox;
+ display: flex;
+ -webkit-box-align: center;
+ -webkit-align-items: center;
+ -ms-flex-align: center;
+ align-items: center;
+ height: 28px;
+}
+.flatpickr-weekdays .flatpickr-weekdaycontainer {
+ display: -webkit-box;
+ display: -webkit-flex;
+ display: -ms-flexbox;
+ display: flex;
+ -webkit-box-flex: 1;
+ -webkit-flex: 1;
+ -ms-flex: 1;
+ flex: 1;
+}
+span.flatpickr-weekday {
+ cursor: default;
+ font-size: 90%;
+ background: transparent;
+ color: rgba(0,0,0,0.54);
+ line-height: 1;
+ margin: 0;
+ text-align: center;
+ display: block;
+ -webkit-box-flex: 1;
+ -webkit-flex: 1;
+ -ms-flex: 1;
+ flex: 1;
+ font-weight: bolder;
+}
+.dayContainer,
+.flatpickr-weeks {
+ padding: 1px 0 0 0;
+}
+.flatpickr-days {
+ position: relative;
+ overflow: hidden;
+ display: -webkit-box;
+ display: -webkit-flex;
+ display: -ms-flexbox;
+ display: flex;
+ -webkit-box-align: start;
+ -webkit-align-items: flex-start;
+ -ms-flex-align: start;
+ align-items: flex-start;
+ width: 307.875px;
+}
+.flatpickr-days:focus {
+ outline: 0;
+}
+.dayContainer {
+ padding: 0;
+ outline: 0;
+ text-align: left;
+ width: 307.875px;
+ min-width: 307.875px;
+ max-width: 307.875px;
+ -webkit-box-sizing: border-box;
+ box-sizing: border-box;
+ display: inline-block;
+ display: -ms-flexbox;
+ display: -webkit-box;
+ display: -webkit-flex;
+ display: flex;
+ -webkit-flex-wrap: wrap;
+ flex-wrap: wrap;
+ -ms-flex-wrap: wrap;
+ -ms-flex-pack: justify;
+ -webkit-justify-content: space-around;
+ justify-content: space-around;
+ -webkit-transform: translate3d(0px, 0px, 0px);
+ transform: translate3d(0px, 0px, 0px);
+ opacity: 1;
+}
+.dayContainer + .dayContainer {
+ -webkit-box-shadow: -1px 0 0 #e6e6e6;
+ box-shadow: -1px 0 0 #e6e6e6;
+}
+.flatpickr-day {
+ background: none;
+ border: 1px solid transparent;
+ border-radius: 150px;
+ -webkit-box-sizing: border-box;
+ box-sizing: border-box;
+ color: #393939;
+ cursor: pointer;
+ font-weight: 400;
+ width: 14.2857143%;
+ -webkit-flex-basis: 14.2857143%;
+ -ms-flex-preferred-size: 14.2857143%;
+ flex-basis: 14.2857143%;
+ max-width: 39px;
+ height: 39px;
+ line-height: 39px;
+ margin: 0;
+ display: inline-block;
+ position: relative;
+ -webkit-box-pack: center;
+ -webkit-justify-content: center;
+ -ms-flex-pack: center;
+ justify-content: center;
+ text-align: center;
+}
+.flatpickr-day.inRange,
+.flatpickr-day.prevMonthDay.inRange,
+.flatpickr-day.nextMonthDay.inRange,
+.flatpickr-day.today.inRange,
+.flatpickr-day.prevMonthDay.today.inRange,
+.flatpickr-day.nextMonthDay.today.inRange,
+.flatpickr-day:hover,
+.flatpickr-day.prevMonthDay:hover,
+.flatpickr-day.nextMonthDay:hover,
+.flatpickr-day:focus,
+.flatpickr-day.prevMonthDay:focus,
+.flatpickr-day.nextMonthDay:focus {
+ cursor: pointer;
+ outline: 0;
+ background: #e6e6e6;
+ border-color: #e6e6e6;
+}
+.flatpickr-day.today {
+ border-color: #959ea9;
+}
+.flatpickr-day.today:hover,
+.flatpickr-day.today:focus {
+ border-color: #959ea9;
+ background: #959ea9;
+ color: #fff;
+}
+.flatpickr-day.selected,
+.flatpickr-day.startRange,
+.flatpickr-day.endRange,
+.flatpickr-day.selected.inRange,
+.flatpickr-day.startRange.inRange,
+.flatpickr-day.endRange.inRange,
+.flatpickr-day.selected:focus,
+.flatpickr-day.startRange:focus,
+.flatpickr-day.endRange:focus,
+.flatpickr-day.selected:hover,
+.flatpickr-day.startRange:hover,
+.flatpickr-day.endRange:hover,
+.flatpickr-day.selected.prevMonthDay,
+.flatpickr-day.startRange.prevMonthDay,
+.flatpickr-day.endRange.prevMonthDay,
+.flatpickr-day.selected.nextMonthDay,
+.flatpickr-day.startRange.nextMonthDay,
+.flatpickr-day.endRange.nextMonthDay {
+ background: #569ff7;
+ -webkit-box-shadow: none;
+ box-shadow: none;
+ color: #fff;
+ border-color: #569ff7;
+}
+.flatpickr-day.selected.startRange,
+.flatpickr-day.startRange.startRange,
+.flatpickr-day.endRange.startRange {
+ border-radius: 50px 0 0 50px;
+}
+.flatpickr-day.selected.endRange,
+.flatpickr-day.startRange.endRange,
+.flatpickr-day.endRange.endRange {
+ border-radius: 0 50px 50px 0;
+}
+.flatpickr-day.selected.startRange + .endRange:not(:nth-child(7n+1)),
+.flatpickr-day.startRange.startRange + .endRange:not(:nth-child(7n+1)),
+.flatpickr-day.endRange.startRange + .endRange:not(:nth-child(7n+1)) {
+ -webkit-box-shadow: -10px 0 0 #569ff7;
+ box-shadow: -10px 0 0 #569ff7;
+}
+.flatpickr-day.selected.startRange.endRange,
+.flatpickr-day.startRange.startRange.endRange,
+.flatpickr-day.endRange.startRange.endRange {
+ border-radius: 50px;
+}
+.flatpickr-day.inRange {
+ border-radius: 0;
+ -webkit-box-shadow: -5px 0 0 #e6e6e6, 5px 0 0 #e6e6e6;
+ box-shadow: -5px 0 0 #e6e6e6, 5px 0 0 #e6e6e6;
+}
+.flatpickr-day.flatpickr-disabled,
+.flatpickr-day.flatpickr-disabled:hover,
+.flatpickr-day.prevMonthDay,
+.flatpickr-day.nextMonthDay,
+.flatpickr-day.notAllowed,
+.flatpickr-day.notAllowed.prevMonthDay,
+.flatpickr-day.notAllowed.nextMonthDay {
+ color: rgba(57,57,57,0.3);
+ background: transparent;
+ border-color: transparent;
+ cursor: default;
+}
+.flatpickr-day.flatpickr-disabled,
+.flatpickr-day.flatpickr-disabled:hover {
+ cursor: not-allowed;
+ color: rgba(57,57,57,0.1);
+}
+.flatpickr-day.week.selected {
+ border-radius: 0;
+ -webkit-box-shadow: -5px 0 0 #569ff7, 5px 0 0 #569ff7;
+ box-shadow: -5px 0 0 #569ff7, 5px 0 0 #569ff7;
+}
+.flatpickr-day.hidden {
+ visibility: hidden;
+}
+.rangeMode .flatpickr-day {
+ margin-top: 1px;
+}
+.flatpickr-weekwrapper {
+ float: left;
+}
+.flatpickr-weekwrapper .flatpickr-weeks {
+ padding: 0 12px;
+ -webkit-box-shadow: 1px 0 0 #e6e6e6;
+ box-shadow: 1px 0 0 #e6e6e6;
+}
+.flatpickr-weekwrapper .flatpickr-weekday {
+ float: none;
+ width: 100%;
+ line-height: 28px;
+}
+.flatpickr-weekwrapper span.flatpickr-day,
+.flatpickr-weekwrapper span.flatpickr-day:hover {
+ display: block;
+ width: 100%;
+ max-width: none;
+ color: rgba(57,57,57,0.3);
+ background: transparent;
+ cursor: default;
+ border: none;
+}
+.flatpickr-innerContainer {
+ display: block;
+ display: -webkit-box;
+ display: -webkit-flex;
+ display: -ms-flexbox;
+ display: flex;
+ -webkit-box-sizing: border-box;
+ box-sizing: border-box;
+ overflow: hidden;
+}
+.flatpickr-rContainer {
+ display: inline-block;
+ padding: 0;
+ -webkit-box-sizing: border-box;
+ box-sizing: border-box;
+}
+.flatpickr-time {
+ text-align: center;
+ outline: 0;
+ display: block;
+ height: 0;
+ line-height: 40px;
+ max-height: 40px;
+ -webkit-box-sizing: border-box;
+ box-sizing: border-box;
+ overflow: hidden;
+ display: -webkit-box;
+ display: -webkit-flex;
+ display: -ms-flexbox;
+ display: flex;
+}
+.flatpickr-time:after {
+ content: "";
+ display: table;
+ clear: both;
+}
+.flatpickr-time .numInputWrapper {
+ -webkit-box-flex: 1;
+ -webkit-flex: 1;
+ -ms-flex: 1;
+ flex: 1;
+ width: 40%;
+ height: 40px;
+ float: left;
+}
+.flatpickr-time .numInputWrapper span.arrowUp:after {
+ border-bottom-color: #393939;
+}
+.flatpickr-time .numInputWrapper span.arrowDown:after {
+ border-top-color: #393939;
+}
+.flatpickr-time.hasSeconds .numInputWrapper {
+ width: 26%;
+}
+.flatpickr-time.time24hr .numInputWrapper {
+ width: 49%;
+}
+.flatpickr-time input {
+ background: transparent;
+ -webkit-box-shadow: none;
+ box-shadow: none;
+ border: 0;
+ border-radius: 0;
+ text-align: center;
+ margin: 0;
+ padding: 0;
+ height: inherit;
+ line-height: inherit;
+ color: #393939;
+ font-size: 14px;
+ position: relative;
+ -webkit-box-sizing: border-box;
+ box-sizing: border-box;
+ -webkit-appearance: textfield;
+ -moz-appearance: textfield;
+ appearance: textfield;
+}
+.flatpickr-time input.flatpickr-hour {
+ font-weight: bold;
+}
+.flatpickr-time input.flatpickr-minute,
+.flatpickr-time input.flatpickr-second {
+ font-weight: 400;
+}
+.flatpickr-time input:focus {
+ outline: 0;
+ border: 0;
+}
+.flatpickr-time .flatpickr-time-separator,
+.flatpickr-time .flatpickr-am-pm {
+ height: inherit;
+ float: left;
+ line-height: inherit;
+ color: #393939;
+ font-weight: bold;
+ width: 2%;
+ -webkit-user-select: none;
+ -moz-user-select: none;
+ -ms-user-select: none;
+ user-select: none;
+ -webkit-align-self: center;
+ -ms-flex-item-align: center;
+ align-self: center;
+}
+.flatpickr-time .flatpickr-am-pm {
+ outline: 0;
+ width: 18%;
+ cursor: pointer;
+ text-align: center;
+ font-weight: 400;
+}
+.flatpickr-time input:hover,
+.flatpickr-time .flatpickr-am-pm:hover,
+.flatpickr-time input:focus,
+.flatpickr-time .flatpickr-am-pm:focus {
+ background: #eee;
+}
+.flatpickr-input[readonly] {
+ cursor: pointer;
+}
+@-webkit-keyframes fpFadeInDown {
+ from {
+ opacity: 0;
+ -webkit-transform: translate3d(0, -20px, 0);
+ transform: translate3d(0, -20px, 0);
+ }
+ to {
+ opacity: 1;
+ -webkit-transform: translate3d(0, 0, 0);
+ transform: translate3d(0, 0, 0);
+ }
+}
+@keyframes fpFadeInDown {
+ from {
+ opacity: 0;
+ -webkit-transform: translate3d(0, -20px, 0);
+ transform: translate3d(0, -20px, 0);
+ }
+ to {
+ opacity: 1;
+ -webkit-transform: translate3d(0, 0, 0);
+ transform: translate3d(0, 0, 0);
+ }
+}
diff --git a/asset/css/vendor/flatpickr.vars.less b/asset/css/vendor/flatpickr.vars.less
new file mode 100644
index 0000000..2409667
--- /dev/null
+++ b/asset/css/vendor/flatpickr.vars.less
@@ -0,0 +1,327 @@
+/**
+ * This file's only purpose is to make the flatpickr themeable. DO NOT add ANY custom style here!
+ * Also, DO NOT re-arrange the CSS blocks to make them more LESS like. They're based off of the
+ * pre-compiled flatpickr.css file and so can easily identified when updating to a new version.
+ *
+ * Non-standard LESS variables were added to allow usage of CSS variables. All of them hold a
+ * value calculated by LESS functions. If not temporarily stored in another LESS variable,
+ * they wouldn't be available to CSS variable usage.
+ *
+ * Latest state from version: v4.6.9
+ */
+
+@fp-calendarBackground: #ffffff;
+@fp-calendarBorderColor: #e6e6e6;
+
+@fp-arrowColor: fadeout(@fp-dayForeground, 40%); // Non-standard variable
+@fp-arrow_hover_color: #f64747;
+
+@fp-monthForeground: fadeout(black, 10%);
+@fp-monthBackground: transparent;
+
+@fp-weekdaysBackground: transparent;
+@fp-weekdaysForeground: fadeout(black, 46%);
+@fp-weekNumberForeground: fadeout(@fp-dayForeground, 70%); // Non-standard variable
+
+@fp-dayForeground: #393939;
+@fp-dayHoverBackground: #e6e6e6;
+@fp-disabledDayForeground: fadeout(@fp-dayForeground, 90%); // Non-standard variable
+@fp-outsideRangeDayForeground: @fp-weekNumberForeground; // Non-standard variable
+@fp-selectedDayBackground: #569FF7;
+@fp-todayColor: #959ea9;
+
+@fp-timeHoverBg: lighten(@fp-dayHoverBackground, 3); // Non-standard variable
+
+@fp-invertedBg: black;
+@fp-hoverInvertedBg: fadeout(@fp-invertedBg, 95%); // Non-standard variable
+
+@fp-numChooserSvgFillColor: fadeout(@fp-monthForeground, 50%); // Non-standard variable
+@fp-hoverNumChooserBg: fadeout(@fp-invertedBg, 90%); // Non-standard variable
+@fp-numChooserBorderColor: fadeout(@fp-dayForeground, 85%); // Non-standard variable
+
+.icinga-datetime-picker {
+ &.flatpickr-calendar {
+ background: @fp-calendarBackground;
+ background: var(--fp-calendarBackground, @fp-calendarBackground);
+ box-shadow: 1px 0 0 @fp-calendarBorderColor,
+ -1px 0 0 @fp-calendarBorderColor,
+ 0 1px 0 @fp-calendarBorderColor,
+ 0 -1px 0 @fp-calendarBorderColor,
+ 0 3px 13px fadeout(black, 92%);
+ box-shadow: 1px 0 0 var(--fp-calendarBorderColor, @fp-calendarBorderColor),
+ -1px 0 0 var(--fp-calendarBorderColor, @fp-calendarBorderColor),
+ 0 1px 0 var(--fp-calendarBorderColor, @fp-calendarBorderColor),
+ 0 -1px 0 var(--fp-calendarBorderColor, @fp-calendarBorderColor),
+ 0 3px 13px fadeout(black, 92%);
+ }
+
+ &.flatpickr-calendar.arrowTop:before {
+ border-bottom-color: @fp-calendarBorderColor;
+ border-bottom-color: var(--fp-calendarBorderColor, @fp-calendarBorderColor);
+ }
+ &.flatpickr-calendar.arrowTop:after {
+ border-bottom-color: @fp-calendarBackground;
+ border-bottom-color: var(--fp-calendarBackground, @fp-calendarBackground);
+ }
+ &.flatpickr-calendar.arrowBottom:before {
+ border-top-color: @fp-calendarBorderColor;
+ border-top-color: var(--fp-calendarBorderColor, @fp-calendarBorderColor);
+ }
+ &.flatpickr-calendar.arrowBottom:after {
+ border-top-color: @fp-calendarBackground;
+ border-top-color: var(--fp-calendarBackground, @fp-calendarBackground);
+ }
+
+ &.flatpickr-calendar.hasTime .flatpickr-time {
+ border-top-color: @fp-calendarBorderColor;
+ border-top-color: var(--fp-calendarBorderColor, @fp-calendarBorderColor);
+ }
+
+ .dayContainer + .dayContainer {
+ -webkit-box-shadow: -1px 0 0 @fp-calendarBorderColor;
+ -webkit-box-shadow: -1px 0 0 var(--fp-calendarBorderColor, @fp-calendarBorderColor);
+ box-shadow: -1px 0 0 @fp-calendarBorderColor;
+ box-shadow: -1px 0 0 var(--fp-calendarBorderColor, @fp-calendarBorderColor);
+ }
+
+ .flatpickr-day {
+ color: @fp-dayForeground;
+ color: var(--fp-dayForeground, @fp-dayForeground);
+ }
+ .flatpickr-day.today {
+ border-color: @fp-todayColor;
+ border-color: var(--fp-todayColor, @fp-todayColor);
+ }
+ .flatpickr-day.today:hover,
+ .flatpickr-day.today:focus {
+ border-color: @fp-todayColor;
+ border-color: var(--fp-todayColor, @fp-todayColor);
+ background: @fp-todayColor;
+ background: var(--fp-todayColor, @fp-todayColor);
+ color: @fp-calendarBackground;
+ color: var(--fp-calendarBackground, @fp-calendarBackground);
+ }
+ .flatpickr-day.selected,
+ .flatpickr-day.startRange,
+ .flatpickr-day.endRange,
+ .flatpickr-day.selected.inRange,
+ .flatpickr-day.startRange.inRange,
+ .flatpickr-day.endRange.inRange,
+ .flatpickr-day.selected:focus,
+ .flatpickr-day.startRange:focus,
+ .flatpickr-day.endRange:focus,
+ .flatpickr-day.selected:hover,
+ .flatpickr-day.startRange:hover,
+ .flatpickr-day.endRange:hover,
+ .flatpickr-day.selected.prevMonthDay,
+ .flatpickr-day.startRange.prevMonthDay,
+ .flatpickr-day.endRange.prevMonthDay,
+ .flatpickr-day.selected.nextMonthDay,
+ .flatpickr-day.startRange.nextMonthDay,
+ .flatpickr-day.endRange.nextMonthDay {
+ color: @fp-calendarBackground;
+ color: var(--fp-calendarBackground, @fp-calendarBackground);
+ }
+ .flatpickr-day.inRange,
+ .flatpickr-day.prevMonthDay.inRange,
+ .flatpickr-day.nextMonthDay.inRange,
+ .flatpickr-day.today.inRange,
+ .flatpickr-day.prevMonthDay.today.inRange,
+ .flatpickr-day.nextMonthDay.today.inRange,
+ .flatpickr-day:hover,
+ .flatpickr-day.prevMonthDay:hover,
+ .flatpickr-day.nextMonthDay:hover,
+ .flatpickr-day:focus,
+ .flatpickr-day.nextMonthDay:focus {
+ background: @fp-dayHoverBackground;
+ background: var(--fp-dayHoverBackground, @fp-dayHoverBackground);
+ border-color: @fp-dayHoverBackground;
+ border-color: var(--fp-dayHoverBackground, @fp-dayHoverBackground);
+ }
+ .flatpickr-day.inRange {
+ -webkit-box-shadow: -5px 0 0 @fp-dayHoverBackground, 5px 0 0 @fp-dayHoverBackground;
+ -webkit-box-shadow: -5px 0 0 var(--fp-dayHoverBackground, @fp-dayHoverBackground),
+ 5px 0 0 var(--fp-dayHoverBackground, @fp-dayHoverBackground);
+ box-shadow: -5px 0 0 @fp-dayHoverBackground, 5px 0 0 @fp-dayHoverBackground;
+ box-shadow: -5px 0 0 var(--fp-dayHoverBackground, @fp-dayHoverBackground),
+ 5px 0 0 var(--fp-dayHoverBackground, @fp-dayHoverBackground);
+ }
+ .flatpickr-day.prevMonthDay,
+ .flatpickr-day.nextMonthDay,
+ .flatpickr-day.notAllowed,
+ .flatpickr-day.notAllowed.prevMonthDay,
+ .flatpickr-day.notAllowed.nextMonthDay {
+ color: @fp-outsideRangeDayForeground;
+ color: var(--fp-outsideRangeDayForeground, @fp-outsideRangeDayForeground);
+ }
+ .flatpickr-day.flatpickr-disabled,
+ .flatpickr-day.flatpickr-disabled:hover {
+ color: @fp-disabledDayForeground;
+ color: var(--fp-disabledDayForeground, @fp-disabledDayForeground);
+ }
+ .flatpickr-day.selected,
+ .flatpickr-day.startRange,
+ .flatpickr-day.endRange,
+ .flatpickr-day.selected.inRange,
+ .flatpickr-day.startRange.inRange,
+ .flatpickr-day.endRange.inRange,
+ .flatpickr-day.selected:focus,
+ .flatpickr-day.startRange:focus,
+ .flatpickr-day.endRange:focus,
+ .flatpickr-day.selected:hover,
+ .flatpickr-day.startRange:hover,
+ .flatpickr-day.endRange:hover,
+ .flatpickr-day.selected.prevMonthDay,
+ .flatpickr-day.startRange.prevMonthDay,
+ .flatpickr-day.endRange.prevMonthDay,
+ .flatpickr-day.selected.nextMonthDay,
+ .flatpickr-day.startRange.nextMonthDay,
+ .flatpickr-day.endRange.nextMonthDay {
+ background: @fp-selectedDayBackground;
+ background: var(--fp-selectedDayBackground, @fp-selectedDayBackground);
+ border-color: @fp-selectedDayBackground;
+ border-color: var(--fp-selectedDayBackground, @fp-selectedDayBackground);
+ }
+ .flatpickr-day.selected.startRange + .endRange:not(:nth-child(7n+1)),
+ .flatpickr-day.startRange.startRange + .endRange:not(:nth-child(7n+1)),
+ .flatpickr-day.endRange.startRange + .endRange:not(:nth-child(7n+1)) {
+ -webkit-box-shadow: -10px 0 0 @fp-selectedDayBackground;
+ -webkit-box-shadow: -10px 0 0 var(--fp-selectedDayBackground, @fp-selectedDayBackground);
+ box-shadow: -10px 0 0 @fp-selectedDayBackground;
+ box-shadow: -10px 0 0 var(--fp-selectedDayBackground, @fp-selectedDayBackground);
+ }
+ .flatpickr-day.week.selected {
+ -webkit-box-shadow: -5px 0 0 @fp-selectedDayBackground, 5px 0 0 @fp-selectedDayBackground;
+ -webkit-box-shadow: -5px 0 0 var(--fp-selectedDayBackground, @fp-selectedDayBackground),
+ 5px 0 0 var(--fp-selectedDayBackground, @fp-selectedDayBackground);
+ box-shadow: -5px 0 0 @fp-selectedDayBackground, 5px 0 0 @fp-selectedDayBackground;
+ box-shadow: -5px 0 0 var(--fp-selectedDayBackground, @fp-selectedDayBackground),
+ 5px 0 0 var(--fp-selectedDayBackground, @fp-selectedDayBackground);
+ }
+
+ .flatpickr-weekwrapper .flatpickr-weeks {
+ -webkit-box-shadow: 1px 0 0 @fp-calendarBorderColor;
+ -webkit-box-shadow: 1px 0 0 var(--fp-calendarBorderColor, @fp-calendarBorderColor);
+ box-shadow: 1px 0 0 @fp-calendarBorderColor;
+ box-shadow: 1px 0 0 var(--fp-calendarBorderColor, @fp-calendarBorderColor);
+ }
+ .flatpickr-weekwrapper span.flatpickr-day,
+ .flatpickr-weekwrapper span.flatpickr-day:hover {
+ color: @fp-weekNumberForeground;
+ color: var(--fp-weekNumberForeground, @fp-weekNumberForeground);
+ }
+ .flatpickr-weekdays {
+ background: @fp-weekdaysBackground;
+ background: var(--fp-weekdaysBackground, @fp-weekdaysBackground);
+ }
+ span.flatpickr-weekday {
+ background: @fp-monthBackground;
+ background: var(--fp-monthBackground, @fp-monthBackground);
+ color: @fp-weekdaysForeground;
+ color: var(--fp-weekdaysForeground, @fp-weekdaysForeground);
+ }
+
+ .flatpickr-months .flatpickr-month {
+ background: @fp-monthBackground;
+ background: var(--fp-monthBackground, @fp-monthBackground);
+ color: @fp-monthForeground;
+ color: var(--fp-monthForeground, @fp-monthForeground);
+ fill: @fp-monthForeground;
+ fill: var(--fp-monthForeground, @fp-monthForeground);
+ }
+ .flatpickr-months .flatpickr-prev-month,
+ .flatpickr-months .flatpickr-next-month {
+ color: @fp-monthForeground;
+ color: var(--fp-monthForeground, @fp-monthForeground);
+ fill: @fp-monthForeground;
+ fill: var(--fp-monthForeground, @fp-monthForeground);
+ }
+ .flatpickr-months .flatpickr-prev-month:hover,
+ .flatpickr-months .flatpickr-next-month:hover {
+ color: @fp-todayColor;
+ color: var(--fp-todayColor, @fp-todayColor);
+ }
+ .flatpickr-months .flatpickr-prev-month:hover svg,
+ .flatpickr-months .flatpickr-next-month:hover svg {
+ fill: @fp-arrow_hover_color;
+ fill: var(--fp-arrow_hover_color, @fp-arrow_hover_color);
+ }
+ .flatpickr-current-month .flatpickr-monthDropdown-months {
+ background: @fp-monthBackground;
+ background: var(--fp-monthBackground, @fp-monthBackground);
+ }
+ .flatpickr-current-month .flatpickr-monthDropdown-months .flatpickr-monthDropdown-month {
+ background-color: @fp-monthBackground;
+ background-color: var(--fp-monthBackground, @fp-monthBackground);
+ }
+ .flatpickr-current-month .numInputWrapper span.arrowUp:after {
+ border-bottom-color: @fp-monthForeground;
+ border-bottom-color: var(--fp-monthForeground, @fp-monthForeground);
+ }
+ .flatpickr-current-month .numInputWrapper span.arrowDown:after {
+ border-top-color: @fp-monthForeground;
+ border-top-color: var(--fp-monthForeground, @fp-monthForeground);
+ }
+
+ .numInputWrapper span {
+ border-color: @fp-numChooserBorderColor;
+ border-color: var(--fp-numChooserBorderColor, @fp-numChooserBorderColor);
+ }
+ .numInputWrapper span:hover {
+ background: @fp-hoverNumChooserBg;
+ background: var(--fp-hoverNumChooserBg, @fp-hoverNumChooserBg);
+ }
+ .numInputWrapper span:active {
+ background: @fp-hoverNumChooserBg;
+ background: var(--fp-hoverNumChooserBg, @fp-hoverNumChooserBg);
+ }
+ .numInputWrapper span svg path {
+ fill: @fp-numChooserSvgFillColor;
+ fill: var(--fp-numChooserSvgFillColor, @fp-numChooserSvgFillColor);
+ }
+ .numInputWrapper span.arrowUp:after {
+ border-bottom-color: @fp-arrowColor;
+ border-bottom-color: var(--fp-arrowColor, @fp-arrowColor);
+ }
+ .numInputWrapper span.arrowDown:after {
+ border-top-color: @fp-arrowColor;
+ border-top-color: var(--fp-arrowColor, @fp-arrowColor);
+ }
+ .numInputWrapper:hover {
+ background: @fp-hoverInvertedBg;
+ background: var(--fp-hoverInvertedBg, @fp-hoverInvertedBg);
+ }
+ .flatpickr-current-month span.cur-month:hover {
+ background: @fp-hoverInvertedBg;
+ background: var(--fp-hoverInvertedBg, @fp-hoverInvertedBg);
+ }
+ .flatpickr-current-month .flatpickr-monthDropdown-months:hover {
+ background: @fp-hoverInvertedBg;
+ background: var(--fp-hoverInvertedBg, @fp-hoverInvertedBg);
+ }
+
+ .flatpickr-time input:hover,
+ .flatpickr-time .flatpickr-am-pm:hover,
+ .flatpickr-time input:focus,
+ .flatpickr-time .flatpickr-am-pm:focus {
+ background: @fp-timeHoverBg;
+ background: var(--fp-timeHoverBg, @fp-timeHoverBg);
+ }
+ .flatpickr-time .numInputWrapper span.arrowUp:after {
+ border-bottom-color: @fp-dayForeground;
+ border-bottom-color: var(--fp-dayForeground, @fp-dayForeground);
+ }
+ .flatpickr-time .numInputWrapper span.arrowDown:after {
+ border-top-color: @fp-dayForeground;
+ border-top-color: var(--fp-dayForeground, @fp-dayForeground);
+ }
+ .flatpickr-time input {
+ color: @fp-dayForeground;
+ color: var(--fp-dayForeground, @fp-dayForeground);
+ }
+ .flatpickr-time .flatpickr-time-separator,
+ .flatpickr-time .flatpickr-am-pm {
+ color: @fp-dayForeground;
+ color: var(--fp-dayForeground, @fp-dayForeground);
+ }
+}
diff --git a/asset/css/vertical-key-value.less b/asset/css/vertical-key-value.less
new file mode 100644
index 0000000..3d315a4
--- /dev/null
+++ b/asset/css/vertical-key-value.less
@@ -0,0 +1,17 @@
+.vertical-key-value {
+ display: inline-block;
+ line-height: .75;
+ text-align: center;
+ vertical-align: middle;
+
+ .key {
+ font-size: 10/12em;
+ color: var(--default-text-color-light, @default-text-color-light);
+ }
+
+ .value {
+ color: var(--default-text-color, @default-text-color);
+ font-size: 1.5em;
+ font-weight: bold;
+ }
+}
diff --git a/asset/js/notjQuery.js b/asset/js/notjQuery.js
new file mode 100644
index 0000000..d24cd90
--- /dev/null
+++ b/asset/js/notjQuery.js
@@ -0,0 +1,161 @@
+define(function () {
+
+ "use strict";
+
+ class notjQuery {
+ /**
+ * Create a new notjQuery object
+ *
+ * @param {Element} element
+ */
+ constructor(element) {
+ if (! element) {
+ throw new Error("Can't create a notjQuery object for `" + element + "`");
+ }
+
+ this.element = element;
+ }
+
+ /**
+ * Add an event listener to the element
+ *
+ * @param {string} type
+ * @param {string} selector
+ * @param {function} handler
+ * @param {object} context
+ */
+ on(type, selector, handler, context = null) {
+ if (typeof selector === 'function') {
+ context = handler;
+ handler = selector;
+ selector = null;
+ }
+
+ if (selector === null) {
+ this.element.addEventListener(type, e => {
+ if (type === 'focusin' && e.target.receivesCustomFocus) {
+ // Ignore native focus event if a custom one follows
+ if (e instanceof FocusEvent) {
+ delete e.target.receivesCustomFocus;
+ e.stopImmediatePropagation();
+ return;
+ }
+ }
+
+ if (context === null) {
+ handler.apply(e.currentTarget, [e]);
+ } else {
+ handler.apply(context, [e]);
+ }
+ });
+ } else {
+ this.element.addEventListener(type, e => {
+ if (type === 'focusin' && e.target.receivesCustomFocus) {
+ // Ignore native focus event if a custom one follows
+ if (e instanceof FocusEvent) {
+ delete e.target.receivesCustomFocus;
+ e.stopImmediatePropagation();
+ return;
+ }
+ }
+
+ Object.defineProperty(e, 'currentTarget', { value: e.currentTarget, writable: true });
+
+ let currentParent = e.currentTarget.parentNode;
+ for (let target = e.target; target && target !== currentParent; target = target.parentNode) {
+ if (target.matches(selector)) {
+ e.currentTarget = target;
+ if (context === null) {
+ handler.apply(target, [e]);
+ } else {
+ handler.apply(context, [e]);
+ }
+
+ break;
+ }
+ }
+ }, false);
+ }
+ }
+
+ /**
+ * Trigger a custom event on the element, asynchronously
+ *
+ * The event will bubble and is not cancelable.
+ *
+ * @param {string} type
+ * @param {{}} detail
+ */
+ trigger(type, detail = null) {
+ setTimeout(() => {
+ this.element.dispatchEvent(new CustomEvent(type, {
+ cancelable: true, // TODO: this should depend on whether it's a native or custom event
+ bubbles: true,
+ detail: detail
+ }));
+ }, 0);
+ }
+
+ /**
+ * Focus the element
+ *
+ * Any other option than `preventScroll` is used as `event.detail`.
+ *
+ * @param {{}} options
+ */
+ focus(options = {}) {
+ let { preventScroll = false, ...data } = options;
+
+ const hasData = Object.keys(data).length > 0;
+ if (hasData) {
+ this.element.receivesCustomFocus = true;
+ }
+
+ // Put separately on the event loop because focus() forces layout.
+ setTimeout(() => this.element.focus({ preventScroll: preventScroll }), 0);
+
+ if (hasData) {
+ this.trigger('focusin', data);
+ }
+ }
+
+ /**
+ * Render the element string as DOM Element
+ *
+ * @param {string} html
+ * @return {Element}
+ */
+ static render(html) {
+ if (typeof html !== 'string') {
+ throw new Error("Can\'t render `" + html + "`");
+ }
+
+ let template = document.createElement('template');
+ template.innerHTML = html;
+ return template.content.firstChild;
+ }
+ }
+
+ /**
+ * Return a notjQuery object for the given element
+ *
+ * @param {Element} element
+ * @return {notjQuery}
+ */
+ let factory = function (element) {
+ return new notjQuery(element);
+ }
+
+ // Define the static methods on the factory
+ for (let name of Object.getOwnPropertyNames(notjQuery)) {
+ if (['length', 'prototype', 'name'].includes(name)) {
+ continue;
+ }
+
+ Object.defineProperty(factory, name, {
+ value: notjQuery[name]
+ });
+ }
+
+ return factory;
+});
diff --git a/asset/js/vendor/Sortable.js b/asset/js/vendor/Sortable.js
new file mode 100644
index 0000000..8949720
--- /dev/null
+++ b/asset/js/vendor/Sortable.js
@@ -0,0 +1,3721 @@
+/**!
+ * Sortable 1.13.0
+ * @author RubaXa <trash@rubaxa.org>
+ * @author owenm <owen23355@gmail.com>
+ * @license MIT
+ */
+(function (global, factory) {
+ typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
+ typeof define === 'function' && define.icinga ? define(factory) :
+ (global = global || self, global.Sortable = factory());
+}(this, function () { 'use strict';
+
+ function _typeof(obj) {
+ if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") {
+ _typeof = function (obj) {
+ return typeof obj;
+ };
+ } else {
+ _typeof = function (obj) {
+ return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj;
+ };
+ }
+
+ return _typeof(obj);
+ }
+
+ function _defineProperty(obj, key, value) {
+ if (key in obj) {
+ Object.defineProperty(obj, key, {
+ value: value,
+ enumerable: true,
+ configurable: true,
+ writable: true
+ });
+ } else {
+ obj[key] = value;
+ }
+
+ return obj;
+ }
+
+ function _extends() {
+ _extends = Object.assign || function (target) {
+ for (var i = 1; i < arguments.length; i++) {
+ var source = arguments[i];
+
+ for (var key in source) {
+ if (Object.prototype.hasOwnProperty.call(source, key)) {
+ target[key] = source[key];
+ }
+ }
+ }
+
+ return target;
+ };
+
+ return _extends.apply(this, arguments);
+ }
+
+ function _objectSpread(target) {
+ for (var i = 1; i < arguments.length; i++) {
+ var source = arguments[i] != null ? arguments[i] : {};
+ var ownKeys = Object.keys(source);
+
+ if (typeof Object.getOwnPropertySymbols === 'function') {
+ ownKeys = ownKeys.concat(Object.getOwnPropertySymbols(source).filter(function (sym) {
+ return Object.getOwnPropertyDescriptor(source, sym).enumerable;
+ }));
+ }
+
+ ownKeys.forEach(function (key) {
+ _defineProperty(target, key, source[key]);
+ });
+ }
+
+ return target;
+ }
+
+ function _objectWithoutPropertiesLoose(source, excluded) {
+ if (source == null) return {};
+ var target = {};
+ var sourceKeys = Object.keys(source);
+ var key, i;
+
+ for (i = 0; i < sourceKeys.length; i++) {
+ key = sourceKeys[i];
+ if (excluded.indexOf(key) >= 0) continue;
+ target[key] = source[key];
+ }
+
+ return target;
+ }
+
+ function _objectWithoutProperties(source, excluded) {
+ if (source == null) return {};
+
+ var target = _objectWithoutPropertiesLoose(source, excluded);
+
+ var key, i;
+
+ if (Object.getOwnPropertySymbols) {
+ var sourceSymbolKeys = Object.getOwnPropertySymbols(source);
+
+ for (i = 0; i < sourceSymbolKeys.length; i++) {
+ key = sourceSymbolKeys[i];
+ if (excluded.indexOf(key) >= 0) continue;
+ if (!Object.prototype.propertyIsEnumerable.call(source, key)) continue;
+ target[key] = source[key];
+ }
+ }
+
+ return target;
+ }
+
+ function _toConsumableArray(arr) {
+ return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _nonIterableSpread();
+ }
+
+ function _arrayWithoutHoles(arr) {
+ if (Array.isArray(arr)) {
+ for (var i = 0, arr2 = new Array(arr.length); i < arr.length; i++) arr2[i] = arr[i];
+
+ return arr2;
+ }
+ }
+
+ function _iterableToArray(iter) {
+ if (Symbol.iterator in Object(iter) || Object.prototype.toString.call(iter) === "[object Arguments]") return Array.from(iter);
+ }
+
+ function _nonIterableSpread() {
+ throw new TypeError("Invalid attempt to spread non-iterable instance");
+ }
+
+ var version = "1.13.0";
+
+ function userAgent(pattern) {
+ if (typeof window !== 'undefined' && window.navigator) {
+ return !!
+ /*@__PURE__*/
+ navigator.userAgent.match(pattern);
+ }
+ }
+
+ var IE11OrLess = userAgent(/(?:Trident.*rv[ :]?11\.|msie|iemobile|Windows Phone)/i);
+ var Edge = userAgent(/Edge/i);
+ var FireFox = userAgent(/firefox/i);
+ var Safari = userAgent(/safari/i) && !userAgent(/chrome/i) && !userAgent(/android/i);
+ var IOS = userAgent(/iP(ad|od|hone)/i);
+ var ChromeForAndroid = userAgent(/chrome/i) && userAgent(/android/i);
+
+ var captureMode = {
+ capture: false,
+ passive: false
+ };
+
+ function on(el, event, fn) {
+ el.addEventListener(event, fn, !IE11OrLess && captureMode);
+ }
+
+ function off(el, event, fn) {
+ el.removeEventListener(event, fn, !IE11OrLess && captureMode);
+ }
+
+ function matches(
+ /**HTMLElement*/
+ el,
+ /**String*/
+ selector) {
+ if (!selector) return;
+ selector[0] === '>' && (selector = selector.substring(1));
+
+ if (el) {
+ try {
+ if (el.matches) {
+ return el.matches(selector);
+ } else if (el.msMatchesSelector) {
+ return el.msMatchesSelector(selector);
+ } else if (el.webkitMatchesSelector) {
+ return el.webkitMatchesSelector(selector);
+ }
+ } catch (_) {
+ return false;
+ }
+ }
+
+ return false;
+ }
+
+ function getParentOrHost(el) {
+ return el.host && el !== document && el.host.nodeType ? el.host : el.parentNode;
+ }
+
+ function closest(
+ /**HTMLElement*/
+ el,
+ /**String*/
+ selector,
+ /**HTMLElement*/
+ ctx, includeCTX) {
+ if (el) {
+ ctx = ctx || document;
+
+ do {
+ if (selector != null && (selector[0] === '>' ? el.parentNode === ctx && matches(el, selector) : matches(el, selector)) || includeCTX && el === ctx) {
+ return el;
+ }
+
+ if (el === ctx) break;
+ /* jshint boss:true */
+ } while (el = getParentOrHost(el));
+ }
+
+ return null;
+ }
+
+ var R_SPACE = /\s+/g;
+
+ function toggleClass(el, name, state) {
+ if (el && name) {
+ if (el.classList) {
+ el.classList[state ? 'add' : 'remove'](name);
+ } else {
+ var className = (' ' + el.className + ' ').replace(R_SPACE, ' ').replace(' ' + name + ' ', ' ');
+ el.className = (className + (state ? ' ' + name : '')).replace(R_SPACE, ' ');
+ }
+ }
+ }
+
+ function css(el, prop, val) {
+ var style = el && el.style;
+
+ if (style) {
+ if (val === void 0) {
+ if (document.defaultView && document.defaultView.getComputedStyle) {
+ val = document.defaultView.getComputedStyle(el, '');
+ } else if (el.currentStyle) {
+ val = el.currentStyle;
+ }
+
+ return prop === void 0 ? val : val[prop];
+ } else {
+ if (!(prop in style) && prop.indexOf('webkit') === -1) {
+ prop = '-webkit-' + prop;
+ }
+
+ style[prop] = val + (typeof val === 'string' ? '' : 'px');
+ }
+ }
+ }
+
+ function matrix(el, selfOnly) {
+ var appliedTransforms = '';
+
+ if (typeof el === 'string') {
+ appliedTransforms = el;
+ } else {
+ do {
+ var transform = css(el, 'transform');
+
+ if (transform && transform !== 'none') {
+ appliedTransforms = transform + ' ' + appliedTransforms;
+ }
+ /* jshint boss:true */
+
+ } while (!selfOnly && (el = el.parentNode));
+ }
+
+ var matrixFn = window.DOMMatrix || window.WebKitCSSMatrix || window.CSSMatrix || window.MSCSSMatrix;
+ /*jshint -W056 */
+
+ return matrixFn && new matrixFn(appliedTransforms);
+ }
+
+ function find(ctx, tagName, iterator) {
+ if (ctx) {
+ var list = ctx.getElementsByTagName(tagName),
+ i = 0,
+ n = list.length;
+
+ if (iterator) {
+ for (; i < n; i++) {
+ iterator(list[i], i);
+ }
+ }
+
+ return list;
+ }
+
+ return [];
+ }
+
+ function getWindowScrollingElement() {
+ var scrollingElement = document.scrollingElement;
+
+ if (scrollingElement) {
+ return scrollingElement;
+ } else {
+ return document.documentElement;
+ }
+ }
+ /**
+ * Returns the "bounding client rect" of given element
+ * @param {HTMLElement} el The element whose boundingClientRect is wanted
+ * @param {[Boolean]} relativeToContainingBlock Whether the rect should be relative to the containing block of (including) the container
+ * @param {[Boolean]} relativeToNonStaticParent Whether the rect should be relative to the relative parent of (including) the contaienr
+ * @param {[Boolean]} undoScale Whether the container's scale() should be undone
+ * @param {[HTMLElement]} container The parent the element will be placed in
+ * @return {Object} The boundingClientRect of el, with specified adjustments
+ */
+
+
+ function getRect(el, relativeToContainingBlock, relativeToNonStaticParent, undoScale, container) {
+ if (!el.getBoundingClientRect && el !== window) return;
+ var elRect, top, left, bottom, right, height, width;
+
+ if (el !== window && el.parentNode && el !== getWindowScrollingElement()) {
+ elRect = el.getBoundingClientRect();
+ top = elRect.top;
+ left = elRect.left;
+ bottom = elRect.bottom;
+ right = elRect.right;
+ height = elRect.height;
+ width = elRect.width;
+ } else {
+ top = 0;
+ left = 0;
+ bottom = window.innerHeight;
+ right = window.innerWidth;
+ height = window.innerHeight;
+ width = window.innerWidth;
+ }
+
+ if ((relativeToContainingBlock || relativeToNonStaticParent) && el !== window) {
+ // Adjust for translate()
+ container = container || el.parentNode; // solves #1123 (see: https://stackoverflow.com/a/37953806/6088312)
+ // Not needed on <= IE11
+
+ if (!IE11OrLess) {
+ do {
+ if (container && container.getBoundingClientRect && (css(container, 'transform') !== 'none' || relativeToNonStaticParent && css(container, 'position') !== 'static')) {
+ var containerRect = container.getBoundingClientRect(); // Set relative to edges of padding box of container
+
+ top -= containerRect.top + parseInt(css(container, 'border-top-width'));
+ left -= containerRect.left + parseInt(css(container, 'border-left-width'));
+ bottom = top + elRect.height;
+ right = left + elRect.width;
+ break;
+ }
+ /* jshint boss:true */
+
+ } while (container = container.parentNode);
+ }
+ }
+
+ if (undoScale && el !== window) {
+ // Adjust for scale()
+ var elMatrix = matrix(container || el),
+ scaleX = elMatrix && elMatrix.a,
+ scaleY = elMatrix && elMatrix.d;
+
+ if (elMatrix) {
+ top /= scaleY;
+ left /= scaleX;
+ width /= scaleX;
+ height /= scaleY;
+ bottom = top + height;
+ right = left + width;
+ }
+ }
+
+ return {
+ top: top,
+ left: left,
+ bottom: bottom,
+ right: right,
+ width: width,
+ height: height
+ };
+ }
+ /**
+ * Checks if a side of an element is scrolled past a side of its parents
+ * @param {HTMLElement} el The element who's side being scrolled out of view is in question
+ * @param {String} elSide Side of the element in question ('top', 'left', 'right', 'bottom')
+ * @param {String} parentSide Side of the parent in question ('top', 'left', 'right', 'bottom')
+ * @return {HTMLElement} The parent scroll element that the el's side is scrolled past, or null if there is no such element
+ */
+
+
+ function isScrolledPast(el, elSide, parentSide) {
+ var parent = getParentAutoScrollElement(el, true),
+ elSideVal = getRect(el)[elSide];
+ /* jshint boss:true */
+
+ while (parent) {
+ var parentSideVal = getRect(parent)[parentSide],
+ visible = void 0;
+
+ if (parentSide === 'top' || parentSide === 'left') {
+ visible = elSideVal >= parentSideVal;
+ } else {
+ visible = elSideVal <= parentSideVal;
+ }
+
+ if (!visible) return parent;
+ if (parent === getWindowScrollingElement()) break;
+ parent = getParentAutoScrollElement(parent, false);
+ }
+
+ return false;
+ }
+ /**
+ * Gets nth child of el, ignoring hidden children, sortable's elements (does not ignore clone if it's visible)
+ * and non-draggable elements
+ * @param {HTMLElement} el The parent element
+ * @param {Number} childNum The index of the child
+ * @param {Object} options Parent Sortable's options
+ * @return {HTMLElement} The child at index childNum, or null if not found
+ */
+
+
+ function getChild(el, childNum, options) {
+ var currentChild = 0,
+ i = 0,
+ children = el.children;
+
+ while (i < children.length) {
+ if (children[i].style.display !== 'none' && children[i] !== Sortable.ghost && children[i] !== Sortable.dragged && closest(children[i], options.draggable, el, false)) {
+ if (currentChild === childNum) {
+ return children[i];
+ }
+
+ currentChild++;
+ }
+
+ i++;
+ }
+
+ return null;
+ }
+ /**
+ * Gets the last child in the el, ignoring ghostEl or invisible elements (clones)
+ * @param {HTMLElement} el Parent element
+ * @param {selector} selector Any other elements that should be ignored
+ * @return {HTMLElement} The last child, ignoring ghostEl
+ */
+
+
+ function lastChild(el, selector) {
+ var last = el.lastElementChild;
+
+ while (last && (last === Sortable.ghost || css(last, 'display') === 'none' || selector && !matches(last, selector))) {
+ last = last.previousElementSibling;
+ }
+
+ return last || null;
+ }
+ /**
+ * Returns the index of an element within its parent for a selected set of
+ * elements
+ * @param {HTMLElement} el
+ * @param {selector} selector
+ * @return {number}
+ */
+
+
+ function index(el, selector) {
+ var index = 0;
+
+ if (!el || !el.parentNode) {
+ return -1;
+ }
+ /* jshint boss:true */
+
+
+ while (el = el.previousElementSibling) {
+ if (el.nodeName.toUpperCase() !== 'TEMPLATE' && el !== Sortable.clone && (!selector || matches(el, selector))) {
+ index++;
+ }
+ }
+
+ return index;
+ }
+ /**
+ * Returns the scroll offset of the given element, added with all the scroll offsets of parent elements.
+ * The value is returned in real pixels.
+ * @param {HTMLElement} el
+ * @return {Array} Offsets in the format of [left, top]
+ */
+
+
+ function getRelativeScrollOffset(el) {
+ var offsetLeft = 0,
+ offsetTop = 0,
+ winScroller = getWindowScrollingElement();
+
+ if (el) {
+ do {
+ var elMatrix = matrix(el),
+ scaleX = elMatrix.a,
+ scaleY = elMatrix.d;
+ offsetLeft += el.scrollLeft * scaleX;
+ offsetTop += el.scrollTop * scaleY;
+ } while (el !== winScroller && (el = el.parentNode));
+ }
+
+ return [offsetLeft, offsetTop];
+ }
+ /**
+ * Returns the index of the object within the given array
+ * @param {Array} arr Array that may or may not hold the object
+ * @param {Object} obj An object that has a key-value pair unique to and identical to a key-value pair in the object you want to find
+ * @return {Number} The index of the object in the array, or -1
+ */
+
+
+ function indexOfObject(arr, obj) {
+ for (var i in arr) {
+ if (!arr.hasOwnProperty(i)) continue;
+
+ for (var key in obj) {
+ if (obj.hasOwnProperty(key) && obj[key] === arr[i][key]) return Number(i);
+ }
+ }
+
+ return -1;
+ }
+
+ function getParentAutoScrollElement(el, includeSelf) {
+ // skip to window
+ if (!el || !el.getBoundingClientRect) return getWindowScrollingElement();
+ var elem = el;
+ var gotSelf = false;
+
+ do {
+ // we don't need to get elem css if it isn't even overflowing in the first place (performance)
+ if (elem.clientWidth < elem.scrollWidth || elem.clientHeight < elem.scrollHeight) {
+ var elemCSS = css(elem);
+
+ if (elem.clientWidth < elem.scrollWidth && (elemCSS.overflowX == 'auto' || elemCSS.overflowX == 'scroll') || elem.clientHeight < elem.scrollHeight && (elemCSS.overflowY == 'auto' || elemCSS.overflowY == 'scroll')) {
+ if (!elem.getBoundingClientRect || elem === document.body) return getWindowScrollingElement();
+ if (gotSelf || includeSelf) return elem;
+ gotSelf = true;
+ }
+ }
+ /* jshint boss:true */
+
+ } while (elem = elem.parentNode);
+
+ return getWindowScrollingElement();
+ }
+
+ function extend(dst, src) {
+ if (dst && src) {
+ for (var key in src) {
+ if (src.hasOwnProperty(key)) {
+ dst[key] = src[key];
+ }
+ }
+ }
+
+ return dst;
+ }
+
+ function isRectEqual(rect1, rect2) {
+ return Math.round(rect1.top) === Math.round(rect2.top) && Math.round(rect1.left) === Math.round(rect2.left) && Math.round(rect1.height) === Math.round(rect2.height) && Math.round(rect1.width) === Math.round(rect2.width);
+ }
+
+ var _throttleTimeout;
+
+ function throttle(callback, ms) {
+ return function () {
+ if (!_throttleTimeout) {
+ var args = arguments,
+ _this = this;
+
+ if (args.length === 1) {
+ callback.call(_this, args[0]);
+ } else {
+ callback.apply(_this, args);
+ }
+
+ _throttleTimeout = setTimeout(function () {
+ _throttleTimeout = void 0;
+ }, ms);
+ }
+ };
+ }
+
+ function cancelThrottle() {
+ clearTimeout(_throttleTimeout);
+ _throttleTimeout = void 0;
+ }
+
+ function scrollBy(el, x, y) {
+ el.scrollLeft += x;
+ el.scrollTop += y;
+ }
+
+ function clone(el) {
+ var Polymer = window.Polymer;
+ var $ = window.jQuery || window.Zepto;
+
+ if (Polymer && Polymer.dom) {
+ return Polymer.dom(el).cloneNode(true);
+ } else if ($) {
+ return $(el).clone(true)[0];
+ } else {
+ return el.cloneNode(true);
+ }
+ }
+
+ function setRect(el, rect) {
+ css(el, 'position', 'absolute');
+ css(el, 'top', rect.top);
+ css(el, 'left', rect.left);
+ css(el, 'width', rect.width);
+ css(el, 'height', rect.height);
+ }
+
+ function unsetRect(el) {
+ css(el, 'position', '');
+ css(el, 'top', '');
+ css(el, 'left', '');
+ css(el, 'width', '');
+ css(el, 'height', '');
+ }
+
+ var expando = 'Sortable' + new Date().getTime();
+
+ function AnimationStateManager() {
+ var animationStates = [],
+ animationCallbackId;
+ return {
+ captureAnimationState: function captureAnimationState() {
+ animationStates = [];
+ if (!this.options.animation) return;
+ var children = [].slice.call(this.el.children);
+ children.forEach(function (child) {
+ if (css(child, 'display') === 'none' || child === Sortable.ghost) return;
+ animationStates.push({
+ target: child,
+ rect: getRect(child)
+ });
+
+ var fromRect = _objectSpread({}, animationStates[animationStates.length - 1].rect); // If animating: compensate for current animation
+
+
+ if (child.thisAnimationDuration) {
+ var childMatrix = matrix(child, true);
+
+ if (childMatrix) {
+ fromRect.top -= childMatrix.f;
+ fromRect.left -= childMatrix.e;
+ }
+ }
+
+ child.fromRect = fromRect;
+ });
+ },
+ addAnimationState: function addAnimationState(state) {
+ animationStates.push(state);
+ },
+ removeAnimationState: function removeAnimationState(target) {
+ animationStates.splice(indexOfObject(animationStates, {
+ target: target
+ }), 1);
+ },
+ animateAll: function animateAll(callback) {
+ var _this = this;
+
+ if (!this.options.animation) {
+ clearTimeout(animationCallbackId);
+ if (typeof callback === 'function') callback();
+ return;
+ }
+
+ var animating = false,
+ animationTime = 0;
+ animationStates.forEach(function (state) {
+ var time = 0,
+ target = state.target,
+ fromRect = target.fromRect,
+ toRect = getRect(target),
+ prevFromRect = target.prevFromRect,
+ prevToRect = target.prevToRect,
+ animatingRect = state.rect,
+ targetMatrix = matrix(target, true);
+
+ if (targetMatrix) {
+ // Compensate for current animation
+ toRect.top -= targetMatrix.f;
+ toRect.left -= targetMatrix.e;
+ }
+
+ target.toRect = toRect;
+
+ if (target.thisAnimationDuration) {
+ // Could also check if animatingRect is between fromRect and toRect
+ if (isRectEqual(prevFromRect, toRect) && !isRectEqual(fromRect, toRect) && // Make sure animatingRect is on line between toRect & fromRect
+ (animatingRect.top - toRect.top) / (animatingRect.left - toRect.left) === (fromRect.top - toRect.top) / (fromRect.left - toRect.left)) {
+ // If returning to same place as started from animation and on same axis
+ time = calculateRealTime(animatingRect, prevFromRect, prevToRect, _this.options);
+ }
+ } // if fromRect != toRect: animate
+
+
+ if (!isRectEqual(toRect, fromRect)) {
+ target.prevFromRect = fromRect;
+ target.prevToRect = toRect;
+
+ if (!time) {
+ time = _this.options.animation;
+ }
+
+ _this.animate(target, animatingRect, toRect, time);
+ }
+
+ if (time) {
+ animating = true;
+ animationTime = Math.max(animationTime, time);
+ clearTimeout(target.animationResetTimer);
+ target.animationResetTimer = setTimeout(function () {
+ target.animationTime = 0;
+ target.prevFromRect = null;
+ target.fromRect = null;
+ target.prevToRect = null;
+ target.thisAnimationDuration = null;
+ }, time);
+ target.thisAnimationDuration = time;
+ }
+ });
+ clearTimeout(animationCallbackId);
+
+ if (!animating) {
+ if (typeof callback === 'function') callback();
+ } else {
+ animationCallbackId = setTimeout(function () {
+ if (typeof callback === 'function') callback();
+ }, animationTime);
+ }
+
+ animationStates = [];
+ },
+ animate: function animate(target, currentRect, toRect, duration) {
+ if (duration) {
+ css(target, 'transition', '');
+ css(target, 'transform', '');
+ var elMatrix = matrix(this.el),
+ scaleX = elMatrix && elMatrix.a,
+ scaleY = elMatrix && elMatrix.d,
+ translateX = (currentRect.left - toRect.left) / (scaleX || 1),
+ translateY = (currentRect.top - toRect.top) / (scaleY || 1);
+ target.animatingX = !!translateX;
+ target.animatingY = !!translateY;
+ css(target, 'transform', 'translate3d(' + translateX + 'px,' + translateY + 'px,0)');
+ this.forRepaintDummy = repaint(target); // repaint
+
+ css(target, 'transition', 'transform ' + duration + 'ms' + (this.options.easing ? ' ' + this.options.easing : ''));
+ css(target, 'transform', 'translate3d(0,0,0)');
+ typeof target.animated === 'number' && clearTimeout(target.animated);
+ target.animated = setTimeout(function () {
+ css(target, 'transition', '');
+ css(target, 'transform', '');
+ target.animated = false;
+ target.animatingX = false;
+ target.animatingY = false;
+ }, duration);
+ }
+ }
+ };
+ }
+
+ function repaint(target) {
+ return target.offsetWidth;
+ }
+
+ function calculateRealTime(animatingRect, fromRect, toRect, options) {
+ return Math.sqrt(Math.pow(fromRect.top - animatingRect.top, 2) + Math.pow(fromRect.left - animatingRect.left, 2)) / Math.sqrt(Math.pow(fromRect.top - toRect.top, 2) + Math.pow(fromRect.left - toRect.left, 2)) * options.animation;
+ }
+
+ var plugins = [];
+ var defaults = {
+ initializeByDefault: true
+ };
+ var PluginManager = {
+ mount: function mount(plugin) {
+ // Set default static properties
+ for (var option in defaults) {
+ if (defaults.hasOwnProperty(option) && !(option in plugin)) {
+ plugin[option] = defaults[option];
+ }
+ }
+
+ plugins.forEach(function (p) {
+ if (p.pluginName === plugin.pluginName) {
+ throw "Sortable: Cannot mount plugin ".concat(plugin.pluginName, " more than once");
+ }
+ });
+ plugins.push(plugin);
+ },
+ pluginEvent: function pluginEvent(eventName, sortable, evt) {
+ var _this = this;
+
+ this.eventCanceled = false;
+
+ evt.cancel = function () {
+ _this.eventCanceled = true;
+ };
+
+ var eventNameGlobal = eventName + 'Global';
+ plugins.forEach(function (plugin) {
+ if (!sortable[plugin.pluginName]) return; // Fire global events if it exists in this sortable
+
+ if (sortable[plugin.pluginName][eventNameGlobal]) {
+ sortable[plugin.pluginName][eventNameGlobal](_objectSpread({
+ sortable: sortable
+ }, evt));
+ } // Only fire plugin event if plugin is enabled in this sortable,
+ // and plugin has event defined
+
+
+ if (sortable.options[plugin.pluginName] && sortable[plugin.pluginName][eventName]) {
+ sortable[plugin.pluginName][eventName](_objectSpread({
+ sortable: sortable
+ }, evt));
+ }
+ });
+ },
+ initializePlugins: function initializePlugins(sortable, el, defaults, options) {
+ plugins.forEach(function (plugin) {
+ var pluginName = plugin.pluginName;
+ if (!sortable.options[pluginName] && !plugin.initializeByDefault) return;
+ var initialized = new plugin(sortable, el, sortable.options);
+ initialized.sortable = sortable;
+ initialized.options = sortable.options;
+ sortable[pluginName] = initialized; // Add default options from plugin
+
+ _extends(defaults, initialized.defaults);
+ });
+
+ for (var option in sortable.options) {
+ if (!sortable.options.hasOwnProperty(option)) continue;
+ var modified = this.modifyOption(sortable, option, sortable.options[option]);
+
+ if (typeof modified !== 'undefined') {
+ sortable.options[option] = modified;
+ }
+ }
+ },
+ getEventProperties: function getEventProperties(name, sortable) {
+ var eventProperties = {};
+ plugins.forEach(function (plugin) {
+ if (typeof plugin.eventProperties !== 'function') return;
+
+ _extends(eventProperties, plugin.eventProperties.call(sortable[plugin.pluginName], name));
+ });
+ return eventProperties;
+ },
+ modifyOption: function modifyOption(sortable, name, value) {
+ var modifiedValue;
+ plugins.forEach(function (plugin) {
+ // Plugin must exist on the Sortable
+ if (!sortable[plugin.pluginName]) return; // If static option listener exists for this option, call in the context of the Sortable's instance of this plugin
+
+ if (plugin.optionListeners && typeof plugin.optionListeners[name] === 'function') {
+ modifiedValue = plugin.optionListeners[name].call(sortable[plugin.pluginName], value);
+ }
+ });
+ return modifiedValue;
+ }
+ };
+
+ function dispatchEvent(_ref) {
+ var sortable = _ref.sortable,
+ rootEl = _ref.rootEl,
+ name = _ref.name,
+ targetEl = _ref.targetEl,
+ cloneEl = _ref.cloneEl,
+ toEl = _ref.toEl,
+ fromEl = _ref.fromEl,
+ oldIndex = _ref.oldIndex,
+ newIndex = _ref.newIndex,
+ oldDraggableIndex = _ref.oldDraggableIndex,
+ newDraggableIndex = _ref.newDraggableIndex,
+ originalEvent = _ref.originalEvent,
+ putSortable = _ref.putSortable,
+ extraEventProperties = _ref.extraEventProperties;
+ sortable = sortable || rootEl && rootEl[expando];
+ if (!sortable) return;
+ var evt,
+ options = sortable.options,
+ onName = 'on' + name.charAt(0).toUpperCase() + name.substr(1); // Support for new CustomEvent feature
+
+ if (window.CustomEvent && !IE11OrLess && !Edge) {
+ evt = new CustomEvent(name, {
+ bubbles: true,
+ cancelable: true
+ });
+ } else {
+ evt = document.createEvent('Event');
+ evt.initEvent(name, true, true);
+ }
+
+ evt.to = toEl || rootEl;
+ evt.from = fromEl || rootEl;
+ evt.item = targetEl || rootEl;
+ evt.clone = cloneEl;
+ evt.oldIndex = oldIndex;
+ evt.newIndex = newIndex;
+ evt.oldDraggableIndex = oldDraggableIndex;
+ evt.newDraggableIndex = newDraggableIndex;
+ evt.originalEvent = originalEvent;
+ evt.pullMode = putSortable ? putSortable.lastPutMode : undefined;
+
+ var allEventProperties = _objectSpread({}, extraEventProperties, PluginManager.getEventProperties(name, sortable));
+
+ for (var option in allEventProperties) {
+ evt[option] = allEventProperties[option];
+ }
+
+ if (rootEl) {
+ rootEl.dispatchEvent(evt);
+ }
+
+ if (options[onName]) {
+ options[onName].call(sortable, evt);
+ }
+ }
+
+ var pluginEvent = function pluginEvent(eventName, sortable) {
+ var _ref = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {},
+ originalEvent = _ref.evt,
+ data = _objectWithoutProperties(_ref, ["evt"]);
+
+ PluginManager.pluginEvent.bind(Sortable)(eventName, sortable, _objectSpread({
+ dragEl: dragEl,
+ parentEl: parentEl,
+ ghostEl: ghostEl,
+ rootEl: rootEl,
+ nextEl: nextEl,
+ lastDownEl: lastDownEl,
+ cloneEl: cloneEl,
+ cloneHidden: cloneHidden,
+ dragStarted: moved,
+ putSortable: putSortable,
+ activeSortable: Sortable.active,
+ originalEvent: originalEvent,
+ oldIndex: oldIndex,
+ oldDraggableIndex: oldDraggableIndex,
+ newIndex: newIndex,
+ newDraggableIndex: newDraggableIndex,
+ hideGhostForTarget: _hideGhostForTarget,
+ unhideGhostForTarget: _unhideGhostForTarget,
+ cloneNowHidden: function cloneNowHidden() {
+ cloneHidden = true;
+ },
+ cloneNowShown: function cloneNowShown() {
+ cloneHidden = false;
+ },
+ dispatchSortableEvent: function dispatchSortableEvent(name) {
+ _dispatchEvent({
+ sortable: sortable,
+ name: name,
+ originalEvent: originalEvent
+ });
+ }
+ }, data));
+ };
+
+ function _dispatchEvent(info) {
+ dispatchEvent(_objectSpread({
+ putSortable: putSortable,
+ cloneEl: cloneEl,
+ targetEl: dragEl,
+ rootEl: rootEl,
+ oldIndex: oldIndex,
+ oldDraggableIndex: oldDraggableIndex,
+ newIndex: newIndex,
+ newDraggableIndex: newDraggableIndex
+ }, info));
+ }
+
+ var dragEl,
+ parentEl,
+ ghostEl,
+ rootEl,
+ nextEl,
+ lastDownEl,
+ cloneEl,
+ cloneHidden,
+ oldIndex,
+ newIndex,
+ oldDraggableIndex,
+ newDraggableIndex,
+ activeGroup,
+ putSortable,
+ awaitingDragStarted = false,
+ ignoreNextClick = false,
+ sortables = [],
+ tapEvt,
+ touchEvt,
+ lastDx,
+ lastDy,
+ tapDistanceLeft,
+ tapDistanceTop,
+ moved,
+ lastTarget,
+ lastDirection,
+ pastFirstInvertThresh = false,
+ isCircumstantialInvert = false,
+ targetMoveDistance,
+ // For positioning ghost absolutely
+ ghostRelativeParent,
+ ghostRelativeParentInitialScroll = [],
+ // (left, top)
+ _silent = false,
+ savedInputChecked = [];
+ /** @const */
+
+ var documentExists = typeof document !== 'undefined',
+ PositionGhostAbsolutely = IOS,
+ CSSFloatProperty = Edge || IE11OrLess ? 'cssFloat' : 'float',
+ // This will not pass for IE9, because IE9 DnD only works on anchors
+ supportDraggable = documentExists && !ChromeForAndroid && !IOS && 'draggable' in document.createElement('div'),
+ supportCssPointerEvents = function () {
+ if (!documentExists) return; // false when <= IE11
+
+ if (IE11OrLess) {
+ return false;
+ }
+
+ var el = document.createElement('x');
+ el.style.cssText = 'pointer-events:auto';
+ return el.style.pointerEvents === 'auto';
+ }(),
+ _detectDirection = function _detectDirection(el, options) {
+ var elCSS = css(el),
+ elWidth = parseInt(elCSS.width) - parseInt(elCSS.paddingLeft) - parseInt(elCSS.paddingRight) - parseInt(elCSS.borderLeftWidth) - parseInt(elCSS.borderRightWidth),
+ child1 = getChild(el, 0, options),
+ child2 = getChild(el, 1, options),
+ firstChildCSS = child1 && css(child1),
+ secondChildCSS = child2 && css(child2),
+ firstChildWidth = firstChildCSS && parseInt(firstChildCSS.marginLeft) + parseInt(firstChildCSS.marginRight) + getRect(child1).width,
+ secondChildWidth = secondChildCSS && parseInt(secondChildCSS.marginLeft) + parseInt(secondChildCSS.marginRight) + getRect(child2).width;
+
+ if (elCSS.display === 'flex') {
+ return elCSS.flexDirection === 'column' || elCSS.flexDirection === 'column-reverse' ? 'vertical' : 'horizontal';
+ }
+
+ if (elCSS.display === 'grid') {
+ return elCSS.gridTemplateColumns.split(' ').length <= 1 ? 'vertical' : 'horizontal';
+ }
+
+ if (child1 && firstChildCSS["float"] && firstChildCSS["float"] !== 'none') {
+ var touchingSideChild2 = firstChildCSS["float"] === 'left' ? 'left' : 'right';
+ return child2 && (secondChildCSS.clear === 'both' || secondChildCSS.clear === touchingSideChild2) ? 'vertical' : 'horizontal';
+ }
+
+ return child1 && (firstChildCSS.display === 'block' || firstChildCSS.display === 'flex' || firstChildCSS.display === 'table' || firstChildCSS.display === 'grid' || firstChildWidth >= elWidth && elCSS[CSSFloatProperty] === 'none' || child2 && elCSS[CSSFloatProperty] === 'none' && firstChildWidth + secondChildWidth > elWidth) ? 'vertical' : 'horizontal';
+ },
+ _dragElInRowColumn = function _dragElInRowColumn(dragRect, targetRect, vertical) {
+ var dragElS1Opp = vertical ? dragRect.left : dragRect.top,
+ dragElS2Opp = vertical ? dragRect.right : dragRect.bottom,
+ dragElOppLength = vertical ? dragRect.width : dragRect.height,
+ targetS1Opp = vertical ? targetRect.left : targetRect.top,
+ targetS2Opp = vertical ? targetRect.right : targetRect.bottom,
+ targetOppLength = vertical ? targetRect.width : targetRect.height;
+ return dragElS1Opp === targetS1Opp || dragElS2Opp === targetS2Opp || dragElS1Opp + dragElOppLength / 2 === targetS1Opp + targetOppLength / 2;
+ },
+
+ /**
+ * Detects first nearest empty sortable to X and Y position using emptyInsertThreshold.
+ * @param {Number} x X position
+ * @param {Number} y Y position
+ * @return {HTMLElement} Element of the first found nearest Sortable
+ */
+ _detectNearestEmptySortable = function _detectNearestEmptySortable(x, y) {
+ var ret;
+ sortables.some(function (sortable) {
+ if (lastChild(sortable)) return;
+ var rect = getRect(sortable),
+ threshold = sortable[expando].options.emptyInsertThreshold,
+ insideHorizontally = x >= rect.left - threshold && x <= rect.right + threshold,
+ insideVertically = y >= rect.top - threshold && y <= rect.bottom + threshold;
+
+ if (threshold && insideHorizontally && insideVertically) {
+ return ret = sortable;
+ }
+ });
+ return ret;
+ },
+ _prepareGroup = function _prepareGroup(options) {
+ function toFn(value, pull) {
+ return function (to, from, dragEl, evt) {
+ var sameGroup = to.options.group.name && from.options.group.name && to.options.group.name === from.options.group.name;
+
+ if (value == null && (pull || sameGroup)) {
+ // Default pull value
+ // Default pull and put value if same group
+ return true;
+ } else if (value == null || value === false) {
+ return false;
+ } else if (pull && value === 'clone') {
+ return value;
+ } else if (typeof value === 'function') {
+ return toFn(value(to, from, dragEl, evt), pull)(to, from, dragEl, evt);
+ } else {
+ var otherGroup = (pull ? to : from).options.group.name;
+ return value === true || typeof value === 'string' && value === otherGroup || value.join && value.indexOf(otherGroup) > -1;
+ }
+ };
+ }
+
+ var group = {};
+ var originalGroup = options.group;
+
+ if (!originalGroup || _typeof(originalGroup) != 'object') {
+ originalGroup = {
+ name: originalGroup
+ };
+ }
+
+ group.name = originalGroup.name;
+ group.checkPull = toFn(originalGroup.pull, true);
+ group.checkPut = toFn(originalGroup.put);
+ group.revertClone = originalGroup.revertClone;
+ options.group = group;
+ },
+ _hideGhostForTarget = function _hideGhostForTarget() {
+ if (!supportCssPointerEvents && ghostEl) {
+ css(ghostEl, 'display', 'none');
+ }
+ },
+ _unhideGhostForTarget = function _unhideGhostForTarget() {
+ if (!supportCssPointerEvents && ghostEl) {
+ css(ghostEl, 'display', '');
+ }
+ }; // #1184 fix - Prevent click event on fallback if dragged but item not changed position
+
+
+ if (documentExists) {
+ document.addEventListener('click', function (evt) {
+ if (ignoreNextClick) {
+ evt.preventDefault();
+ evt.stopPropagation && evt.stopPropagation();
+ evt.stopImmediatePropagation && evt.stopImmediatePropagation();
+ ignoreNextClick = false;
+ return false;
+ }
+ }, true);
+ }
+
+ var nearestEmptyInsertDetectEvent = function nearestEmptyInsertDetectEvent(evt) {
+ if (dragEl) {
+ evt = evt.touches ? evt.touches[0] : evt;
+
+ var nearest = _detectNearestEmptySortable(evt.clientX, evt.clientY);
+
+ if (nearest) {
+ // Create imitation event
+ var event = {};
+
+ for (var i in evt) {
+ if (evt.hasOwnProperty(i)) {
+ event[i] = evt[i];
+ }
+ }
+
+ event.target = event.rootEl = nearest;
+ event.preventDefault = void 0;
+ event.stopPropagation = void 0;
+
+ nearest[expando]._onDragOver(event);
+ }
+ }
+ };
+
+ var _checkOutsideTargetEl = function _checkOutsideTargetEl(evt) {
+ if (dragEl) {
+ dragEl.parentNode[expando]._isOutsideThisEl(evt.target);
+ }
+ };
+ /**
+ * @class Sortable
+ * @param {HTMLElement} el
+ * @param {Object} [options]
+ */
+
+
+ function Sortable(el, options) {
+ if (!(el && el.nodeType && el.nodeType === 1)) {
+ throw "Sortable: `el` must be an HTMLElement, not ".concat({}.toString.call(el));
+ }
+
+ this.el = el; // root element
+
+ this.options = options = _extends({}, options); // Export instance
+
+ el[expando] = this;
+ var defaults = {
+ group: null,
+ sort: true,
+ disabled: false,
+ store: null,
+ handle: null,
+ draggable: /^[uo]l$/i.test(el.nodeName) ? '>li' : '>*',
+ swapThreshold: 1,
+ // percentage; 0 <= x <= 1
+ invertSwap: false,
+ // invert always
+ invertedSwapThreshold: null,
+ // will be set to same as swapThreshold if default
+ removeCloneOnHide: true,
+ direction: function direction() {
+ return _detectDirection(el, this.options);
+ },
+ ghostClass: 'sortable-ghost',
+ chosenClass: 'sortable-chosen',
+ dragClass: 'sortable-drag',
+ ignore: 'a, img',
+ filter: null,
+ preventOnFilter: true,
+ animation: 0,
+ easing: null,
+ setData: function setData(dataTransfer, dragEl) {
+ dataTransfer.setData('Text', dragEl.textContent);
+ },
+ dropBubble: false,
+ dragoverBubble: false,
+ dataIdAttr: 'data-id',
+ delay: 0,
+ delayOnTouchOnly: false,
+ touchStartThreshold: (Number.parseInt ? Number : window).parseInt(window.devicePixelRatio, 10) || 1,
+ forceFallback: false,
+ fallbackClass: 'sortable-fallback',
+ fallbackOnBody: false,
+ fallbackTolerance: 0,
+ fallbackOffset: {
+ x: 0,
+ y: 0
+ },
+ supportPointer: Sortable.supportPointer !== false && 'PointerEvent' in window && !Safari,
+ emptyInsertThreshold: 5
+ };
+ PluginManager.initializePlugins(this, el, defaults); // Set default options
+
+ for (var name in defaults) {
+ !(name in options) && (options[name] = defaults[name]);
+ }
+
+ _prepareGroup(options); // Bind all private methods
+
+
+ for (var fn in this) {
+ if (fn.charAt(0) === '_' && typeof this[fn] === 'function') {
+ this[fn] = this[fn].bind(this);
+ }
+ } // Setup drag mode
+
+
+ this.nativeDraggable = options.forceFallback ? false : supportDraggable;
+
+ if (this.nativeDraggable) {
+ // Touch start threshold cannot be greater than the native dragstart threshold
+ this.options.touchStartThreshold = 1;
+ } // Bind events
+
+
+ if (options.supportPointer) {
+ on(el, 'pointerdown', this._onTapStart);
+ } else {
+ on(el, 'mousedown', this._onTapStart);
+ on(el, 'touchstart', this._onTapStart);
+ }
+
+ if (this.nativeDraggable) {
+ on(el, 'dragover', this);
+ on(el, 'dragenter', this);
+ }
+
+ sortables.push(this.el); // Restore sorting
+
+ options.store && options.store.get && this.sort(options.store.get(this) || []); // Add animation state manager
+
+ _extends(this, AnimationStateManager());
+ }
+
+ Sortable.prototype =
+ /** @lends Sortable.prototype */
+ {
+ constructor: Sortable,
+ _isOutsideThisEl: function _isOutsideThisEl(target) {
+ if (!this.el.contains(target) && target !== this.el) {
+ lastTarget = null;
+ }
+ },
+ _getDirection: function _getDirection(evt, target) {
+ return typeof this.options.direction === 'function' ? this.options.direction.call(this, evt, target, dragEl) : this.options.direction;
+ },
+ _onTapStart: function _onTapStart(
+ /** Event|TouchEvent */
+ evt) {
+ if (!evt.cancelable) return;
+
+ var _this = this,
+ el = this.el,
+ options = this.options,
+ preventOnFilter = options.preventOnFilter,
+ type = evt.type,
+ touch = evt.touches && evt.touches[0] || evt.pointerType && evt.pointerType === 'touch' && evt,
+ target = (touch || evt).target,
+ originalTarget = evt.target.shadowRoot && (evt.path && evt.path[0] || evt.composedPath && evt.composedPath()[0]) || target,
+ filter = options.filter;
+
+ _saveInputCheckedState(el); // Don't trigger start event when an element is been dragged, otherwise the evt.oldindex always wrong when set option.group.
+
+
+ if (dragEl) {
+ return;
+ }
+
+ if (/mousedown|pointerdown/.test(type) && evt.button !== 0 || options.disabled) {
+ return; // only left button and enabled
+ } // cancel dnd if original target is content editable
+
+
+ if (originalTarget.isContentEditable) {
+ return;
+ } // Safari ignores further event handling after mousedown
+
+
+ if (!this.nativeDraggable && Safari && target && target.tagName.toUpperCase() === 'SELECT') {
+ return;
+ }
+
+ target = closest(target, options.draggable, el, false);
+
+ if (target && target.animated) {
+ return;
+ }
+
+ if (lastDownEl === target) {
+ // Ignoring duplicate `down`
+ return;
+ } // Get the index of the dragged element within its parent
+
+
+ oldIndex = index(target);
+ oldDraggableIndex = index(target, options.draggable); // Check filter
+
+ if (typeof filter === 'function') {
+ if (filter.call(this, evt, target, this)) {
+ _dispatchEvent({
+ sortable: _this,
+ rootEl: originalTarget,
+ name: 'filter',
+ targetEl: target,
+ toEl: el,
+ fromEl: el
+ });
+
+ pluginEvent('filter', _this, {
+ evt: evt
+ });
+ preventOnFilter && evt.cancelable && evt.preventDefault();
+ return; // cancel dnd
+ }
+ } else if (filter) {
+ filter = filter.split(',').some(function (criteria) {
+ criteria = closest(originalTarget, criteria.trim(), el, false);
+
+ if (criteria) {
+ _dispatchEvent({
+ sortable: _this,
+ rootEl: criteria,
+ name: 'filter',
+ targetEl: target,
+ fromEl: el,
+ toEl: el
+ });
+
+ pluginEvent('filter', _this, {
+ evt: evt
+ });
+ return true;
+ }
+ });
+
+ if (filter) {
+ preventOnFilter && evt.cancelable && evt.preventDefault();
+ return; // cancel dnd
+ }
+ }
+
+ if (options.handle && !closest(originalTarget, options.handle, el, false)) {
+ return;
+ } // Prepare `dragstart`
+
+
+ this._prepareDragStart(evt, touch, target);
+ },
+ _prepareDragStart: function _prepareDragStart(
+ /** Event */
+ evt,
+ /** Touch */
+ touch,
+ /** HTMLElement */
+ target) {
+ var _this = this,
+ el = _this.el,
+ options = _this.options,
+ ownerDocument = el.ownerDocument,
+ dragStartFn;
+
+ if (target && !dragEl && target.parentNode === el) {
+ var dragRect = getRect(target);
+ rootEl = el;
+ dragEl = target;
+ parentEl = dragEl.parentNode;
+ nextEl = dragEl.nextSibling;
+ lastDownEl = target;
+ activeGroup = options.group;
+ Sortable.dragged = dragEl;
+ tapEvt = {
+ target: dragEl,
+ clientX: (touch || evt).clientX,
+ clientY: (touch || evt).clientY
+ };
+ tapDistanceLeft = tapEvt.clientX - dragRect.left;
+ tapDistanceTop = tapEvt.clientY - dragRect.top;
+ this._lastX = (touch || evt).clientX;
+ this._lastY = (touch || evt).clientY;
+ dragEl.style['will-change'] = 'all';
+
+ dragStartFn = function dragStartFn() {
+ pluginEvent('delayEnded', _this, {
+ evt: evt
+ });
+
+ if (Sortable.eventCanceled) {
+ _this._onDrop();
+
+ return;
+ } // Delayed drag has been triggered
+ // we can re-enable the events: touchmove/mousemove
+
+
+ _this._disableDelayedDragEvents();
+
+ if (!FireFox && _this.nativeDraggable) {
+ dragEl.draggable = true;
+ } // Bind the events: dragstart/dragend
+
+
+ _this._triggerDragStart(evt, touch); // Drag start event
+
+
+ _dispatchEvent({
+ sortable: _this,
+ name: 'choose',
+ originalEvent: evt
+ }); // Chosen item
+
+
+ toggleClass(dragEl, options.chosenClass, true);
+ }; // Disable "draggable"
+
+
+ options.ignore.split(',').forEach(function (criteria) {
+ find(dragEl, criteria.trim(), _disableDraggable);
+ });
+ on(ownerDocument, 'dragover', nearestEmptyInsertDetectEvent);
+ on(ownerDocument, 'mousemove', nearestEmptyInsertDetectEvent);
+ on(ownerDocument, 'touchmove', nearestEmptyInsertDetectEvent);
+ on(ownerDocument, 'mouseup', _this._onDrop);
+ on(ownerDocument, 'touchend', _this._onDrop);
+ on(ownerDocument, 'touchcancel', _this._onDrop); // Make dragEl draggable (must be before delay for FireFox)
+
+ if (FireFox && this.nativeDraggable) {
+ this.options.touchStartThreshold = 4;
+ dragEl.draggable = true;
+ }
+
+ pluginEvent('delayStart', this, {
+ evt: evt
+ }); // Delay is impossible for native DnD in Edge or IE
+
+ if (options.delay && (!options.delayOnTouchOnly || touch) && (!this.nativeDraggable || !(Edge || IE11OrLess))) {
+ if (Sortable.eventCanceled) {
+ this._onDrop();
+
+ return;
+ } // If the user moves the pointer or let go the click or touch
+ // before the delay has been reached:
+ // disable the delayed drag
+
+
+ on(ownerDocument, 'mouseup', _this._disableDelayedDrag);
+ on(ownerDocument, 'touchend', _this._disableDelayedDrag);
+ on(ownerDocument, 'touchcancel', _this._disableDelayedDrag);
+ on(ownerDocument, 'mousemove', _this._delayedDragTouchMoveHandler);
+ on(ownerDocument, 'touchmove', _this._delayedDragTouchMoveHandler);
+ options.supportPointer && on(ownerDocument, 'pointermove', _this._delayedDragTouchMoveHandler);
+ _this._dragStartTimer = setTimeout(dragStartFn, options.delay);
+ } else {
+ dragStartFn();
+ }
+ }
+ },
+ _delayedDragTouchMoveHandler: function _delayedDragTouchMoveHandler(
+ /** TouchEvent|PointerEvent **/
+ e) {
+ var touch = e.touches ? e.touches[0] : e;
+
+ if (Math.max(Math.abs(touch.clientX - this._lastX), Math.abs(touch.clientY - this._lastY)) >= Math.floor(this.options.touchStartThreshold / (this.nativeDraggable && window.devicePixelRatio || 1))) {
+ this._disableDelayedDrag();
+ }
+ },
+ _disableDelayedDrag: function _disableDelayedDrag() {
+ dragEl && _disableDraggable(dragEl);
+ clearTimeout(this._dragStartTimer);
+
+ this._disableDelayedDragEvents();
+ },
+ _disableDelayedDragEvents: function _disableDelayedDragEvents() {
+ var ownerDocument = this.el.ownerDocument;
+ off(ownerDocument, 'mouseup', this._disableDelayedDrag);
+ off(ownerDocument, 'touchend', this._disableDelayedDrag);
+ off(ownerDocument, 'touchcancel', this._disableDelayedDrag);
+ off(ownerDocument, 'mousemove', this._delayedDragTouchMoveHandler);
+ off(ownerDocument, 'touchmove', this._delayedDragTouchMoveHandler);
+ off(ownerDocument, 'pointermove', this._delayedDragTouchMoveHandler);
+ },
+ _triggerDragStart: function _triggerDragStart(
+ /** Event */
+ evt,
+ /** Touch */
+ touch) {
+ touch = touch || evt.pointerType == 'touch' && evt;
+
+ if (!this.nativeDraggable || touch) {
+ if (this.options.supportPointer) {
+ on(document, 'pointermove', this._onTouchMove);
+ } else if (touch) {
+ on(document, 'touchmove', this._onTouchMove);
+ } else {
+ on(document, 'mousemove', this._onTouchMove);
+ }
+ } else {
+ on(dragEl, 'dragend', this);
+ on(rootEl, 'dragstart', this._onDragStart);
+ }
+
+ try {
+ if (document.selection) {
+ // Timeout neccessary for IE9
+ _nextTick(function () {
+ document.selection.empty();
+ });
+ } else {
+ window.getSelection().removeAllRanges();
+ }
+ } catch (err) {}
+ },
+ _dragStarted: function _dragStarted(fallback, evt) {
+
+ awaitingDragStarted = false;
+
+ if (rootEl && dragEl) {
+ pluginEvent('dragStarted', this, {
+ evt: evt
+ });
+
+ if (this.nativeDraggable) {
+ on(document, 'dragover', _checkOutsideTargetEl);
+ }
+
+ var options = this.options; // Apply effect
+
+ !fallback && toggleClass(dragEl, options.dragClass, false);
+ toggleClass(dragEl, options.ghostClass, true);
+ Sortable.active = this;
+ fallback && this._appendGhost(); // Drag start event
+
+ _dispatchEvent({
+ sortable: this,
+ name: 'start',
+ originalEvent: evt
+ });
+ } else {
+ this._nulling();
+ }
+ },
+ _emulateDragOver: function _emulateDragOver() {
+ if (touchEvt) {
+ this._lastX = touchEvt.clientX;
+ this._lastY = touchEvt.clientY;
+
+ _hideGhostForTarget();
+
+ var target = document.elementFromPoint(touchEvt.clientX, touchEvt.clientY);
+ var parent = target;
+
+ while (target && target.shadowRoot) {
+ target = target.shadowRoot.elementFromPoint(touchEvt.clientX, touchEvt.clientY);
+ if (target === parent) break;
+ parent = target;
+ }
+
+ dragEl.parentNode[expando]._isOutsideThisEl(target);
+
+ if (parent) {
+ do {
+ if (parent[expando]) {
+ var inserted = void 0;
+ inserted = parent[expando]._onDragOver({
+ clientX: touchEvt.clientX,
+ clientY: touchEvt.clientY,
+ target: target,
+ rootEl: parent
+ });
+
+ if (inserted && !this.options.dragoverBubble) {
+ break;
+ }
+ }
+
+ target = parent; // store last element
+ }
+ /* jshint boss:true */
+ while (parent = parent.parentNode);
+ }
+
+ _unhideGhostForTarget();
+ }
+ },
+ _onTouchMove: function _onTouchMove(
+ /**TouchEvent*/
+ evt) {
+ if (tapEvt) {
+ var options = this.options,
+ fallbackTolerance = options.fallbackTolerance,
+ fallbackOffset = options.fallbackOffset,
+ touch = evt.touches ? evt.touches[0] : evt,
+ ghostMatrix = ghostEl && matrix(ghostEl, true),
+ scaleX = ghostEl && ghostMatrix && ghostMatrix.a,
+ scaleY = ghostEl && ghostMatrix && ghostMatrix.d,
+ relativeScrollOffset = PositionGhostAbsolutely && ghostRelativeParent && getRelativeScrollOffset(ghostRelativeParent),
+ dx = (touch.clientX - tapEvt.clientX + fallbackOffset.x) / (scaleX || 1) + (relativeScrollOffset ? relativeScrollOffset[0] - ghostRelativeParentInitialScroll[0] : 0) / (scaleX || 1),
+ dy = (touch.clientY - tapEvt.clientY + fallbackOffset.y) / (scaleY || 1) + (relativeScrollOffset ? relativeScrollOffset[1] - ghostRelativeParentInitialScroll[1] : 0) / (scaleY || 1); // only set the status to dragging, when we are actually dragging
+
+ if (!Sortable.active && !awaitingDragStarted) {
+ if (fallbackTolerance && Math.max(Math.abs(touch.clientX - this._lastX), Math.abs(touch.clientY - this._lastY)) < fallbackTolerance) {
+ return;
+ }
+
+ this._onDragStart(evt, true);
+ }
+
+ if (ghostEl) {
+ if (ghostMatrix) {
+ ghostMatrix.e += dx - (lastDx || 0);
+ ghostMatrix.f += dy - (lastDy || 0);
+ } else {
+ ghostMatrix = {
+ a: 1,
+ b: 0,
+ c: 0,
+ d: 1,
+ e: dx,
+ f: dy
+ };
+ }
+
+ var cssMatrix = "matrix(".concat(ghostMatrix.a, ",").concat(ghostMatrix.b, ",").concat(ghostMatrix.c, ",").concat(ghostMatrix.d, ",").concat(ghostMatrix.e, ",").concat(ghostMatrix.f, ")");
+ css(ghostEl, 'webkitTransform', cssMatrix);
+ css(ghostEl, 'mozTransform', cssMatrix);
+ css(ghostEl, 'msTransform', cssMatrix);
+ css(ghostEl, 'transform', cssMatrix);
+ lastDx = dx;
+ lastDy = dy;
+ touchEvt = touch;
+ }
+
+ evt.cancelable && evt.preventDefault();
+ }
+ },
+ _appendGhost: function _appendGhost() {
+ // Bug if using scale(): https://stackoverflow.com/questions/2637058
+ // Not being adjusted for
+ if (!ghostEl) {
+ var container = this.options.fallbackOnBody ? document.body : rootEl,
+ rect = getRect(dragEl, true, PositionGhostAbsolutely, true, container),
+ options = this.options; // Position absolutely
+
+ if (PositionGhostAbsolutely) {
+ // Get relatively positioned parent
+ ghostRelativeParent = container;
+
+ while (css(ghostRelativeParent, 'position') === 'static' && css(ghostRelativeParent, 'transform') === 'none' && ghostRelativeParent !== document) {
+ ghostRelativeParent = ghostRelativeParent.parentNode;
+ }
+
+ if (ghostRelativeParent !== document.body && ghostRelativeParent !== document.documentElement) {
+ if (ghostRelativeParent === document) ghostRelativeParent = getWindowScrollingElement();
+ rect.top += ghostRelativeParent.scrollTop;
+ rect.left += ghostRelativeParent.scrollLeft;
+ } else {
+ ghostRelativeParent = getWindowScrollingElement();
+ }
+
+ ghostRelativeParentInitialScroll = getRelativeScrollOffset(ghostRelativeParent);
+ }
+
+ ghostEl = dragEl.cloneNode(true);
+ toggleClass(ghostEl, options.ghostClass, false);
+ toggleClass(ghostEl, options.fallbackClass, true);
+ toggleClass(ghostEl, options.dragClass, true);
+ css(ghostEl, 'transition', '');
+ css(ghostEl, 'transform', '');
+ css(ghostEl, 'box-sizing', 'border-box');
+ css(ghostEl, 'margin', 0);
+ css(ghostEl, 'top', rect.top);
+ css(ghostEl, 'left', rect.left);
+ css(ghostEl, 'width', rect.width);
+ css(ghostEl, 'height', rect.height);
+ css(ghostEl, 'opacity', '0.8');
+ css(ghostEl, 'position', PositionGhostAbsolutely ? 'absolute' : 'fixed');
+ css(ghostEl, 'zIndex', '100000');
+ css(ghostEl, 'pointerEvents', 'none');
+ Sortable.ghost = ghostEl;
+ container.appendChild(ghostEl); // Set transform-origin
+
+ css(ghostEl, 'transform-origin', tapDistanceLeft / parseInt(ghostEl.style.width) * 100 + '% ' + tapDistanceTop / parseInt(ghostEl.style.height) * 100 + '%');
+ }
+ },
+ _onDragStart: function _onDragStart(
+ /**Event*/
+ evt,
+ /**boolean*/
+ fallback) {
+ var _this = this;
+
+ var dataTransfer = evt.dataTransfer;
+ var options = _this.options;
+ pluginEvent('dragStart', this, {
+ evt: evt
+ });
+
+ if (Sortable.eventCanceled) {
+ this._onDrop();
+
+ return;
+ }
+
+ pluginEvent('setupClone', this);
+
+ if (!Sortable.eventCanceled) {
+ cloneEl = clone(dragEl);
+ cloneEl.draggable = false;
+ cloneEl.style['will-change'] = '';
+
+ this._hideClone();
+
+ toggleClass(cloneEl, this.options.chosenClass, false);
+ Sortable.clone = cloneEl;
+ } // #1143: IFrame support workaround
+
+
+ _this.cloneId = _nextTick(function () {
+ pluginEvent('clone', _this);
+ if (Sortable.eventCanceled) return;
+
+ if (!_this.options.removeCloneOnHide) {
+ rootEl.insertBefore(cloneEl, dragEl);
+ }
+
+ _this._hideClone();
+
+ _dispatchEvent({
+ sortable: _this,
+ name: 'clone'
+ });
+ });
+ !fallback && toggleClass(dragEl, options.dragClass, true); // Set proper drop events
+
+ if (fallback) {
+ ignoreNextClick = true;
+ _this._loopId = setInterval(_this._emulateDragOver, 50);
+ } else {
+ // Undo what was set in _prepareDragStart before drag started
+ off(document, 'mouseup', _this._onDrop);
+ off(document, 'touchend', _this._onDrop);
+ off(document, 'touchcancel', _this._onDrop);
+
+ if (dataTransfer) {
+ dataTransfer.effectAllowed = 'move';
+ options.setData && options.setData.call(_this, dataTransfer, dragEl);
+ }
+
+ on(document, 'drop', _this); // #1276 fix:
+
+ css(dragEl, 'transform', 'translateZ(0)');
+ }
+
+ awaitingDragStarted = true;
+ _this._dragStartId = _nextTick(_this._dragStarted.bind(_this, fallback, evt));
+ on(document, 'selectstart', _this);
+ moved = true;
+
+ if (Safari) {
+ css(document.body, 'user-select', 'none');
+ }
+ },
+ // Returns true - if no further action is needed (either inserted or another condition)
+ _onDragOver: function _onDragOver(
+ /**Event*/
+ evt) {
+ var el = this.el,
+ target = evt.target,
+ dragRect,
+ targetRect,
+ revert,
+ options = this.options,
+ group = options.group,
+ activeSortable = Sortable.active,
+ isOwner = activeGroup === group,
+ canSort = options.sort,
+ fromSortable = putSortable || activeSortable,
+ vertical,
+ _this = this,
+ completedFired = false;
+
+ if (_silent) return;
+
+ function dragOverEvent(name, extra) {
+ pluginEvent(name, _this, _objectSpread({
+ evt: evt,
+ isOwner: isOwner,
+ axis: vertical ? 'vertical' : 'horizontal',
+ revert: revert,
+ dragRect: dragRect,
+ targetRect: targetRect,
+ canSort: canSort,
+ fromSortable: fromSortable,
+ target: target,
+ completed: completed,
+ onMove: function onMove(target, after) {
+ return _onMove(rootEl, el, dragEl, dragRect, target, getRect(target), evt, after);
+ },
+ changed: changed
+ }, extra));
+ } // Capture animation state
+
+
+ function capture() {
+ dragOverEvent('dragOverAnimationCapture');
+
+ _this.captureAnimationState();
+
+ if (_this !== fromSortable) {
+ fromSortable.captureAnimationState();
+ }
+ } // Return invocation when dragEl is inserted (or completed)
+
+
+ function completed(insertion) {
+ dragOverEvent('dragOverCompleted', {
+ insertion: insertion
+ });
+
+ if (insertion) {
+ // Clones must be hidden before folding animation to capture dragRectAbsolute properly
+ if (isOwner) {
+ activeSortable._hideClone();
+ } else {
+ activeSortable._showClone(_this);
+ }
+
+ if (_this !== fromSortable) {
+ // Set ghost class to new sortable's ghost class
+ toggleClass(dragEl, putSortable ? putSortable.options.ghostClass : activeSortable.options.ghostClass, false);
+ toggleClass(dragEl, options.ghostClass, true);
+ }
+
+ if (putSortable !== _this && _this !== Sortable.active) {
+ putSortable = _this;
+ } else if (_this === Sortable.active && putSortable) {
+ putSortable = null;
+ } // Animation
+
+
+ if (fromSortable === _this) {
+ _this._ignoreWhileAnimating = target;
+ }
+
+ _this.animateAll(function () {
+ dragOverEvent('dragOverAnimationComplete');
+ _this._ignoreWhileAnimating = null;
+ });
+
+ if (_this !== fromSortable) {
+ fromSortable.animateAll();
+ fromSortable._ignoreWhileAnimating = null;
+ }
+ } // Null lastTarget if it is not inside a previously swapped element
+
+
+ if (target === dragEl && !dragEl.animated || target === el && !target.animated) {
+ lastTarget = null;
+ } // no bubbling and not fallback
+
+
+ if (!options.dragoverBubble && !evt.rootEl && target !== document) {
+ dragEl.parentNode[expando]._isOutsideThisEl(evt.target); // Do not detect for empty insert if already inserted
+
+
+ !insertion && nearestEmptyInsertDetectEvent(evt);
+ }
+
+ !options.dragoverBubble && evt.stopPropagation && evt.stopPropagation();
+ return completedFired = true;
+ } // Call when dragEl has been inserted
+
+
+ function changed() {
+ newIndex = index(dragEl);
+ newDraggableIndex = index(dragEl, options.draggable);
+
+ _dispatchEvent({
+ sortable: _this,
+ name: 'change',
+ toEl: el,
+ newIndex: newIndex,
+ newDraggableIndex: newDraggableIndex,
+ originalEvent: evt
+ });
+ }
+
+ if (evt.preventDefault !== void 0) {
+ evt.cancelable && evt.preventDefault();
+ }
+
+ target = closest(target, options.draggable, el, true);
+ dragOverEvent('dragOver');
+ if (Sortable.eventCanceled) return completedFired;
+
+ if (dragEl.contains(evt.target) || target.animated && target.animatingX && target.animatingY || _this._ignoreWhileAnimating === target) {
+ return completed(false);
+ }
+
+ ignoreNextClick = false;
+
+ if (activeSortable && !options.disabled && (isOwner ? canSort || (revert = !rootEl.contains(dragEl)) // Reverting item into the original list
+ : putSortable === this || (this.lastPutMode = activeGroup.checkPull(this, activeSortable, dragEl, evt)) && group.checkPut(this, activeSortable, dragEl, evt))) {
+ vertical = this._getDirection(evt, target) === 'vertical';
+ dragRect = getRect(dragEl);
+ dragOverEvent('dragOverValid');
+ if (Sortable.eventCanceled) return completedFired;
+
+ if (revert) {
+ parentEl = rootEl; // actualization
+
+ capture();
+
+ this._hideClone();
+
+ dragOverEvent('revert');
+
+ if (!Sortable.eventCanceled) {
+ if (nextEl) {
+ rootEl.insertBefore(dragEl, nextEl);
+ } else {
+ rootEl.appendChild(dragEl);
+ }
+ }
+
+ return completed(true);
+ }
+
+ var elLastChild = lastChild(el, options.draggable);
+
+ if (!elLastChild || _ghostIsLast(evt, vertical, this) && !elLastChild.animated) {
+ // If already at end of list: Do not insert
+ if (elLastChild === dragEl) {
+ return completed(false);
+ } // assign target only if condition is true
+
+
+ if (elLastChild && el === evt.target) {
+ target = elLastChild;
+ }
+
+ if (target) {
+ targetRect = getRect(target);
+ }
+
+ if (_onMove(rootEl, el, dragEl, dragRect, target, targetRect, evt, !!target) !== false) {
+ capture();
+ el.appendChild(dragEl);
+ parentEl = el; // actualization
+
+ changed();
+ return completed(true);
+ }
+ } else if (target.parentNode === el) {
+ targetRect = getRect(target);
+ var direction = 0,
+ targetBeforeFirstSwap,
+ differentLevel = dragEl.parentNode !== el,
+ differentRowCol = !_dragElInRowColumn(dragEl.animated && dragEl.toRect || dragRect, target.animated && target.toRect || targetRect, vertical),
+ side1 = vertical ? 'top' : 'left',
+ scrolledPastTop = isScrolledPast(target, 'top', 'top') || isScrolledPast(dragEl, 'top', 'top'),
+ scrollBefore = scrolledPastTop ? scrolledPastTop.scrollTop : void 0;
+
+ if (lastTarget !== target) {
+ targetBeforeFirstSwap = targetRect[side1];
+ pastFirstInvertThresh = false;
+ isCircumstantialInvert = !differentRowCol && options.invertSwap || differentLevel;
+ }
+
+ direction = _getSwapDirection(evt, target, targetRect, vertical, differentRowCol ? 1 : options.swapThreshold, options.invertedSwapThreshold == null ? options.swapThreshold : options.invertedSwapThreshold, isCircumstantialInvert, lastTarget === target);
+ var sibling;
+
+ if (direction !== 0) {
+ // Check if target is beside dragEl in respective direction (ignoring hidden elements)
+ var dragIndex = index(dragEl);
+
+ do {
+ dragIndex -= direction;
+ sibling = parentEl.children[dragIndex];
+ } while (sibling && (css(sibling, 'display') === 'none' || sibling === ghostEl));
+ } // If dragEl is already beside target: Do not insert
+
+
+ if (direction === 0 || sibling === target) {
+ return completed(false);
+ }
+
+ lastTarget = target;
+ lastDirection = direction;
+ var nextSibling = target.nextElementSibling,
+ after = false;
+ after = direction === 1;
+
+ var moveVector = _onMove(rootEl, el, dragEl, dragRect, target, targetRect, evt, after);
+
+ if (moveVector !== false) {
+ if (moveVector === 1 || moveVector === -1) {
+ after = moveVector === 1;
+ }
+
+ _silent = true;
+ setTimeout(_unsilent, 30);
+ capture();
+
+ if (after && !nextSibling) {
+ el.appendChild(dragEl);
+ } else {
+ target.parentNode.insertBefore(dragEl, after ? nextSibling : target);
+ } // Undo chrome's scroll adjustment (has no effect on other browsers)
+
+
+ if (scrolledPastTop) {
+ scrollBy(scrolledPastTop, 0, scrollBefore - scrolledPastTop.scrollTop);
+ }
+
+ parentEl = dragEl.parentNode; // actualization
+ // must be done before animation
+
+ if (targetBeforeFirstSwap !== undefined && !isCircumstantialInvert) {
+ targetMoveDistance = Math.abs(targetBeforeFirstSwap - getRect(target)[side1]);
+ }
+
+ changed();
+ return completed(true);
+ }
+ }
+
+ if (el.contains(dragEl)) {
+ return completed(false);
+ }
+ }
+
+ return false;
+ },
+ _ignoreWhileAnimating: null,
+ _offMoveEvents: function _offMoveEvents() {
+ off(document, 'mousemove', this._onTouchMove);
+ off(document, 'touchmove', this._onTouchMove);
+ off(document, 'pointermove', this._onTouchMove);
+ off(document, 'dragover', nearestEmptyInsertDetectEvent);
+ off(document, 'mousemove', nearestEmptyInsertDetectEvent);
+ off(document, 'touchmove', nearestEmptyInsertDetectEvent);
+ },
+ _offUpEvents: function _offUpEvents() {
+ var ownerDocument = this.el.ownerDocument;
+ off(ownerDocument, 'mouseup', this._onDrop);
+ off(ownerDocument, 'touchend', this._onDrop);
+ off(ownerDocument, 'pointerup', this._onDrop);
+ off(ownerDocument, 'touchcancel', this._onDrop);
+ off(document, 'selectstart', this);
+ },
+ _onDrop: function _onDrop(
+ /**Event*/
+ evt) {
+ var el = this.el,
+ options = this.options; // Get the index of the dragged element within its parent
+
+ newIndex = index(dragEl);
+ newDraggableIndex = index(dragEl, options.draggable);
+ pluginEvent('drop', this, {
+ evt: evt
+ });
+ parentEl = dragEl && dragEl.parentNode; // Get again after plugin event
+
+ newIndex = index(dragEl);
+ newDraggableIndex = index(dragEl, options.draggable);
+
+ if (Sortable.eventCanceled) {
+ this._nulling();
+
+ return;
+ }
+
+ awaitingDragStarted = false;
+ isCircumstantialInvert = false;
+ pastFirstInvertThresh = false;
+ clearInterval(this._loopId);
+ clearTimeout(this._dragStartTimer);
+
+ _cancelNextTick(this.cloneId);
+
+ _cancelNextTick(this._dragStartId); // Unbind events
+
+
+ if (this.nativeDraggable) {
+ off(document, 'drop', this);
+ off(el, 'dragstart', this._onDragStart);
+ }
+
+ this._offMoveEvents();
+
+ this._offUpEvents();
+
+ if (Safari) {
+ css(document.body, 'user-select', '');
+ }
+
+ css(dragEl, 'transform', '');
+
+ if (evt) {
+ if (moved) {
+ evt.cancelable && evt.preventDefault();
+ !options.dropBubble && evt.stopPropagation();
+ }
+
+ ghostEl && ghostEl.parentNode && ghostEl.parentNode.removeChild(ghostEl);
+
+ if (rootEl === parentEl || putSortable && putSortable.lastPutMode !== 'clone') {
+ // Remove clone(s)
+ cloneEl && cloneEl.parentNode && cloneEl.parentNode.removeChild(cloneEl);
+ }
+
+ if (dragEl) {
+ if (this.nativeDraggable) {
+ off(dragEl, 'dragend', this);
+ }
+
+ _disableDraggable(dragEl);
+
+ dragEl.style['will-change'] = ''; // Remove classes
+ // ghostClass is added in dragStarted
+
+ if (moved && !awaitingDragStarted) {
+ toggleClass(dragEl, putSortable ? putSortable.options.ghostClass : this.options.ghostClass, false);
+ }
+
+ toggleClass(dragEl, this.options.chosenClass, false); // Drag stop event
+
+ _dispatchEvent({
+ sortable: this,
+ name: 'unchoose',
+ toEl: parentEl,
+ newIndex: null,
+ newDraggableIndex: null,
+ originalEvent: evt
+ });
+
+ if (rootEl !== parentEl) {
+ if (newIndex >= 0) {
+ // Add event
+ _dispatchEvent({
+ rootEl: parentEl,
+ name: 'add',
+ toEl: parentEl,
+ fromEl: rootEl,
+ originalEvent: evt
+ }); // Remove event
+
+
+ _dispatchEvent({
+ sortable: this,
+ name: 'remove',
+ toEl: parentEl,
+ originalEvent: evt
+ }); // drag from one list and drop into another
+
+
+ _dispatchEvent({
+ rootEl: parentEl,
+ name: 'sort',
+ toEl: parentEl,
+ fromEl: rootEl,
+ originalEvent: evt
+ });
+
+ _dispatchEvent({
+ sortable: this,
+ name: 'sort',
+ toEl: parentEl,
+ originalEvent: evt
+ });
+ }
+
+ putSortable && putSortable.save();
+ } else {
+ if (newIndex !== oldIndex) {
+ if (newIndex >= 0) {
+ // drag & drop within the same list
+ _dispatchEvent({
+ sortable: this,
+ name: 'update',
+ toEl: parentEl,
+ originalEvent: evt
+ });
+
+ _dispatchEvent({
+ sortable: this,
+ name: 'sort',
+ toEl: parentEl,
+ originalEvent: evt
+ });
+ }
+ }
+ }
+
+ if (Sortable.active) {
+ /* jshint eqnull:true */
+ if (newIndex == null || newIndex === -1) {
+ newIndex = oldIndex;
+ newDraggableIndex = oldDraggableIndex;
+ }
+
+ _dispatchEvent({
+ sortable: this,
+ name: 'end',
+ toEl: parentEl,
+ originalEvent: evt
+ }); // Save sorting
+
+
+ this.save();
+ }
+ }
+ }
+
+ this._nulling();
+ },
+ _nulling: function _nulling() {
+ pluginEvent('nulling', this);
+ rootEl = dragEl = parentEl = ghostEl = nextEl = cloneEl = lastDownEl = cloneHidden = tapEvt = touchEvt = moved = newIndex = newDraggableIndex = oldIndex = oldDraggableIndex = lastTarget = lastDirection = putSortable = activeGroup = Sortable.dragged = Sortable.ghost = Sortable.clone = Sortable.active = null;
+ savedInputChecked.forEach(function (el) {
+ el.checked = true;
+ });
+ savedInputChecked.length = lastDx = lastDy = 0;
+ },
+ handleEvent: function handleEvent(
+ /**Event*/
+ evt) {
+ switch (evt.type) {
+ case 'drop':
+ case 'dragend':
+ this._onDrop(evt);
+
+ break;
+
+ case 'dragenter':
+ case 'dragover':
+ if (dragEl) {
+ this._onDragOver(evt);
+
+ _globalDragOver(evt);
+ }
+
+ break;
+
+ case 'selectstart':
+ evt.preventDefault();
+ break;
+ }
+ },
+
+ /**
+ * Serializes the item into an array of string.
+ * @returns {String[]}
+ */
+ toArray: function toArray() {
+ var order = [],
+ el,
+ children = this.el.children,
+ i = 0,
+ n = children.length,
+ options = this.options;
+
+ for (; i < n; i++) {
+ el = children[i];
+
+ if (closest(el, options.draggable, this.el, false)) {
+ order.push(el.getAttribute(options.dataIdAttr) || _generateId(el));
+ }
+ }
+
+ return order;
+ },
+
+ /**
+ * Sorts the elements according to the array.
+ * @param {String[]} order order of the items
+ */
+ sort: function sort(order, useAnimation) {
+ var items = {},
+ rootEl = this.el;
+ this.toArray().forEach(function (id, i) {
+ var el = rootEl.children[i];
+
+ if (closest(el, this.options.draggable, rootEl, false)) {
+ items[id] = el;
+ }
+ }, this);
+ useAnimation && this.captureAnimationState();
+ order.forEach(function (id) {
+ if (items[id]) {
+ rootEl.removeChild(items[id]);
+ rootEl.appendChild(items[id]);
+ }
+ });
+ useAnimation && this.animateAll();
+ },
+
+ /**
+ * Save the current sorting
+ */
+ save: function save() {
+ var store = this.options.store;
+ store && store.set && store.set(this);
+ },
+
+ /**
+ * For each element in the set, get the first element that matches the selector by testing the element itself and traversing up through its ancestors in the DOM tree.
+ * @param {HTMLElement} el
+ * @param {String} [selector] default: `options.draggable`
+ * @returns {HTMLElement|null}
+ */
+ closest: function closest$1(el, selector) {
+ return closest(el, selector || this.options.draggable, this.el, false);
+ },
+
+ /**
+ * Set/get option
+ * @param {string} name
+ * @param {*} [value]
+ * @returns {*}
+ */
+ option: function option(name, value) {
+ var options = this.options;
+
+ if (value === void 0) {
+ return options[name];
+ } else {
+ var modifiedValue = PluginManager.modifyOption(this, name, value);
+
+ if (typeof modifiedValue !== 'undefined') {
+ options[name] = modifiedValue;
+ } else {
+ options[name] = value;
+ }
+
+ if (name === 'group') {
+ _prepareGroup(options);
+ }
+ }
+ },
+
+ /**
+ * Destroy
+ */
+ destroy: function destroy() {
+ pluginEvent('destroy', this);
+ var el = this.el;
+ el[expando] = null;
+ off(el, 'mousedown', this._onTapStart);
+ off(el, 'touchstart', this._onTapStart);
+ off(el, 'pointerdown', this._onTapStart);
+
+ if (this.nativeDraggable) {
+ off(el, 'dragover', this);
+ off(el, 'dragenter', this);
+ } // Remove draggable attributes
+
+
+ Array.prototype.forEach.call(el.querySelectorAll('[draggable]'), function (el) {
+ el.removeAttribute('draggable');
+ });
+
+ this._onDrop();
+
+ this._disableDelayedDragEvents();
+
+ sortables.splice(sortables.indexOf(this.el), 1);
+ this.el = el = null;
+ },
+ _hideClone: function _hideClone() {
+ if (!cloneHidden) {
+ pluginEvent('hideClone', this);
+ if (Sortable.eventCanceled) return;
+ css(cloneEl, 'display', 'none');
+
+ if (this.options.removeCloneOnHide && cloneEl.parentNode) {
+ cloneEl.parentNode.removeChild(cloneEl);
+ }
+
+ cloneHidden = true;
+ }
+ },
+ _showClone: function _showClone(putSortable) {
+ if (putSortable.lastPutMode !== 'clone') {
+ this._hideClone();
+
+ return;
+ }
+
+ if (cloneHidden) {
+ pluginEvent('showClone', this);
+ if (Sortable.eventCanceled) return; // show clone at dragEl or original position
+
+ if (dragEl.parentNode == rootEl && !this.options.group.revertClone) {
+ rootEl.insertBefore(cloneEl, dragEl);
+ } else if (nextEl) {
+ rootEl.insertBefore(cloneEl, nextEl);
+ } else {
+ rootEl.appendChild(cloneEl);
+ }
+
+ if (this.options.group.revertClone) {
+ this.animate(dragEl, cloneEl);
+ }
+
+ css(cloneEl, 'display', '');
+ cloneHidden = false;
+ }
+ }
+ };
+
+ function _globalDragOver(
+ /**Event*/
+ evt) {
+ if (evt.dataTransfer) {
+ evt.dataTransfer.dropEffect = 'move';
+ }
+
+ evt.cancelable && evt.preventDefault();
+ }
+
+ function _onMove(fromEl, toEl, dragEl, dragRect, targetEl, targetRect, originalEvent, willInsertAfter) {
+ var evt,
+ sortable = fromEl[expando],
+ onMoveFn = sortable.options.onMove,
+ retVal; // Support for new CustomEvent feature
+
+ if (window.CustomEvent && !IE11OrLess && !Edge) {
+ evt = new CustomEvent('move', {
+ bubbles: true,
+ cancelable: true
+ });
+ } else {
+ evt = document.createEvent('Event');
+ evt.initEvent('move', true, true);
+ }
+
+ evt.to = toEl;
+ evt.from = fromEl;
+ evt.dragged = dragEl;
+ evt.draggedRect = dragRect;
+ evt.related = targetEl || toEl;
+ evt.relatedRect = targetRect || getRect(toEl);
+ evt.willInsertAfter = willInsertAfter;
+ evt.originalEvent = originalEvent;
+ fromEl.dispatchEvent(evt);
+
+ if (onMoveFn) {
+ retVal = onMoveFn.call(sortable, evt, originalEvent);
+ }
+
+ return retVal;
+ }
+
+ function _disableDraggable(el) {
+ el.draggable = false;
+ }
+
+ function _unsilent() {
+ _silent = false;
+ }
+
+ function _ghostIsLast(evt, vertical, sortable) {
+ var rect = getRect(lastChild(sortable.el, sortable.options.draggable));
+ var spacer = 10;
+ return vertical ? evt.clientX > rect.right + spacer || evt.clientX <= rect.right && evt.clientY > rect.bottom && evt.clientX >= rect.left : evt.clientX > rect.right && evt.clientY > rect.top || evt.clientX <= rect.right && evt.clientY > rect.bottom + spacer;
+ }
+
+ function _getSwapDirection(evt, target, targetRect, vertical, swapThreshold, invertedSwapThreshold, invertSwap, isLastTarget) {
+ var mouseOnAxis = vertical ? evt.clientY : evt.clientX,
+ targetLength = vertical ? targetRect.height : targetRect.width,
+ targetS1 = vertical ? targetRect.top : targetRect.left,
+ targetS2 = vertical ? targetRect.bottom : targetRect.right,
+ invert = false;
+
+ if (!invertSwap) {
+ // Never invert or create dragEl shadow when target movemenet causes mouse to move past the end of regular swapThreshold
+ if (isLastTarget && targetMoveDistance < targetLength * swapThreshold) {
+ // multiplied only by swapThreshold because mouse will already be inside target by (1 - threshold) * targetLength / 2
+ // check if past first invert threshold on side opposite of lastDirection
+ if (!pastFirstInvertThresh && (lastDirection === 1 ? mouseOnAxis > targetS1 + targetLength * invertedSwapThreshold / 2 : mouseOnAxis < targetS2 - targetLength * invertedSwapThreshold / 2)) {
+ // past first invert threshold, do not restrict inverted threshold to dragEl shadow
+ pastFirstInvertThresh = true;
+ }
+
+ if (!pastFirstInvertThresh) {
+ // dragEl shadow (target move distance shadow)
+ if (lastDirection === 1 ? mouseOnAxis < targetS1 + targetMoveDistance // over dragEl shadow
+ : mouseOnAxis > targetS2 - targetMoveDistance) {
+ return -lastDirection;
+ }
+ } else {
+ invert = true;
+ }
+ } else {
+ // Regular
+ if (mouseOnAxis > targetS1 + targetLength * (1 - swapThreshold) / 2 && mouseOnAxis < targetS2 - targetLength * (1 - swapThreshold) / 2) {
+ return _getInsertDirection(target);
+ }
+ }
+ }
+
+ invert = invert || invertSwap;
+
+ if (invert) {
+ // Invert of regular
+ if (mouseOnAxis < targetS1 + targetLength * invertedSwapThreshold / 2 || mouseOnAxis > targetS2 - targetLength * invertedSwapThreshold / 2) {
+ return mouseOnAxis > targetS1 + targetLength / 2 ? 1 : -1;
+ }
+ }
+
+ return 0;
+ }
+ /**
+ * Gets the direction dragEl must be swapped relative to target in order to make it
+ * seem that dragEl has been "inserted" into that element's position
+ * @param {HTMLElement} target The target whose position dragEl is being inserted at
+ * @return {Number} Direction dragEl must be swapped
+ */
+
+
+ function _getInsertDirection(target) {
+ if (index(dragEl) < index(target)) {
+ return 1;
+ } else {
+ return -1;
+ }
+ }
+ /**
+ * Generate id
+ * @param {HTMLElement} el
+ * @returns {String}
+ * @private
+ */
+
+
+ function _generateId(el) {
+ var str = el.tagName + el.className + el.src + el.href + el.textContent,
+ i = str.length,
+ sum = 0;
+
+ while (i--) {
+ sum += str.charCodeAt(i);
+ }
+
+ return sum.toString(36);
+ }
+
+ function _saveInputCheckedState(root) {
+ savedInputChecked.length = 0;
+ var inputs = root.getElementsByTagName('input');
+ var idx = inputs.length;
+
+ while (idx--) {
+ var el = inputs[idx];
+ el.checked && savedInputChecked.push(el);
+ }
+ }
+
+ function _nextTick(fn) {
+ return setTimeout(fn, 0);
+ }
+
+ function _cancelNextTick(id) {
+ return clearTimeout(id);
+ } // Fixed #973:
+
+
+ if (documentExists) {
+ on(document, 'touchmove', function (evt) {
+ if ((Sortable.active || awaitingDragStarted) && evt.cancelable) {
+ evt.preventDefault();
+ }
+ });
+ } // Export utils
+
+
+ Sortable.utils = {
+ on: on,
+ off: off,
+ css: css,
+ find: find,
+ is: function is(el, selector) {
+ return !!closest(el, selector, el, false);
+ },
+ extend: extend,
+ throttle: throttle,
+ closest: closest,
+ toggleClass: toggleClass,
+ clone: clone,
+ index: index,
+ nextTick: _nextTick,
+ cancelNextTick: _cancelNextTick,
+ detectDirection: _detectDirection,
+ getChild: getChild
+ };
+ /**
+ * Get the Sortable instance of an element
+ * @param {HTMLElement} element The element
+ * @return {Sortable|undefined} The instance of Sortable
+ */
+
+ Sortable.get = function (element) {
+ return element[expando];
+ };
+ /**
+ * Mount a plugin to Sortable
+ * @param {...SortablePlugin|SortablePlugin[]} plugins Plugins being mounted
+ */
+
+
+ Sortable.mount = function () {
+ for (var _len = arguments.length, plugins = new Array(_len), _key = 0; _key < _len; _key++) {
+ plugins[_key] = arguments[_key];
+ }
+
+ if (plugins[0].constructor === Array) plugins = plugins[0];
+ plugins.forEach(function (plugin) {
+ if (!plugin.prototype || !plugin.prototype.constructor) {
+ throw "Sortable: Mounted plugin must be a constructor function, not ".concat({}.toString.call(plugin));
+ }
+
+ if (plugin.utils) Sortable.utils = _objectSpread({}, Sortable.utils, plugin.utils);
+ PluginManager.mount(plugin);
+ });
+ };
+ /**
+ * Create sortable instance
+ * @param {HTMLElement} el
+ * @param {Object} [options]
+ */
+
+
+ Sortable.create = function (el, options) {
+ return new Sortable(el, options);
+ }; // Export
+
+
+ Sortable.version = version;
+
+ var autoScrolls = [],
+ scrollEl,
+ scrollRootEl,
+ scrolling = false,
+ lastAutoScrollX,
+ lastAutoScrollY,
+ touchEvt$1,
+ pointerElemChangedInterval;
+
+ function AutoScrollPlugin() {
+ function AutoScroll() {
+ this.defaults = {
+ scroll: true,
+ scrollSensitivity: 30,
+ scrollSpeed: 10,
+ bubbleScroll: true
+ }; // Bind all private methods
+
+ for (var fn in this) {
+ if (fn.charAt(0) === '_' && typeof this[fn] === 'function') {
+ this[fn] = this[fn].bind(this);
+ }
+ }
+ }
+
+ AutoScroll.prototype = {
+ dragStarted: function dragStarted(_ref) {
+ var originalEvent = _ref.originalEvent;
+
+ if (this.sortable.nativeDraggable) {
+ on(document, 'dragover', this._handleAutoScroll);
+ } else {
+ if (this.options.supportPointer) {
+ on(document, 'pointermove', this._handleFallbackAutoScroll);
+ } else if (originalEvent.touches) {
+ on(document, 'touchmove', this._handleFallbackAutoScroll);
+ } else {
+ on(document, 'mousemove', this._handleFallbackAutoScroll);
+ }
+ }
+ },
+ dragOverCompleted: function dragOverCompleted(_ref2) {
+ var originalEvent = _ref2.originalEvent;
+
+ // For when bubbling is canceled and using fallback (fallback 'touchmove' always reached)
+ if (!this.options.dragOverBubble && !originalEvent.rootEl) {
+ this._handleAutoScroll(originalEvent);
+ }
+ },
+ drop: function drop() {
+ if (this.sortable.nativeDraggable) {
+ off(document, 'dragover', this._handleAutoScroll);
+ } else {
+ off(document, 'pointermove', this._handleFallbackAutoScroll);
+ off(document, 'touchmove', this._handleFallbackAutoScroll);
+ off(document, 'mousemove', this._handleFallbackAutoScroll);
+ }
+
+ clearPointerElemChangedInterval();
+ clearAutoScrolls();
+ cancelThrottle();
+ },
+ nulling: function nulling() {
+ touchEvt$1 = scrollRootEl = scrollEl = scrolling = pointerElemChangedInterval = lastAutoScrollX = lastAutoScrollY = null;
+ autoScrolls.length = 0;
+ },
+ _handleFallbackAutoScroll: function _handleFallbackAutoScroll(evt) {
+ this._handleAutoScroll(evt, true);
+ },
+ _handleAutoScroll: function _handleAutoScroll(evt, fallback) {
+ var _this = this;
+
+ var x = (evt.touches ? evt.touches[0] : evt).clientX,
+ y = (evt.touches ? evt.touches[0] : evt).clientY,
+ elem = document.elementFromPoint(x, y);
+ touchEvt$1 = evt; // IE does not seem to have native autoscroll,
+ // Edge's autoscroll seems too conditional,
+ // MACOS Safari does not have autoscroll,
+ // Firefox and Chrome are good
+
+ if (fallback || Edge || IE11OrLess || Safari) {
+ autoScroll(evt, this.options, elem, fallback); // Listener for pointer element change
+
+ var ogElemScroller = getParentAutoScrollElement(elem, true);
+
+ if (scrolling && (!pointerElemChangedInterval || x !== lastAutoScrollX || y !== lastAutoScrollY)) {
+ pointerElemChangedInterval && clearPointerElemChangedInterval(); // Detect for pointer elem change, emulating native DnD behaviour
+
+ pointerElemChangedInterval = setInterval(function () {
+ var newElem = getParentAutoScrollElement(document.elementFromPoint(x, y), true);
+
+ if (newElem !== ogElemScroller) {
+ ogElemScroller = newElem;
+ clearAutoScrolls();
+ }
+
+ autoScroll(evt, _this.options, newElem, fallback);
+ }, 10);
+ lastAutoScrollX = x;
+ lastAutoScrollY = y;
+ }
+ } else {
+ // if DnD is enabled (and browser has good autoscrolling), first autoscroll will already scroll, so get parent autoscroll of first autoscroll
+ if (!this.options.bubbleScroll || getParentAutoScrollElement(elem, true) === getWindowScrollingElement()) {
+ clearAutoScrolls();
+ return;
+ }
+
+ autoScroll(evt, this.options, getParentAutoScrollElement(elem, false), false);
+ }
+ }
+ };
+ return _extends(AutoScroll, {
+ pluginName: 'scroll',
+ initializeByDefault: true
+ });
+ }
+
+ function clearAutoScrolls() {
+ autoScrolls.forEach(function (autoScroll) {
+ clearInterval(autoScroll.pid);
+ });
+ autoScrolls = [];
+ }
+
+ function clearPointerElemChangedInterval() {
+ clearInterval(pointerElemChangedInterval);
+ }
+
+ var autoScroll = throttle(function (evt, options, rootEl, isFallback) {
+ // Bug: https://bugzilla.mozilla.org/show_bug.cgi?id=505521
+ if (!options.scroll) return;
+ var x = (evt.touches ? evt.touches[0] : evt).clientX,
+ y = (evt.touches ? evt.touches[0] : evt).clientY,
+ sens = options.scrollSensitivity,
+ speed = options.scrollSpeed,
+ winScroller = getWindowScrollingElement();
+ var scrollThisInstance = false,
+ scrollCustomFn; // New scroll root, set scrollEl
+
+ if (scrollRootEl !== rootEl) {
+ scrollRootEl = rootEl;
+ clearAutoScrolls();
+ scrollEl = options.scroll;
+ scrollCustomFn = options.scrollFn;
+
+ if (scrollEl === true) {
+ scrollEl = getParentAutoScrollElement(rootEl, true);
+ }
+ }
+
+ var layersOut = 0;
+ var currentParent = scrollEl;
+
+ do {
+ var el = currentParent,
+ rect = getRect(el),
+ top = rect.top,
+ bottom = rect.bottom,
+ left = rect.left,
+ right = rect.right,
+ width = rect.width,
+ height = rect.height,
+ canScrollX = void 0,
+ canScrollY = void 0,
+ scrollWidth = el.scrollWidth,
+ scrollHeight = el.scrollHeight,
+ elCSS = css(el),
+ scrollPosX = el.scrollLeft,
+ scrollPosY = el.scrollTop;
+
+ if (el === winScroller) {
+ canScrollX = width < scrollWidth && (elCSS.overflowX === 'auto' || elCSS.overflowX === 'scroll' || elCSS.overflowX === 'visible');
+ canScrollY = height < scrollHeight && (elCSS.overflowY === 'auto' || elCSS.overflowY === 'scroll' || elCSS.overflowY === 'visible');
+ } else {
+ canScrollX = width < scrollWidth && (elCSS.overflowX === 'auto' || elCSS.overflowX === 'scroll');
+ canScrollY = height < scrollHeight && (elCSS.overflowY === 'auto' || elCSS.overflowY === 'scroll');
+ }
+
+ var vx = canScrollX && (Math.abs(right - x) <= sens && scrollPosX + width < scrollWidth) - (Math.abs(left - x) <= sens && !!scrollPosX);
+ var vy = canScrollY && (Math.abs(bottom - y) <= sens && scrollPosY + height < scrollHeight) - (Math.abs(top - y) <= sens && !!scrollPosY);
+
+ if (!autoScrolls[layersOut]) {
+ for (var i = 0; i <= layersOut; i++) {
+ if (!autoScrolls[i]) {
+ autoScrolls[i] = {};
+ }
+ }
+ }
+
+ if (autoScrolls[layersOut].vx != vx || autoScrolls[layersOut].vy != vy || autoScrolls[layersOut].el !== el) {
+ autoScrolls[layersOut].el = el;
+ autoScrolls[layersOut].vx = vx;
+ autoScrolls[layersOut].vy = vy;
+ clearInterval(autoScrolls[layersOut].pid);
+
+ if (vx != 0 || vy != 0) {
+ scrollThisInstance = true;
+ /* jshint loopfunc:true */
+
+ autoScrolls[layersOut].pid = setInterval(function () {
+ // emulate drag over during autoscroll (fallback), emulating native DnD behaviour
+ if (isFallback && this.layer === 0) {
+ Sortable.active._onTouchMove(touchEvt$1); // To move ghost if it is positioned absolutely
+
+ }
+
+ var scrollOffsetY = autoScrolls[this.layer].vy ? autoScrolls[this.layer].vy * speed : 0;
+ var scrollOffsetX = autoScrolls[this.layer].vx ? autoScrolls[this.layer].vx * speed : 0;
+
+ if (typeof scrollCustomFn === 'function') {
+ if (scrollCustomFn.call(Sortable.dragged.parentNode[expando], scrollOffsetX, scrollOffsetY, evt, touchEvt$1, autoScrolls[this.layer].el) !== 'continue') {
+ return;
+ }
+ }
+
+ scrollBy(autoScrolls[this.layer].el, scrollOffsetX, scrollOffsetY);
+ }.bind({
+ layer: layersOut
+ }), 24);
+ }
+ }
+
+ layersOut++;
+ } while (options.bubbleScroll && currentParent !== winScroller && (currentParent = getParentAutoScrollElement(currentParent, false)));
+
+ scrolling = scrollThisInstance; // in case another function catches scrolling as false in between when it is not
+ }, 30);
+
+ var drop = function drop(_ref) {
+ var originalEvent = _ref.originalEvent,
+ putSortable = _ref.putSortable,
+ dragEl = _ref.dragEl,
+ activeSortable = _ref.activeSortable,
+ dispatchSortableEvent = _ref.dispatchSortableEvent,
+ hideGhostForTarget = _ref.hideGhostForTarget,
+ unhideGhostForTarget = _ref.unhideGhostForTarget;
+ if (!originalEvent) return;
+ var toSortable = putSortable || activeSortable;
+ hideGhostForTarget();
+ var touch = originalEvent.changedTouches && originalEvent.changedTouches.length ? originalEvent.changedTouches[0] : originalEvent;
+ var target = document.elementFromPoint(touch.clientX, touch.clientY);
+ unhideGhostForTarget();
+
+ if (toSortable && !toSortable.el.contains(target)) {
+ dispatchSortableEvent('spill');
+ this.onSpill({
+ dragEl: dragEl,
+ putSortable: putSortable
+ });
+ }
+ };
+
+ function Revert() {}
+
+ Revert.prototype = {
+ startIndex: null,
+ dragStart: function dragStart(_ref2) {
+ var oldDraggableIndex = _ref2.oldDraggableIndex;
+ this.startIndex = oldDraggableIndex;
+ },
+ onSpill: function onSpill(_ref3) {
+ var dragEl = _ref3.dragEl,
+ putSortable = _ref3.putSortable;
+ this.sortable.captureAnimationState();
+
+ if (putSortable) {
+ putSortable.captureAnimationState();
+ }
+
+ var nextSibling = getChild(this.sortable.el, this.startIndex, this.options);
+
+ if (nextSibling) {
+ this.sortable.el.insertBefore(dragEl, nextSibling);
+ } else {
+ this.sortable.el.appendChild(dragEl);
+ }
+
+ this.sortable.animateAll();
+
+ if (putSortable) {
+ putSortable.animateAll();
+ }
+ },
+ drop: drop
+ };
+
+ _extends(Revert, {
+ pluginName: 'revertOnSpill'
+ });
+
+ function Remove() {}
+
+ Remove.prototype = {
+ onSpill: function onSpill(_ref4) {
+ var dragEl = _ref4.dragEl,
+ putSortable = _ref4.putSortable;
+ var parentSortable = putSortable || this.sortable;
+ parentSortable.captureAnimationState();
+ dragEl.parentNode && dragEl.parentNode.removeChild(dragEl);
+ parentSortable.animateAll();
+ },
+ drop: drop
+ };
+
+ _extends(Remove, {
+ pluginName: 'removeOnSpill'
+ });
+
+ var lastSwapEl;
+
+ function SwapPlugin() {
+ function Swap() {
+ this.defaults = {
+ swapClass: 'sortable-swap-highlight'
+ };
+ }
+
+ Swap.prototype = {
+ dragStart: function dragStart(_ref) {
+ var dragEl = _ref.dragEl;
+ lastSwapEl = dragEl;
+ },
+ dragOverValid: function dragOverValid(_ref2) {
+ var completed = _ref2.completed,
+ target = _ref2.target,
+ onMove = _ref2.onMove,
+ activeSortable = _ref2.activeSortable,
+ changed = _ref2.changed,
+ cancel = _ref2.cancel;
+ if (!activeSortable.options.swap) return;
+ var el = this.sortable.el,
+ options = this.options;
+
+ if (target && target !== el) {
+ var prevSwapEl = lastSwapEl;
+
+ if (onMove(target) !== false) {
+ toggleClass(target, options.swapClass, true);
+ lastSwapEl = target;
+ } else {
+ lastSwapEl = null;
+ }
+
+ if (prevSwapEl && prevSwapEl !== lastSwapEl) {
+ toggleClass(prevSwapEl, options.swapClass, false);
+ }
+ }
+
+ changed();
+ completed(true);
+ cancel();
+ },
+ drop: function drop(_ref3) {
+ var activeSortable = _ref3.activeSortable,
+ putSortable = _ref3.putSortable,
+ dragEl = _ref3.dragEl;
+ var toSortable = putSortable || this.sortable;
+ var options = this.options;
+ lastSwapEl && toggleClass(lastSwapEl, options.swapClass, false);
+
+ if (lastSwapEl && (options.swap || putSortable && putSortable.options.swap)) {
+ if (dragEl !== lastSwapEl) {
+ toSortable.captureAnimationState();
+ if (toSortable !== activeSortable) activeSortable.captureAnimationState();
+ swapNodes(dragEl, lastSwapEl);
+ toSortable.animateAll();
+ if (toSortable !== activeSortable) activeSortable.animateAll();
+ }
+ }
+ },
+ nulling: function nulling() {
+ lastSwapEl = null;
+ }
+ };
+ return _extends(Swap, {
+ pluginName: 'swap',
+ eventProperties: function eventProperties() {
+ return {
+ swapItem: lastSwapEl
+ };
+ }
+ });
+ }
+
+ function swapNodes(n1, n2) {
+ var p1 = n1.parentNode,
+ p2 = n2.parentNode,
+ i1,
+ i2;
+ if (!p1 || !p2 || p1.isEqualNode(n2) || p2.isEqualNode(n1)) return;
+ i1 = index(n1);
+ i2 = index(n2);
+
+ if (p1.isEqualNode(p2) && i1 < i2) {
+ i2++;
+ }
+
+ p1.insertBefore(n2, p1.children[i1]);
+ p2.insertBefore(n1, p2.children[i2]);
+ }
+
+ var multiDragElements = [],
+ multiDragClones = [],
+ lastMultiDragSelect,
+ // for selection with modifier key down (SHIFT)
+ multiDragSortable,
+ initialFolding = false,
+ // Initial multi-drag fold when drag started
+ folding = false,
+ // Folding any other time
+ dragStarted = false,
+ dragEl$1,
+ clonesFromRect,
+ clonesHidden;
+
+ function MultiDragPlugin() {
+ function MultiDrag(sortable) {
+ // Bind all private methods
+ for (var fn in this) {
+ if (fn.charAt(0) === '_' && typeof this[fn] === 'function') {
+ this[fn] = this[fn].bind(this);
+ }
+ }
+
+ if (sortable.options.supportPointer) {
+ on(document, 'pointerup', this._deselectMultiDrag);
+ } else {
+ on(document, 'mouseup', this._deselectMultiDrag);
+ on(document, 'touchend', this._deselectMultiDrag);
+ }
+
+ on(document, 'keydown', this._checkKeyDown);
+ on(document, 'keyup', this._checkKeyUp);
+ this.defaults = {
+ selectedClass: 'sortable-selected',
+ multiDragKey: null,
+ setData: function setData(dataTransfer, dragEl) {
+ var data = '';
+
+ if (multiDragElements.length && multiDragSortable === sortable) {
+ multiDragElements.forEach(function (multiDragElement, i) {
+ data += (!i ? '' : ', ') + multiDragElement.textContent;
+ });
+ } else {
+ data = dragEl.textContent;
+ }
+
+ dataTransfer.setData('Text', data);
+ }
+ };
+ }
+
+ MultiDrag.prototype = {
+ multiDragKeyDown: false,
+ isMultiDrag: false,
+ delayStartGlobal: function delayStartGlobal(_ref) {
+ var dragged = _ref.dragEl;
+ dragEl$1 = dragged;
+ },
+ delayEnded: function delayEnded() {
+ this.isMultiDrag = ~multiDragElements.indexOf(dragEl$1);
+ },
+ setupClone: function setupClone(_ref2) {
+ var sortable = _ref2.sortable,
+ cancel = _ref2.cancel;
+ if (!this.isMultiDrag) return;
+
+ for (var i = 0; i < multiDragElements.length; i++) {
+ multiDragClones.push(clone(multiDragElements[i]));
+ multiDragClones[i].sortableIndex = multiDragElements[i].sortableIndex;
+ multiDragClones[i].draggable = false;
+ multiDragClones[i].style['will-change'] = '';
+ toggleClass(multiDragClones[i], this.options.selectedClass, false);
+ multiDragElements[i] === dragEl$1 && toggleClass(multiDragClones[i], this.options.chosenClass, false);
+ }
+
+ sortable._hideClone();
+
+ cancel();
+ },
+ clone: function clone(_ref3) {
+ var sortable = _ref3.sortable,
+ rootEl = _ref3.rootEl,
+ dispatchSortableEvent = _ref3.dispatchSortableEvent,
+ cancel = _ref3.cancel;
+ if (!this.isMultiDrag) return;
+
+ if (!this.options.removeCloneOnHide) {
+ if (multiDragElements.length && multiDragSortable === sortable) {
+ insertMultiDragClones(true, rootEl);
+ dispatchSortableEvent('clone');
+ cancel();
+ }
+ }
+ },
+ showClone: function showClone(_ref4) {
+ var cloneNowShown = _ref4.cloneNowShown,
+ rootEl = _ref4.rootEl,
+ cancel = _ref4.cancel;
+ if (!this.isMultiDrag) return;
+ insertMultiDragClones(false, rootEl);
+ multiDragClones.forEach(function (clone) {
+ css(clone, 'display', '');
+ });
+ cloneNowShown();
+ clonesHidden = false;
+ cancel();
+ },
+ hideClone: function hideClone(_ref5) {
+ var _this = this;
+
+ var sortable = _ref5.sortable,
+ cloneNowHidden = _ref5.cloneNowHidden,
+ cancel = _ref5.cancel;
+ if (!this.isMultiDrag) return;
+ multiDragClones.forEach(function (clone) {
+ css(clone, 'display', 'none');
+
+ if (_this.options.removeCloneOnHide && clone.parentNode) {
+ clone.parentNode.removeChild(clone);
+ }
+ });
+ cloneNowHidden();
+ clonesHidden = true;
+ cancel();
+ },
+ dragStartGlobal: function dragStartGlobal(_ref6) {
+ var sortable = _ref6.sortable;
+
+ if (!this.isMultiDrag && multiDragSortable) {
+ multiDragSortable.multiDrag._deselectMultiDrag();
+ }
+
+ multiDragElements.forEach(function (multiDragElement) {
+ multiDragElement.sortableIndex = index(multiDragElement);
+ }); // Sort multi-drag elements
+
+ multiDragElements = multiDragElements.sort(function (a, b) {
+ return a.sortableIndex - b.sortableIndex;
+ });
+ dragStarted = true;
+ },
+ dragStarted: function dragStarted(_ref7) {
+ var _this2 = this;
+
+ var sortable = _ref7.sortable;
+ if (!this.isMultiDrag) return;
+
+ if (this.options.sort) {
+ // Capture rects,
+ // hide multi drag elements (by positioning them absolute),
+ // set multi drag elements rects to dragRect,
+ // show multi drag elements,
+ // animate to rects,
+ // unset rects & remove from DOM
+ sortable.captureAnimationState();
+
+ if (this.options.animation) {
+ multiDragElements.forEach(function (multiDragElement) {
+ if (multiDragElement === dragEl$1) return;
+ css(multiDragElement, 'position', 'absolute');
+ });
+ var dragRect = getRect(dragEl$1, false, true, true);
+ multiDragElements.forEach(function (multiDragElement) {
+ if (multiDragElement === dragEl$1) return;
+ setRect(multiDragElement, dragRect);
+ });
+ folding = true;
+ initialFolding = true;
+ }
+ }
+
+ sortable.animateAll(function () {
+ folding = false;
+ initialFolding = false;
+
+ if (_this2.options.animation) {
+ multiDragElements.forEach(function (multiDragElement) {
+ unsetRect(multiDragElement);
+ });
+ } // Remove all auxiliary multidrag items from el, if sorting enabled
+
+
+ if (_this2.options.sort) {
+ removeMultiDragElements();
+ }
+ });
+ },
+ dragOver: function dragOver(_ref8) {
+ var target = _ref8.target,
+ completed = _ref8.completed,
+ cancel = _ref8.cancel;
+
+ if (folding && ~multiDragElements.indexOf(target)) {
+ completed(false);
+ cancel();
+ }
+ },
+ revert: function revert(_ref9) {
+ var fromSortable = _ref9.fromSortable,
+ rootEl = _ref9.rootEl,
+ sortable = _ref9.sortable,
+ dragRect = _ref9.dragRect;
+
+ if (multiDragElements.length > 1) {
+ // Setup unfold animation
+ multiDragElements.forEach(function (multiDragElement) {
+ sortable.addAnimationState({
+ target: multiDragElement,
+ rect: folding ? getRect(multiDragElement) : dragRect
+ });
+ unsetRect(multiDragElement);
+ multiDragElement.fromRect = dragRect;
+ fromSortable.removeAnimationState(multiDragElement);
+ });
+ folding = false;
+ insertMultiDragElements(!this.options.removeCloneOnHide, rootEl);
+ }
+ },
+ dragOverCompleted: function dragOverCompleted(_ref10) {
+ var sortable = _ref10.sortable,
+ isOwner = _ref10.isOwner,
+ insertion = _ref10.insertion,
+ activeSortable = _ref10.activeSortable,
+ parentEl = _ref10.parentEl,
+ putSortable = _ref10.putSortable;
+ var options = this.options;
+
+ if (insertion) {
+ // Clones must be hidden before folding animation to capture dragRectAbsolute properly
+ if (isOwner) {
+ activeSortable._hideClone();
+ }
+
+ initialFolding = false; // If leaving sort:false root, or already folding - Fold to new location
+
+ if (options.animation && multiDragElements.length > 1 && (folding || !isOwner && !activeSortable.options.sort && !putSortable)) {
+ // Fold: Set all multi drag elements's rects to dragEl's rect when multi-drag elements are invisible
+ var dragRectAbsolute = getRect(dragEl$1, false, true, true);
+ multiDragElements.forEach(function (multiDragElement) {
+ if (multiDragElement === dragEl$1) return;
+ setRect(multiDragElement, dragRectAbsolute); // Move element(s) to end of parentEl so that it does not interfere with multi-drag clones insertion if they are inserted
+ // while folding, and so that we can capture them again because old sortable will no longer be fromSortable
+
+ parentEl.appendChild(multiDragElement);
+ });
+ folding = true;
+ } // Clones must be shown (and check to remove multi drags) after folding when interfering multiDragElements are moved out
+
+
+ if (!isOwner) {
+ // Only remove if not folding (folding will remove them anyways)
+ if (!folding) {
+ removeMultiDragElements();
+ }
+
+ if (multiDragElements.length > 1) {
+ var clonesHiddenBefore = clonesHidden;
+
+ activeSortable._showClone(sortable); // Unfold animation for clones if showing from hidden
+
+
+ if (activeSortable.options.animation && !clonesHidden && clonesHiddenBefore) {
+ multiDragClones.forEach(function (clone) {
+ activeSortable.addAnimationState({
+ target: clone,
+ rect: clonesFromRect
+ });
+ clone.fromRect = clonesFromRect;
+ clone.thisAnimationDuration = null;
+ });
+ }
+ } else {
+ activeSortable._showClone(sortable);
+ }
+ }
+ }
+ },
+ dragOverAnimationCapture: function dragOverAnimationCapture(_ref11) {
+ var dragRect = _ref11.dragRect,
+ isOwner = _ref11.isOwner,
+ activeSortable = _ref11.activeSortable;
+ multiDragElements.forEach(function (multiDragElement) {
+ multiDragElement.thisAnimationDuration = null;
+ });
+
+ if (activeSortable.options.animation && !isOwner && activeSortable.multiDrag.isMultiDrag) {
+ clonesFromRect = _extends({}, dragRect);
+ var dragMatrix = matrix(dragEl$1, true);
+ clonesFromRect.top -= dragMatrix.f;
+ clonesFromRect.left -= dragMatrix.e;
+ }
+ },
+ dragOverAnimationComplete: function dragOverAnimationComplete() {
+ if (folding) {
+ folding = false;
+ removeMultiDragElements();
+ }
+ },
+ drop: function drop(_ref12) {
+ var evt = _ref12.originalEvent,
+ rootEl = _ref12.rootEl,
+ parentEl = _ref12.parentEl,
+ sortable = _ref12.sortable,
+ dispatchSortableEvent = _ref12.dispatchSortableEvent,
+ oldIndex = _ref12.oldIndex,
+ putSortable = _ref12.putSortable;
+ var toSortable = putSortable || this.sortable;
+ if (!evt) return;
+ var options = this.options,
+ children = parentEl.children; // Multi-drag selection
+
+ if (!dragStarted) {
+ if (options.multiDragKey && !this.multiDragKeyDown) {
+ this._deselectMultiDrag();
+ }
+
+ toggleClass(dragEl$1, options.selectedClass, !~multiDragElements.indexOf(dragEl$1));
+
+ if (!~multiDragElements.indexOf(dragEl$1)) {
+ multiDragElements.push(dragEl$1);
+ dispatchEvent({
+ sortable: sortable,
+ rootEl: rootEl,
+ name: 'select',
+ targetEl: dragEl$1,
+ originalEvt: evt
+ }); // Modifier activated, select from last to dragEl
+
+ if (evt.shiftKey && lastMultiDragSelect && sortable.el.contains(lastMultiDragSelect)) {
+ var lastIndex = index(lastMultiDragSelect),
+ currentIndex = index(dragEl$1);
+
+ if (~lastIndex && ~currentIndex && lastIndex !== currentIndex) {
+ // Must include lastMultiDragSelect (select it), in case modified selection from no selection
+ // (but previous selection existed)
+ var n, i;
+
+ if (currentIndex > lastIndex) {
+ i = lastIndex;
+ n = currentIndex;
+ } else {
+ i = currentIndex;
+ n = lastIndex + 1;
+ }
+
+ for (; i < n; i++) {
+ if (~multiDragElements.indexOf(children[i])) continue;
+ toggleClass(children[i], options.selectedClass, true);
+ multiDragElements.push(children[i]);
+ dispatchEvent({
+ sortable: sortable,
+ rootEl: rootEl,
+ name: 'select',
+ targetEl: children[i],
+ originalEvt: evt
+ });
+ }
+ }
+ } else {
+ lastMultiDragSelect = dragEl$1;
+ }
+
+ multiDragSortable = toSortable;
+ } else {
+ multiDragElements.splice(multiDragElements.indexOf(dragEl$1), 1);
+ lastMultiDragSelect = null;
+ dispatchEvent({
+ sortable: sortable,
+ rootEl: rootEl,
+ name: 'deselect',
+ targetEl: dragEl$1,
+ originalEvt: evt
+ });
+ }
+ } // Multi-drag drop
+
+
+ if (dragStarted && this.isMultiDrag) {
+ // Do not "unfold" after around dragEl if reverted
+ if ((parentEl[expando].options.sort || parentEl !== rootEl) && multiDragElements.length > 1) {
+ var dragRect = getRect(dragEl$1),
+ multiDragIndex = index(dragEl$1, ':not(.' + this.options.selectedClass + ')');
+ if (!initialFolding && options.animation) dragEl$1.thisAnimationDuration = null;
+ toSortable.captureAnimationState();
+
+ if (!initialFolding) {
+ if (options.animation) {
+ dragEl$1.fromRect = dragRect;
+ multiDragElements.forEach(function (multiDragElement) {
+ multiDragElement.thisAnimationDuration = null;
+
+ if (multiDragElement !== dragEl$1) {
+ var rect = folding ? getRect(multiDragElement) : dragRect;
+ multiDragElement.fromRect = rect; // Prepare unfold animation
+
+ toSortable.addAnimationState({
+ target: multiDragElement,
+ rect: rect
+ });
+ }
+ });
+ } // Multi drag elements are not necessarily removed from the DOM on drop, so to reinsert
+ // properly they must all be removed
+
+
+ removeMultiDragElements();
+ multiDragElements.forEach(function (multiDragElement) {
+ if (children[multiDragIndex]) {
+ parentEl.insertBefore(multiDragElement, children[multiDragIndex]);
+ } else {
+ parentEl.appendChild(multiDragElement);
+ }
+
+ multiDragIndex++;
+ }); // If initial folding is done, the elements may have changed position because they are now
+ // unfolding around dragEl, even though dragEl may not have his index changed, so update event
+ // must be fired here as Sortable will not.
+
+ if (oldIndex === index(dragEl$1)) {
+ var update = false;
+ multiDragElements.forEach(function (multiDragElement) {
+ if (multiDragElement.sortableIndex !== index(multiDragElement)) {
+ update = true;
+ return;
+ }
+ });
+
+ if (update) {
+ dispatchSortableEvent('update');
+ }
+ }
+ } // Must be done after capturing individual rects (scroll bar)
+
+
+ multiDragElements.forEach(function (multiDragElement) {
+ unsetRect(multiDragElement);
+ });
+ toSortable.animateAll();
+ }
+
+ multiDragSortable = toSortable;
+ } // Remove clones if necessary
+
+
+ if (rootEl === parentEl || putSortable && putSortable.lastPutMode !== 'clone') {
+ multiDragClones.forEach(function (clone) {
+ clone.parentNode && clone.parentNode.removeChild(clone);
+ });
+ }
+ },
+ nullingGlobal: function nullingGlobal() {
+ this.isMultiDrag = dragStarted = false;
+ multiDragClones.length = 0;
+ },
+ destroyGlobal: function destroyGlobal() {
+ this._deselectMultiDrag();
+
+ off(document, 'pointerup', this._deselectMultiDrag);
+ off(document, 'mouseup', this._deselectMultiDrag);
+ off(document, 'touchend', this._deselectMultiDrag);
+ off(document, 'keydown', this._checkKeyDown);
+ off(document, 'keyup', this._checkKeyUp);
+ },
+ _deselectMultiDrag: function _deselectMultiDrag(evt) {
+ if (typeof dragStarted !== "undefined" && dragStarted) return; // Only deselect if selection is in this sortable
+
+ if (multiDragSortable !== this.sortable) return; // Only deselect if target is not item in this sortable
+
+ if (evt && closest(evt.target, this.options.draggable, this.sortable.el, false)) return; // Only deselect if left click
+
+ if (evt && evt.button !== 0) return;
+
+ while (multiDragElements.length) {
+ var el = multiDragElements[0];
+ toggleClass(el, this.options.selectedClass, false);
+ multiDragElements.shift();
+ dispatchEvent({
+ sortable: this.sortable,
+ rootEl: this.sortable.el,
+ name: 'deselect',
+ targetEl: el,
+ originalEvt: evt
+ });
+ }
+ },
+ _checkKeyDown: function _checkKeyDown(evt) {
+ if (evt.key === this.options.multiDragKey) {
+ this.multiDragKeyDown = true;
+ }
+ },
+ _checkKeyUp: function _checkKeyUp(evt) {
+ if (evt.key === this.options.multiDragKey) {
+ this.multiDragKeyDown = false;
+ }
+ }
+ };
+ return _extends(MultiDrag, {
+ // Static methods & properties
+ pluginName: 'multiDrag',
+ utils: {
+ /**
+ * Selects the provided multi-drag item
+ * @param {HTMLElement} el The element to be selected
+ */
+ select: function select(el) {
+ var sortable = el.parentNode[expando];
+ if (!sortable || !sortable.options.multiDrag || ~multiDragElements.indexOf(el)) return;
+
+ if (multiDragSortable && multiDragSortable !== sortable) {
+ multiDragSortable.multiDrag._deselectMultiDrag();
+
+ multiDragSortable = sortable;
+ }
+
+ toggleClass(el, sortable.options.selectedClass, true);
+ multiDragElements.push(el);
+ },
+
+ /**
+ * Deselects the provided multi-drag item
+ * @param {HTMLElement} el The element to be deselected
+ */
+ deselect: function deselect(el) {
+ var sortable = el.parentNode[expando],
+ index = multiDragElements.indexOf(el);
+ if (!sortable || !sortable.options.multiDrag || !~index) return;
+ toggleClass(el, sortable.options.selectedClass, false);
+ multiDragElements.splice(index, 1);
+ }
+ },
+ eventProperties: function eventProperties() {
+ var _this3 = this;
+
+ var oldIndicies = [],
+ newIndicies = [];
+ multiDragElements.forEach(function (multiDragElement) {
+ oldIndicies.push({
+ multiDragElement: multiDragElement,
+ index: multiDragElement.sortableIndex
+ }); // multiDragElements will already be sorted if folding
+
+ var newIndex;
+
+ if (folding && multiDragElement !== dragEl$1) {
+ newIndex = -1;
+ } else if (folding) {
+ newIndex = index(multiDragElement, ':not(.' + _this3.options.selectedClass + ')');
+ } else {
+ newIndex = index(multiDragElement);
+ }
+
+ newIndicies.push({
+ multiDragElement: multiDragElement,
+ index: newIndex
+ });
+ });
+ return {
+ items: _toConsumableArray(multiDragElements),
+ clones: [].concat(multiDragClones),
+ oldIndicies: oldIndicies,
+ newIndicies: newIndicies
+ };
+ },
+ optionListeners: {
+ multiDragKey: function multiDragKey(key) {
+ key = key.toLowerCase();
+
+ if (key === 'ctrl') {
+ key = 'Control';
+ } else if (key.length > 1) {
+ key = key.charAt(0).toUpperCase() + key.substr(1);
+ }
+
+ return key;
+ }
+ }
+ });
+ }
+
+ function insertMultiDragElements(clonesInserted, rootEl) {
+ multiDragElements.forEach(function (multiDragElement, i) {
+ var target = rootEl.children[multiDragElement.sortableIndex + (clonesInserted ? Number(i) : 0)];
+
+ if (target) {
+ rootEl.insertBefore(multiDragElement, target);
+ } else {
+ rootEl.appendChild(multiDragElement);
+ }
+ });
+ }
+ /**
+ * Insert multi-drag clones
+ * @param {[Boolean]} elementsInserted Whether the multi-drag elements are inserted
+ * @param {HTMLElement} rootEl
+ */
+
+
+ function insertMultiDragClones(elementsInserted, rootEl) {
+ multiDragClones.forEach(function (clone, i) {
+ var target = rootEl.children[clone.sortableIndex + (elementsInserted ? Number(i) : 0)];
+
+ if (target) {
+ rootEl.insertBefore(clone, target);
+ } else {
+ rootEl.appendChild(clone);
+ }
+ });
+ }
+
+ function removeMultiDragElements() {
+ multiDragElements.forEach(function (multiDragElement) {
+ if (multiDragElement === dragEl$1) return;
+ multiDragElement.parentNode && multiDragElement.parentNode.removeChild(multiDragElement);
+ });
+ }
+
+ Sortable.mount(new AutoScrollPlugin());
+ Sortable.mount(Remove, Revert);
+
+ Sortable.mount(new SwapPlugin());
+ Sortable.mount(new MultiDragPlugin());
+
+ return Sortable;
+
+}));
diff --git a/asset/js/vendor/Sortable.min.js b/asset/js/vendor/Sortable.min.js
new file mode 100644
index 0000000..ad0275a
--- /dev/null
+++ b/asset/js/vendor/Sortable.min.js
@@ -0,0 +1,2 @@
+/*! Sortable 1.13.0 - MIT | git://github.com/SortableJS/Sortable.git */
+!function(t,e){"object"==typeof exports&&"undefined"!=typeof module?module.exports=e():"function"==typeof define&&define.icinga?define(e):(t=t||self).Sortable=e()}(this,function(){"use strict";function o(t){return(o="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t})(t)}function a(){return(a=Object.assign||function(t){for(var e=1;e<arguments.length;e++){var n=arguments[e];for(var o in n)Object.prototype.hasOwnProperty.call(n,o)&&(t[o]=n[o])}return t}).apply(this,arguments)}function I(i){for(var t=1;t<arguments.length;t++){var r=null!=arguments[t]?arguments[t]:{},e=Object.keys(r);"function"==typeof Object.getOwnPropertySymbols&&(e=e.concat(Object.getOwnPropertySymbols(r).filter(function(t){return Object.getOwnPropertyDescriptor(r,t).enumerable}))),e.forEach(function(t){var e,n,o;e=i,o=r[n=t],n in e?Object.defineProperty(e,n,{value:o,enumerable:!0,configurable:!0,writable:!0}):e[n]=o})}return i}function l(t,e){if(null==t)return{};var n,o,i=function(t,e){if(null==t)return{};var n,o,i={},r=Object.keys(t);for(o=0;o<r.length;o++)n=r[o],0<=e.indexOf(n)||(i[n]=t[n]);return i}(t,e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(t);for(o=0;o<r.length;o++)n=r[o],0<=e.indexOf(n)||Object.prototype.propertyIsEnumerable.call(t,n)&&(i[n]=t[n])}return i}function e(t){return function(t){if(Array.isArray(t)){for(var e=0,n=new Array(t.length);e<t.length;e++)n[e]=t[e];return n}}(t)||function(t){if(Symbol.iterator in Object(t)||"[object Arguments]"===Object.prototype.toString.call(t))return Array.from(t)}(t)||function(){throw new TypeError("Invalid attempt to spread non-iterable instance")}()}function t(t){if("undefined"!=typeof window&&window.navigator)return!!navigator.userAgent.match(t)}var w=t(/(?:Trident.*rv[ :]?11\.|msie|iemobile|Windows Phone)/i),E=t(/Edge/i),c=t(/firefox/i),u=t(/safari/i)&&!t(/chrome/i)&&!t(/android/i),n=t(/iP(ad|od|hone)/i),i=t(/chrome/i)&&t(/android/i),r={capture:!1,passive:!1};function d(t,e,n){t.addEventListener(e,n,!w&&r)}function s(t,e,n){t.removeEventListener(e,n,!w&&r)}function h(t,e){if(e){if(">"===e[0]&&(e=e.substring(1)),t)try{if(t.matches)return t.matches(e);if(t.msMatchesSelector)return t.msMatchesSelector(e);if(t.webkitMatchesSelector)return t.webkitMatchesSelector(e)}catch(t){return!1}return!1}}function P(t,e,n,o){if(t){n=n||document;do{if(null!=e&&(">"===e[0]?t.parentNode===n&&h(t,e):h(t,e))||o&&t===n)return t;if(t===n)break}while(t=(i=t).host&&i!==document&&i.host.nodeType?i.host:i.parentNode)}var i;return null}var f,p=/\s+/g;function k(t,e,n){if(t&&e)if(t.classList)t.classList[n?"add":"remove"](e);else{var o=(" "+t.className+" ").replace(p," ").replace(" "+e+" "," ");t.className=(o+(n?" "+e:"")).replace(p," ")}}function R(t,e,n){var o=t&&t.style;if(o){if(void 0===n)return document.defaultView&&document.defaultView.getComputedStyle?n=document.defaultView.getComputedStyle(t,""):t.currentStyle&&(n=t.currentStyle),void 0===e?n:n[e];e in o||-1!==e.indexOf("webkit")||(e="-webkit-"+e),o[e]=n+("string"==typeof n?"":"px")}}function v(t,e){var n="";if("string"==typeof t)n=t;else do{var o=R(t,"transform");o&&"none"!==o&&(n=o+" "+n)}while(!e&&(t=t.parentNode));var i=window.DOMMatrix||window.WebKitCSSMatrix||window.CSSMatrix||window.MSCSSMatrix;return i&&new i(n)}function g(t,e,n){if(t){var o=t.getElementsByTagName(e),i=0,r=o.length;if(n)for(;i<r;i++)n(o[i],i);return o}return[]}function A(){var t=document.scrollingElement;return t||document.documentElement}function X(t,e,n,o,i){if(t.getBoundingClientRect||t===window){var r,a,l,s,c,u,d;if(d=t!==window&&t.parentNode&&t!==A()?(a=(r=t.getBoundingClientRect()).top,l=r.left,s=r.bottom,c=r.right,u=r.height,r.width):(l=a=0,s=window.innerHeight,c=window.innerWidth,u=window.innerHeight,window.innerWidth),(e||n)&&t!==window&&(i=i||t.parentNode,!w))do{if(i&&i.getBoundingClientRect&&("none"!==R(i,"transform")||n&&"static"!==R(i,"position"))){var h=i.getBoundingClientRect();a-=h.top+parseInt(R(i,"border-top-width")),l-=h.left+parseInt(R(i,"border-left-width")),s=a+r.height,c=l+r.width;break}}while(i=i.parentNode);if(o&&t!==window){var f=v(i||t),p=f&&f.a,g=f&&f.d;f&&(s=(a/=g)+(u/=g),c=(l/=p)+(d/=p))}return{top:a,left:l,bottom:s,right:c,width:d,height:u}}}function Y(t,e,n){for(var o=H(t,!0),i=X(t)[e];o;){var r=X(o)[n];if(!("top"===n||"left"===n?r<=i:i<=r))return o;if(o===A())break;o=H(o,!1)}return!1}function m(t,e,n){for(var o=0,i=0,r=t.children;i<r.length;){if("none"!==r[i].style.display&&r[i]!==Rt.ghost&&r[i]!==Rt.dragged&&P(r[i],n.draggable,t,!1)){if(o===e)return r[i];o++}i++}return null}function B(t,e){for(var n=t.lastElementChild;n&&(n===Rt.ghost||"none"===R(n,"display")||e&&!h(n,e));)n=n.previousElementSibling;return n||null}function F(t,e){var n=0;if(!t||!t.parentNode)return-1;for(;t=t.previousElementSibling;)"TEMPLATE"===t.nodeName.toUpperCase()||t===Rt.clone||e&&!h(t,e)||n++;return n}function b(t){var e=0,n=0,o=A();if(t)do{var i=v(t),r=i.a,a=i.d;e+=t.scrollLeft*r,n+=t.scrollTop*a}while(t!==o&&(t=t.parentNode));return[e,n]}function H(t,e){if(!t||!t.getBoundingClientRect)return A();var n=t,o=!1;do{if(n.clientWidth<n.scrollWidth||n.clientHeight<n.scrollHeight){var i=R(n);if(n.clientWidth<n.scrollWidth&&("auto"==i.overflowX||"scroll"==i.overflowX)||n.clientHeight<n.scrollHeight&&("auto"==i.overflowY||"scroll"==i.overflowY)){if(!n.getBoundingClientRect||n===document.body)return A();if(o||e)return n;o=!0}}}while(n=n.parentNode);return A()}function y(t,e){return Math.round(t.top)===Math.round(e.top)&&Math.round(t.left)===Math.round(e.left)&&Math.round(t.height)===Math.round(e.height)&&Math.round(t.width)===Math.round(e.width)}function D(e,n){return function(){if(!f){var t=arguments;1===t.length?e.call(this,t[0]):e.apply(this,t),f=setTimeout(function(){f=void 0},n)}}}function L(t,e,n){t.scrollLeft+=e,t.scrollTop+=n}function S(t){var e=window.Polymer,n=window.jQuery||window.Zepto;return e&&e.dom?e.dom(t).cloneNode(!0):n?n(t).clone(!0)[0]:t.cloneNode(!0)}function _(t,e){R(t,"position","absolute"),R(t,"top",e.top),R(t,"left",e.left),R(t,"width",e.width),R(t,"height",e.height)}function C(t){R(t,"position",""),R(t,"top",""),R(t,"left",""),R(t,"width",""),R(t,"height","")}var j="Sortable"+(new Date).getTime();function T(){var e,o=[];return{captureAnimationState:function(){o=[],this.options.animation&&[].slice.call(this.el.children).forEach(function(t){if("none"!==R(t,"display")&&t!==Rt.ghost){o.push({target:t,rect:X(t)});var e=I({},o[o.length-1].rect);if(t.thisAnimationDuration){var n=v(t,!0);n&&(e.top-=n.f,e.left-=n.e)}t.fromRect=e}})},addAnimationState:function(t){o.push(t)},removeAnimationState:function(t){o.splice(function(t,e){for(var n in t)if(t.hasOwnProperty(n))for(var o in e)if(e.hasOwnProperty(o)&&e[o]===t[n][o])return Number(n);return-1}(o,{target:t}),1)},animateAll:function(t){var c=this;if(!this.options.animation)return clearTimeout(e),void("function"==typeof t&&t());var u=!1,d=0;o.forEach(function(t){var e=0,n=t.target,o=n.fromRect,i=X(n),r=n.prevFromRect,a=n.prevToRect,l=t.rect,s=v(n,!0);s&&(i.top-=s.f,i.left-=s.e),n.toRect=i,n.thisAnimationDuration&&y(r,i)&&!y(o,i)&&(l.top-i.top)/(l.left-i.left)==(o.top-i.top)/(o.left-i.left)&&(e=function(t,e,n,o){return Math.sqrt(Math.pow(e.top-t.top,2)+Math.pow(e.left-t.left,2))/Math.sqrt(Math.pow(e.top-n.top,2)+Math.pow(e.left-n.left,2))*o.animation}(l,r,a,c.options)),y(i,o)||(n.prevFromRect=o,n.prevToRect=i,e||(e=c.options.animation),c.animate(n,l,i,e)),e&&(u=!0,d=Math.max(d,e),clearTimeout(n.animationResetTimer),n.animationResetTimer=setTimeout(function(){n.animationTime=0,n.prevFromRect=null,n.fromRect=null,n.prevToRect=null,n.thisAnimationDuration=null},e),n.thisAnimationDuration=e)}),clearTimeout(e),u?e=setTimeout(function(){"function"==typeof t&&t()},d):"function"==typeof t&&t(),o=[]},animate:function(t,e,n,o){if(o){R(t,"transition",""),R(t,"transform","");var i=v(this.el),r=i&&i.a,a=i&&i.d,l=(e.left-n.left)/(r||1),s=(e.top-n.top)/(a||1);t.animatingX=!!l,t.animatingY=!!s,R(t,"transform","translate3d("+l+"px,"+s+"px,0)"),this.forRepaintDummy=function(t){return t.offsetWidth}(t),R(t,"transition","transform "+o+"ms"+(this.options.easing?" "+this.options.easing:"")),R(t,"transform","translate3d(0,0,0)"),"number"==typeof t.animated&&clearTimeout(t.animated),t.animated=setTimeout(function(){R(t,"transition",""),R(t,"transform",""),t.animated=!1,t.animatingX=!1,t.animatingY=!1},o)}}}}var x=[],M={initializeByDefault:!0},O={mount:function(e){for(var t in M)!M.hasOwnProperty(t)||t in e||(e[t]=M[t]);x.forEach(function(t){if(t.pluginName===e.pluginName)throw"Sortable: Cannot mount plugin ".concat(e.pluginName," more than once")}),x.push(e)},pluginEvent:function(e,n,o){var t=this;this.eventCanceled=!1,o.cancel=function(){t.eventCanceled=!0};var i=e+"Global";x.forEach(function(t){n[t.pluginName]&&(n[t.pluginName][i]&&n[t.pluginName][i](I({sortable:n},o)),n.options[t.pluginName]&&n[t.pluginName][e]&&n[t.pluginName][e](I({sortable:n},o)))})},initializePlugins:function(o,i,r,t){for(var e in x.forEach(function(t){var e=t.pluginName;if(o.options[e]||t.initializeByDefault){var n=new t(o,i,o.options);n.sortable=o,n.options=o.options,o[e]=n,a(r,n.defaults)}}),o.options)if(o.options.hasOwnProperty(e)){var n=this.modifyOption(o,e,o.options[e]);void 0!==n&&(o.options[e]=n)}},getEventProperties:function(e,n){var o={};return x.forEach(function(t){"function"==typeof t.eventProperties&&a(o,t.eventProperties.call(n[t.pluginName],e))}),o},modifyOption:function(e,n,o){var i;return x.forEach(function(t){e[t.pluginName]&&t.optionListeners&&"function"==typeof t.optionListeners[n]&&(i=t.optionListeners[n].call(e[t.pluginName],o))}),i}};function N(t){var e=t.sortable,n=t.rootEl,o=t.name,i=t.targetEl,r=t.cloneEl,a=t.toEl,l=t.fromEl,s=t.oldIndex,c=t.newIndex,u=t.oldDraggableIndex,d=t.newDraggableIndex,h=t.originalEvent,f=t.putSortable,p=t.extraEventProperties;if(e=e||n&&n[j]){var g,v=e.options,m="on"+o.charAt(0).toUpperCase()+o.substr(1);!window.CustomEvent||w||E?(g=document.createEvent("Event")).initEvent(o,!0,!0):g=new CustomEvent(o,{bubbles:!0,cancelable:!0}),g.to=a||n,g.from=l||n,g.item=i||n,g.clone=r,g.oldIndex=s,g.newIndex=c,g.oldDraggableIndex=u,g.newDraggableIndex=d,g.originalEvent=h,g.pullMode=f?f.lastPutMode:void 0;var b=I({},p,O.getEventProperties(o,e));for(var y in b)g[y]=b[y];n&&n.dispatchEvent(g),v[m]&&v[m].call(e,g)}}function K(t,e,n){var o=2<arguments.length&&void 0!==n?n:{},i=o.evt,r=l(o,["evt"]);O.pluginEvent.bind(Rt)(t,e,I({dragEl:z,parentEl:G,ghostEl:U,rootEl:q,nextEl:V,lastDownEl:Z,cloneEl:Q,cloneHidden:$,dragStarted:dt,putSortable:it,activeSortable:Rt.active,originalEvent:i,oldIndex:J,oldDraggableIndex:et,newIndex:tt,newDraggableIndex:nt,hideGhostForTarget:At,unhideGhostForTarget:It,cloneNowHidden:function(){$=!0},cloneNowShown:function(){$=!1},dispatchSortableEvent:function(t){W({sortable:e,name:t,originalEvent:i})}},r))}function W(t){N(I({putSortable:it,cloneEl:Q,targetEl:z,rootEl:q,oldIndex:J,oldDraggableIndex:et,newIndex:tt,newDraggableIndex:nt},t))}var z,G,U,q,V,Z,Q,$,J,tt,et,nt,ot,it,rt,at,lt,st,ct,ut,dt,ht,ft,pt,gt,vt=!1,mt=!1,bt=[],yt=!1,wt=!1,Et=[],Dt=!1,St=[],_t="undefined"!=typeof document,Ct=n,Tt=E||w?"cssFloat":"float",xt=_t&&!i&&!n&&"draggable"in document.createElement("div"),Mt=function(){if(_t){if(w)return!1;var t=document.createElement("x");return t.style.cssText="pointer-events:auto","auto"===t.style.pointerEvents}}(),Ot=function(t,e){var n=R(t),o=parseInt(n.width)-parseInt(n.paddingLeft)-parseInt(n.paddingRight)-parseInt(n.borderLeftWidth)-parseInt(n.borderRightWidth),i=m(t,0,e),r=m(t,1,e),a=i&&R(i),l=r&&R(r),s=a&&parseInt(a.marginLeft)+parseInt(a.marginRight)+X(i).width,c=l&&parseInt(l.marginLeft)+parseInt(l.marginRight)+X(r).width;if("flex"===n.display)return"column"===n.flexDirection||"column-reverse"===n.flexDirection?"vertical":"horizontal";if("grid"===n.display)return n.gridTemplateColumns.split(" ").length<=1?"vertical":"horizontal";if(i&&a.float&&"none"!==a.float){var u="left"===a.float?"left":"right";return!r||"both"!==l.clear&&l.clear!==u?"horizontal":"vertical"}return i&&("block"===a.display||"flex"===a.display||"table"===a.display||"grid"===a.display||o<=s&&"none"===n[Tt]||r&&"none"===n[Tt]&&o<s+c)?"vertical":"horizontal"},Nt=function(t){function s(a,l){return function(t,e,n,o){var i=t.options.group.name&&e.options.group.name&&t.options.group.name===e.options.group.name;if(null==a&&(l||i))return!0;if(null==a||!1===a)return!1;if(l&&"clone"===a)return a;if("function"==typeof a)return s(a(t,e,n,o),l)(t,e,n,o);var r=(l?t:e).options.group.name;return!0===a||"string"==typeof a&&a===r||a.join&&-1<a.indexOf(r)}}var e={},n=t.group;n&&"object"==o(n)||(n={name:n}),e.name=n.name,e.checkPull=s(n.pull,!0),e.checkPut=s(n.put),e.revertClone=n.revertClone,t.group=e},At=function(){!Mt&&U&&R(U,"display","none")},It=function(){!Mt&&U&&R(U,"display","")};_t&&document.addEventListener("click",function(t){if(mt)return t.preventDefault(),t.stopPropagation&&t.stopPropagation(),t.stopImmediatePropagation&&t.stopImmediatePropagation(),mt=!1},!0);function Pt(t){if(z){var e=function(r,a){var l;return bt.some(function(t){if(!B(t)){var e=X(t),n=t[j].options.emptyInsertThreshold,o=r>=e.left-n&&r<=e.right+n,i=a>=e.top-n&&a<=e.bottom+n;return n&&o&&i?l=t:void 0}}),l}((t=t.touches?t.touches[0]:t).clientX,t.clientY);if(e){var n={};for(var o in t)t.hasOwnProperty(o)&&(n[o]=t[o]);n.target=n.rootEl=e,n.preventDefault=void 0,n.stopPropagation=void 0,e[j]._onDragOver(n)}}}function kt(t){z&&z.parentNode[j]._isOutsideThisEl(t.target)}function Rt(t,e){if(!t||!t.nodeType||1!==t.nodeType)throw"Sortable: `el` must be an HTMLElement, not ".concat({}.toString.call(t));this.el=t,this.options=e=a({},e),t[j]=this;var n={group:null,sort:!0,disabled:!1,store:null,handle:null,draggable:/^[uo]l$/i.test(t.nodeName)?">li":">*",swapThreshold:1,invertSwap:!1,invertedSwapThreshold:null,removeCloneOnHide:!0,direction:function(){return Ot(t,this.options)},ghostClass:"sortable-ghost",chosenClass:"sortable-chosen",dragClass:"sortable-drag",ignore:"a, img",filter:null,preventOnFilter:!0,animation:0,easing:null,setData:function(t,e){t.setData("Text",e.textContent)},dropBubble:!1,dragoverBubble:!1,dataIdAttr:"data-id",delay:0,delayOnTouchOnly:!1,touchStartThreshold:(Number.parseInt?Number:window).parseInt(window.devicePixelRatio,10)||1,forceFallback:!1,fallbackClass:"sortable-fallback",fallbackOnBody:!1,fallbackTolerance:0,fallbackOffset:{x:0,y:0},supportPointer:!1!==Rt.supportPointer&&"PointerEvent"in window&&!u,emptyInsertThreshold:5};for(var o in O.initializePlugins(this,t,n),n)o in e||(e[o]=n[o]);for(var i in Nt(e),this)"_"===i.charAt(0)&&"function"==typeof this[i]&&(this[i]=this[i].bind(this));this.nativeDraggable=!e.forceFallback&&xt,this.nativeDraggable&&(this.options.touchStartThreshold=1),e.supportPointer?d(t,"pointerdown",this._onTapStart):(d(t,"mousedown",this._onTapStart),d(t,"touchstart",this._onTapStart)),this.nativeDraggable&&(d(t,"dragover",this),d(t,"dragenter",this)),bt.push(this.el),e.store&&e.store.get&&this.sort(e.store.get(this)||[]),a(this,T())}function Xt(t,e,n,o,i,r,a,l){var s,c,u=t[j],d=u.options.onMove;return!window.CustomEvent||w||E?(s=document.createEvent("Event")).initEvent("move",!0,!0):s=new CustomEvent("move",{bubbles:!0,cancelable:!0}),s.to=e,s.from=t,s.dragged=n,s.draggedRect=o,s.related=i||e,s.relatedRect=r||X(e),s.willInsertAfter=l,s.originalEvent=a,t.dispatchEvent(s),d&&(c=d.call(u,s,a)),c}function Yt(t){t.draggable=!1}function Bt(){Dt=!1}function Ft(t){for(var e=t.tagName+t.className+t.src+t.href+t.textContent,n=e.length,o=0;n--;)o+=e.charCodeAt(n);return o.toString(36)}function Ht(t){return setTimeout(t,0)}function Lt(t){return clearTimeout(t)}Rt.prototype={constructor:Rt,_isOutsideThisEl:function(t){this.el.contains(t)||t===this.el||(ht=null)},_getDirection:function(t,e){return"function"==typeof this.options.direction?this.options.direction.call(this,t,e,z):this.options.direction},_onTapStart:function(e){if(e.cancelable){var n=this,o=this.el,t=this.options,i=t.preventOnFilter,r=e.type,a=e.touches&&e.touches[0]||e.pointerType&&"touch"===e.pointerType&&e,l=(a||e).target,s=e.target.shadowRoot&&(e.path&&e.path[0]||e.composedPath&&e.composedPath()[0])||l,c=t.filter;if(function(t){St.length=0;var e=t.getElementsByTagName("input"),n=e.length;for(;n--;){var o=e[n];o.checked&&St.push(o)}}(o),!z&&!(/mousedown|pointerdown/.test(r)&&0!==e.button||t.disabled)&&!s.isContentEditable&&(this.nativeDraggable||!u||!l||"SELECT"!==l.tagName.toUpperCase())&&!((l=P(l,t.draggable,o,!1))&&l.animated||Z===l)){if(J=F(l),et=F(l,t.draggable),"function"==typeof c){if(c.call(this,e,l,this))return W({sortable:n,rootEl:s,name:"filter",targetEl:l,toEl:o,fromEl:o}),K("filter",n,{evt:e}),void(i&&e.cancelable&&e.preventDefault())}else if(c&&(c=c.split(",").some(function(t){if(t=P(s,t.trim(),o,!1))return W({sortable:n,rootEl:t,name:"filter",targetEl:l,fromEl:o,toEl:o}),K("filter",n,{evt:e}),!0})))return void(i&&e.cancelable&&e.preventDefault());t.handle&&!P(s,t.handle,o,!1)||this._prepareDragStart(e,a,l)}}},_prepareDragStart:function(t,e,n){var o,i=this,r=i.el,a=i.options,l=r.ownerDocument;if(n&&!z&&n.parentNode===r){var s=X(n);if(q=r,G=(z=n).parentNode,V=z.nextSibling,Z=n,ot=a.group,rt={target:Rt.dragged=z,clientX:(e||t).clientX,clientY:(e||t).clientY},ct=rt.clientX-s.left,ut=rt.clientY-s.top,this._lastX=(e||t).clientX,this._lastY=(e||t).clientY,z.style["will-change"]="all",o=function(){K("delayEnded",i,{evt:t}),Rt.eventCanceled?i._onDrop():(i._disableDelayedDragEvents(),!c&&i.nativeDraggable&&(z.draggable=!0),i._triggerDragStart(t,e),W({sortable:i,name:"choose",originalEvent:t}),k(z,a.chosenClass,!0))},a.ignore.split(",").forEach(function(t){g(z,t.trim(),Yt)}),d(l,"dragover",Pt),d(l,"mousemove",Pt),d(l,"touchmove",Pt),d(l,"mouseup",i._onDrop),d(l,"touchend",i._onDrop),d(l,"touchcancel",i._onDrop),c&&this.nativeDraggable&&(this.options.touchStartThreshold=4,z.draggable=!0),K("delayStart",this,{evt:t}),!a.delay||a.delayOnTouchOnly&&!e||this.nativeDraggable&&(E||w))o();else{if(Rt.eventCanceled)return void this._onDrop();d(l,"mouseup",i._disableDelayedDrag),d(l,"touchend",i._disableDelayedDrag),d(l,"touchcancel",i._disableDelayedDrag),d(l,"mousemove",i._delayedDragTouchMoveHandler),d(l,"touchmove",i._delayedDragTouchMoveHandler),a.supportPointer&&d(l,"pointermove",i._delayedDragTouchMoveHandler),i._dragStartTimer=setTimeout(o,a.delay)}}},_delayedDragTouchMoveHandler:function(t){var e=t.touches?t.touches[0]:t;Math.max(Math.abs(e.clientX-this._lastX),Math.abs(e.clientY-this._lastY))>=Math.floor(this.options.touchStartThreshold/(this.nativeDraggable&&window.devicePixelRatio||1))&&this._disableDelayedDrag()},_disableDelayedDrag:function(){z&&Yt(z),clearTimeout(this._dragStartTimer),this._disableDelayedDragEvents()},_disableDelayedDragEvents:function(){var t=this.el.ownerDocument;s(t,"mouseup",this._disableDelayedDrag),s(t,"touchend",this._disableDelayedDrag),s(t,"touchcancel",this._disableDelayedDrag),s(t,"mousemove",this._delayedDragTouchMoveHandler),s(t,"touchmove",this._delayedDragTouchMoveHandler),s(t,"pointermove",this._delayedDragTouchMoveHandler)},_triggerDragStart:function(t,e){e=e||"touch"==t.pointerType&&t,!this.nativeDraggable||e?this.options.supportPointer?d(document,"pointermove",this._onTouchMove):d(document,e?"touchmove":"mousemove",this._onTouchMove):(d(z,"dragend",this),d(q,"dragstart",this._onDragStart));try{document.selection?Ht(function(){document.selection.empty()}):window.getSelection().removeAllRanges()}catch(t){}},_dragStarted:function(t,e){if(vt=!1,q&&z){K("dragStarted",this,{evt:e}),this.nativeDraggable&&d(document,"dragover",kt);var n=this.options;t||k(z,n.dragClass,!1),k(z,n.ghostClass,!0),Rt.active=this,t&&this._appendGhost(),W({sortable:this,name:"start",originalEvent:e})}else this._nulling()},_emulateDragOver:function(){if(at){this._lastX=at.clientX,this._lastY=at.clientY,At();for(var t=document.elementFromPoint(at.clientX,at.clientY),e=t;t&&t.shadowRoot&&(t=t.shadowRoot.elementFromPoint(at.clientX,at.clientY))!==e;)e=t;if(z.parentNode[j]._isOutsideThisEl(t),e)do{if(e[j]){if(e[j]._onDragOver({clientX:at.clientX,clientY:at.clientY,target:t,rootEl:e})&&!this.options.dragoverBubble)break}t=e}while(e=e.parentNode);It()}},_onTouchMove:function(t){if(rt){var e=this.options,n=e.fallbackTolerance,o=e.fallbackOffset,i=t.touches?t.touches[0]:t,r=U&&v(U,!0),a=U&&r&&r.a,l=U&&r&&r.d,s=Ct&&gt&&b(gt),c=(i.clientX-rt.clientX+o.x)/(a||1)+(s?s[0]-Et[0]:0)/(a||1),u=(i.clientY-rt.clientY+o.y)/(l||1)+(s?s[1]-Et[1]:0)/(l||1);if(!Rt.active&&!vt){if(n&&Math.max(Math.abs(i.clientX-this._lastX),Math.abs(i.clientY-this._lastY))<n)return;this._onDragStart(t,!0)}if(U){r?(r.e+=c-(lt||0),r.f+=u-(st||0)):r={a:1,b:0,c:0,d:1,e:c,f:u};var d="matrix(".concat(r.a,",").concat(r.b,",").concat(r.c,",").concat(r.d,",").concat(r.e,",").concat(r.f,")");R(U,"webkitTransform",d),R(U,"mozTransform",d),R(U,"msTransform",d),R(U,"transform",d),lt=c,st=u,at=i}t.cancelable&&t.preventDefault()}},_appendGhost:function(){if(!U){var t=this.options.fallbackOnBody?document.body:q,e=X(z,!0,Ct,!0,t),n=this.options;if(Ct){for(gt=t;"static"===R(gt,"position")&&"none"===R(gt,"transform")&&gt!==document;)gt=gt.parentNode;gt!==document.body&&gt!==document.documentElement?(gt===document&&(gt=A()),e.top+=gt.scrollTop,e.left+=gt.scrollLeft):gt=A(),Et=b(gt)}k(U=z.cloneNode(!0),n.ghostClass,!1),k(U,n.fallbackClass,!0),k(U,n.dragClass,!0),R(U,"transition",""),R(U,"transform",""),R(U,"box-sizing","border-box"),R(U,"margin",0),R(U,"top",e.top),R(U,"left",e.left),R(U,"width",e.width),R(U,"height",e.height),R(U,"opacity","0.8"),R(U,"position",Ct?"absolute":"fixed"),R(U,"zIndex","100000"),R(U,"pointerEvents","none"),Rt.ghost=U,t.appendChild(U),R(U,"transform-origin",ct/parseInt(U.style.width)*100+"% "+ut/parseInt(U.style.height)*100+"%")}},_onDragStart:function(t,e){var n=this,o=t.dataTransfer,i=n.options;K("dragStart",this,{evt:t}),Rt.eventCanceled?this._onDrop():(K("setupClone",this),Rt.eventCanceled||((Q=S(z)).draggable=!1,Q.style["will-change"]="",this._hideClone(),k(Q,this.options.chosenClass,!1),Rt.clone=Q),n.cloneId=Ht(function(){K("clone",n),Rt.eventCanceled||(n.options.removeCloneOnHide||q.insertBefore(Q,z),n._hideClone(),W({sortable:n,name:"clone"}))}),e||k(z,i.dragClass,!0),e?(mt=!0,n._loopId=setInterval(n._emulateDragOver,50)):(s(document,"mouseup",n._onDrop),s(document,"touchend",n._onDrop),s(document,"touchcancel",n._onDrop),o&&(o.effectAllowed="move",i.setData&&i.setData.call(n,o,z)),d(document,"drop",n),R(z,"transform","translateZ(0)")),vt=!0,n._dragStartId=Ht(n._dragStarted.bind(n,e,t)),d(document,"selectstart",n),dt=!0,u&&R(document.body,"user-select","none"))},_onDragOver:function(n){var o,i,r,a,l=this.el,s=n.target,e=this.options,t=e.group,c=Rt.active,u=ot===t,d=e.sort,h=it||c,f=this,p=!1;if(!Dt){if(void 0!==n.preventDefault&&n.cancelable&&n.preventDefault(),s=P(s,e.draggable,l,!0),M("dragOver"),Rt.eventCanceled)return p;if(z.contains(n.target)||s.animated&&s.animatingX&&s.animatingY||f._ignoreWhileAnimating===s)return N(!1);if(mt=!1,c&&!e.disabled&&(u?d||(r=!q.contains(z)):it===this||(this.lastPutMode=ot.checkPull(this,c,z,n))&&t.checkPut(this,c,z,n))){if(a="vertical"===this._getDirection(n,s),o=X(z),M("dragOverValid"),Rt.eventCanceled)return p;if(r)return G=q,O(),this._hideClone(),M("revert"),Rt.eventCanceled||(V?q.insertBefore(z,V):q.appendChild(z)),N(!0);var g=B(l,e.draggable);if(!g||function(t,e,n){var o=X(B(n.el,n.options.draggable));return e?t.clientX>o.right+10||t.clientX<=o.right&&t.clientY>o.bottom&&t.clientX>=o.left:t.clientX>o.right&&t.clientY>o.top||t.clientX<=o.right&&t.clientY>o.bottom+10}(n,a,this)&&!g.animated){if(g===z)return N(!1);if(g&&l===n.target&&(s=g),s&&(i=X(s)),!1!==Xt(q,l,z,o,s,i,n,!!s))return O(),l.appendChild(z),G=l,A(),N(!0)}else if(s.parentNode===l){i=X(s);var v,m,b,y=z.parentNode!==l,w=!function(t,e,n){var o=n?t.left:t.top,i=n?t.right:t.bottom,r=n?t.width:t.height,a=n?e.left:e.top,l=n?e.right:e.bottom,s=n?e.width:e.height;return o===a||i===l||o+r/2===a+s/2}(z.animated&&z.toRect||o,s.animated&&s.toRect||i,a),E=a?"top":"left",D=Y(s,"top","top")||Y(z,"top","top"),S=D?D.scrollTop:void 0;if(ht!==s&&(m=i[E],yt=!1,wt=!w&&e.invertSwap||y),0!==(v=function(t,e,n,o,i,r,a,l){var s=o?t.clientY:t.clientX,c=o?n.height:n.width,u=o?n.top:n.left,d=o?n.bottom:n.right,h=!1;if(!a)if(l&&pt<c*i){if(!yt&&(1===ft?u+c*r/2<s:s<d-c*r/2)&&(yt=!0),yt)h=!0;else if(1===ft?s<u+pt:d-pt<s)return-ft}else if(u+c*(1-i)/2<s&&s<d-c*(1-i)/2)return function(t){return F(z)<F(t)?1:-1}(e);if((h=h||a)&&(s<u+c*r/2||d-c*r/2<s))return u+c/2<s?1:-1;return 0}(n,s,i,a,w?1:e.swapThreshold,null==e.invertedSwapThreshold?e.swapThreshold:e.invertedSwapThreshold,wt,ht===s)))for(var _=F(z);_-=v,(b=G.children[_])&&("none"===R(b,"display")||b===U););if(0===v||b===s)return N(!1);ft=v;var C=(ht=s).nextElementSibling,T=!1,x=Xt(q,l,z,o,s,i,n,T=1===v);if(!1!==x)return 1!==x&&-1!==x||(T=1===x),Dt=!0,setTimeout(Bt,30),O(),T&&!C?l.appendChild(z):s.parentNode.insertBefore(z,T?C:s),D&&L(D,0,S-D.scrollTop),G=z.parentNode,void 0===m||wt||(pt=Math.abs(m-X(s)[E])),A(),N(!0)}if(l.contains(z))return N(!1)}return!1}function M(t,e){K(t,f,I({evt:n,isOwner:u,axis:a?"vertical":"horizontal",revert:r,dragRect:o,targetRect:i,canSort:d,fromSortable:h,target:s,completed:N,onMove:function(t,e){return Xt(q,l,z,o,t,X(t),n,e)},changed:A},e))}function O(){M("dragOverAnimationCapture"),f.captureAnimationState(),f!==h&&h.captureAnimationState()}function N(t){return M("dragOverCompleted",{insertion:t}),t&&(u?c._hideClone():c._showClone(f),f!==h&&(k(z,it?it.options.ghostClass:c.options.ghostClass,!1),k(z,e.ghostClass,!0)),it!==f&&f!==Rt.active?it=f:f===Rt.active&&it&&(it=null),h===f&&(f._ignoreWhileAnimating=s),f.animateAll(function(){M("dragOverAnimationComplete"),f._ignoreWhileAnimating=null}),f!==h&&(h.animateAll(),h._ignoreWhileAnimating=null)),(s===z&&!z.animated||s===l&&!s.animated)&&(ht=null),e.dragoverBubble||n.rootEl||s===document||(z.parentNode[j]._isOutsideThisEl(n.target),t||Pt(n)),!e.dragoverBubble&&n.stopPropagation&&n.stopPropagation(),p=!0}function A(){tt=F(z),nt=F(z,e.draggable),W({sortable:f,name:"change",toEl:l,newIndex:tt,newDraggableIndex:nt,originalEvent:n})}},_ignoreWhileAnimating:null,_offMoveEvents:function(){s(document,"mousemove",this._onTouchMove),s(document,"touchmove",this._onTouchMove),s(document,"pointermove",this._onTouchMove),s(document,"dragover",Pt),s(document,"mousemove",Pt),s(document,"touchmove",Pt)},_offUpEvents:function(){var t=this.el.ownerDocument;s(t,"mouseup",this._onDrop),s(t,"touchend",this._onDrop),s(t,"pointerup",this._onDrop),s(t,"touchcancel",this._onDrop),s(document,"selectstart",this)},_onDrop:function(t){var e=this.el,n=this.options;tt=F(z),nt=F(z,n.draggable),K("drop",this,{evt:t}),G=z&&z.parentNode,tt=F(z),nt=F(z,n.draggable),Rt.eventCanceled||(yt=wt=vt=!1,clearInterval(this._loopId),clearTimeout(this._dragStartTimer),Lt(this.cloneId),Lt(this._dragStartId),this.nativeDraggable&&(s(document,"drop",this),s(e,"dragstart",this._onDragStart)),this._offMoveEvents(),this._offUpEvents(),u&&R(document.body,"user-select",""),R(z,"transform",""),t&&(dt&&(t.cancelable&&t.preventDefault(),n.dropBubble||t.stopPropagation()),U&&U.parentNode&&U.parentNode.removeChild(U),(q===G||it&&"clone"!==it.lastPutMode)&&Q&&Q.parentNode&&Q.parentNode.removeChild(Q),z&&(this.nativeDraggable&&s(z,"dragend",this),Yt(z),z.style["will-change"]="",dt&&!vt&&k(z,it?it.options.ghostClass:this.options.ghostClass,!1),k(z,this.options.chosenClass,!1),W({sortable:this,name:"unchoose",toEl:G,newIndex:null,newDraggableIndex:null,originalEvent:t}),q!==G?(0<=tt&&(W({rootEl:G,name:"add",toEl:G,fromEl:q,originalEvent:t}),W({sortable:this,name:"remove",toEl:G,originalEvent:t}),W({rootEl:G,name:"sort",toEl:G,fromEl:q,originalEvent:t}),W({sortable:this,name:"sort",toEl:G,originalEvent:t})),it&&it.save()):tt!==J&&0<=tt&&(W({sortable:this,name:"update",toEl:G,originalEvent:t}),W({sortable:this,name:"sort",toEl:G,originalEvent:t})),Rt.active&&(null!=tt&&-1!==tt||(tt=J,nt=et),W({sortable:this,name:"end",toEl:G,originalEvent:t}),this.save())))),this._nulling()},_nulling:function(){K("nulling",this),q=z=G=U=V=Q=Z=$=rt=at=dt=tt=nt=J=et=ht=ft=it=ot=Rt.dragged=Rt.ghost=Rt.clone=Rt.active=null,St.forEach(function(t){t.checked=!0}),St.length=lt=st=0},handleEvent:function(t){switch(t.type){case"drop":case"dragend":this._onDrop(t);break;case"dragenter":case"dragover":z&&(this._onDragOver(t),function(t){t.dataTransfer&&(t.dataTransfer.dropEffect="move");t.cancelable&&t.preventDefault()}(t));break;case"selectstart":t.preventDefault()}},toArray:function(){for(var t,e=[],n=this.el.children,o=0,i=n.length,r=this.options;o<i;o++)P(t=n[o],r.draggable,this.el,!1)&&e.push(t.getAttribute(r.dataIdAttr)||Ft(t));return e},sort:function(t,e){var o={},i=this.el;this.toArray().forEach(function(t,e){var n=i.children[e];P(n,this.options.draggable,i,!1)&&(o[t]=n)},this),e&&this.captureAnimationState(),t.forEach(function(t){o[t]&&(i.removeChild(o[t]),i.appendChild(o[t]))}),e&&this.animateAll()},save:function(){var t=this.options.store;t&&t.set&&t.set(this)},closest:function(t,e){return P(t,e||this.options.draggable,this.el,!1)},option:function(t,e){var n=this.options;if(void 0===e)return n[t];var o=O.modifyOption(this,t,e);n[t]=void 0!==o?o:e,"group"===t&&Nt(n)},destroy:function(){K("destroy",this);var t=this.el;t[j]=null,s(t,"mousedown",this._onTapStart),s(t,"touchstart",this._onTapStart),s(t,"pointerdown",this._onTapStart),this.nativeDraggable&&(s(t,"dragover",this),s(t,"dragenter",this)),Array.prototype.forEach.call(t.querySelectorAll("[draggable]"),function(t){t.removeAttribute("draggable")}),this._onDrop(),this._disableDelayedDragEvents(),bt.splice(bt.indexOf(this.el),1),this.el=t=null},_hideClone:function(){if(!$){if(K("hideClone",this),Rt.eventCanceled)return;R(Q,"display","none"),this.options.removeCloneOnHide&&Q.parentNode&&Q.parentNode.removeChild(Q),$=!0}},_showClone:function(t){if("clone"===t.lastPutMode){if($){if(K("showClone",this),Rt.eventCanceled)return;z.parentNode!=q||this.options.group.revertClone?V?q.insertBefore(Q,V):q.appendChild(Q):q.insertBefore(Q,z),this.options.group.revertClone&&this.animate(z,Q),R(Q,"display",""),$=!1}}else this._hideClone()}},_t&&d(document,"touchmove",function(t){(Rt.active||vt)&&t.cancelable&&t.preventDefault()}),Rt.utils={on:d,off:s,css:R,find:g,is:function(t,e){return!!P(t,e,t,!1)},extend:function(t,e){if(t&&e)for(var n in e)e.hasOwnProperty(n)&&(t[n]=e[n]);return t},throttle:D,closest:P,toggleClass:k,clone:S,index:F,nextTick:Ht,cancelNextTick:Lt,detectDirection:Ot,getChild:m},Rt.get=function(t){return t[j]},Rt.mount=function(){for(var t=arguments.length,e=new Array(t),n=0;n<t;n++)e[n]=arguments[n];e[0].constructor===Array&&(e=e[0]),e.forEach(function(t){if(!t.prototype||!t.prototype.constructor)throw"Sortable: Mounted plugin must be a constructor function, not ".concat({}.toString.call(t));t.utils&&(Rt.utils=I({},Rt.utils,t.utils)),O.mount(t)})},Rt.create=function(t,e){return new Rt(t,e)};var jt,Kt,Wt,zt,Gt,Ut,qt=[],Vt=!(Rt.version="1.13.0");function Zt(){qt.forEach(function(t){clearInterval(t.pid)}),qt=[]}function Qt(){clearInterval(Ut)}function $t(t){var e=t.originalEvent,n=t.putSortable,o=t.dragEl,i=t.activeSortable,r=t.dispatchSortableEvent,a=t.hideGhostForTarget,l=t.unhideGhostForTarget;if(e){var s=n||i;a();var c=e.changedTouches&&e.changedTouches.length?e.changedTouches[0]:e,u=document.elementFromPoint(c.clientX,c.clientY);l(),s&&!s.el.contains(u)&&(r("spill"),this.onSpill({dragEl:o,putSortable:n}))}}var Jt,te=D(function(n,t,e,o){if(t.scroll){var i,r=(n.touches?n.touches[0]:n).clientX,a=(n.touches?n.touches[0]:n).clientY,l=t.scrollSensitivity,s=t.scrollSpeed,c=A(),u=!1;Kt!==e&&(Kt=e,Zt(),jt=t.scroll,i=t.scrollFn,!0===jt&&(jt=H(e,!0)));var d=0,h=jt;do{var f=h,p=X(f),g=p.top,v=p.bottom,m=p.left,b=p.right,y=p.width,w=p.height,E=void 0,D=void 0,S=f.scrollWidth,_=f.scrollHeight,C=R(f),T=f.scrollLeft,x=f.scrollTop;D=f===c?(E=y<S&&("auto"===C.overflowX||"scroll"===C.overflowX||"visible"===C.overflowX),w<_&&("auto"===C.overflowY||"scroll"===C.overflowY||"visible"===C.overflowY)):(E=y<S&&("auto"===C.overflowX||"scroll"===C.overflowX),w<_&&("auto"===C.overflowY||"scroll"===C.overflowY));var M=E&&(Math.abs(b-r)<=l&&T+y<S)-(Math.abs(m-r)<=l&&!!T),O=D&&(Math.abs(v-a)<=l&&x+w<_)-(Math.abs(g-a)<=l&&!!x);if(!qt[d])for(var N=0;N<=d;N++)qt[N]||(qt[N]={});qt[d].vx==M&&qt[d].vy==O&&qt[d].el===f||(qt[d].el=f,qt[d].vx=M,qt[d].vy=O,clearInterval(qt[d].pid),0==M&&0==O||(u=!0,qt[d].pid=setInterval(function(){o&&0===this.layer&&Rt.active._onTouchMove(Gt);var t=qt[this.layer].vy?qt[this.layer].vy*s:0,e=qt[this.layer].vx?qt[this.layer].vx*s:0;"function"==typeof i&&"continue"!==i.call(Rt.dragged.parentNode[j],e,t,n,Gt,qt[this.layer].el)||L(qt[this.layer].el,e,t)}.bind({layer:d}),24))),d++}while(t.bubbleScroll&&h!==c&&(h=H(h,!1)));Vt=u}},30);function ee(){}function ne(){}ee.prototype={startIndex:null,dragStart:function(t){var e=t.oldDraggableIndex;this.startIndex=e},onSpill:function(t){var e=t.dragEl,n=t.putSortable;this.sortable.captureAnimationState(),n&&n.captureAnimationState();var o=m(this.sortable.el,this.startIndex,this.options);o?this.sortable.el.insertBefore(e,o):this.sortable.el.appendChild(e),this.sortable.animateAll(),n&&n.animateAll()},drop:$t},a(ee,{pluginName:"revertOnSpill"}),ne.prototype={onSpill:function(t){var e=t.dragEl,n=t.putSortable||this.sortable;n.captureAnimationState(),e.parentNode&&e.parentNode.removeChild(e),n.animateAll()},drop:$t},a(ne,{pluginName:"removeOnSpill"});var oe,ie,re,ae,le,se=[],ce=[],ue=!1,de=!1,he=!1;function fe(o,i){ce.forEach(function(t,e){var n=i.children[t.sortableIndex+(o?Number(e):0)];n?i.insertBefore(t,n):i.appendChild(t)})}function pe(){se.forEach(function(t){t!==re&&t.parentNode&&t.parentNode.removeChild(t)})}return Rt.mount(new function(){function t(){for(var t in this.defaults={scroll:!0,scrollSensitivity:30,scrollSpeed:10,bubbleScroll:!0},this)"_"===t.charAt(0)&&"function"==typeof this[t]&&(this[t]=this[t].bind(this))}return t.prototype={dragStarted:function(t){var e=t.originalEvent;this.sortable.nativeDraggable?d(document,"dragover",this._handleAutoScroll):this.options.supportPointer?d(document,"pointermove",this._handleFallbackAutoScroll):e.touches?d(document,"touchmove",this._handleFallbackAutoScroll):d(document,"mousemove",this._handleFallbackAutoScroll)},dragOverCompleted:function(t){var e=t.originalEvent;this.options.dragOverBubble||e.rootEl||this._handleAutoScroll(e)},drop:function(){this.sortable.nativeDraggable?s(document,"dragover",this._handleAutoScroll):(s(document,"pointermove",this._handleFallbackAutoScroll),s(document,"touchmove",this._handleFallbackAutoScroll),s(document,"mousemove",this._handleFallbackAutoScroll)),Qt(),Zt(),clearTimeout(f),f=void 0},nulling:function(){Gt=Kt=jt=Vt=Ut=Wt=zt=null,qt.length=0},_handleFallbackAutoScroll:function(t){this._handleAutoScroll(t,!0)},_handleAutoScroll:function(e,n){var o=this,i=(e.touches?e.touches[0]:e).clientX,r=(e.touches?e.touches[0]:e).clientY,t=document.elementFromPoint(i,r);if(Gt=e,n||E||w||u){te(e,this.options,t,n);var a=H(t,!0);!Vt||Ut&&i===Wt&&r===zt||(Ut&&Qt(),Ut=setInterval(function(){var t=H(document.elementFromPoint(i,r),!0);t!==a&&(a=t,Zt()),te(e,o.options,t,n)},10),Wt=i,zt=r)}else{if(!this.options.bubbleScroll||H(t,!0)===A())return void Zt();te(e,this.options,H(t,!1),!1)}}},a(t,{pluginName:"scroll",initializeByDefault:!0})}),Rt.mount(ne,ee),Rt.mount(new function(){function t(){this.defaults={swapClass:"sortable-swap-highlight"}}return t.prototype={dragStart:function(t){var e=t.dragEl;Jt=e},dragOverValid:function(t){var e=t.completed,n=t.target,o=t.onMove,i=t.activeSortable,r=t.changed,a=t.cancel;if(i.options.swap){var l=this.sortable.el,s=this.options;if(n&&n!==l){var c=Jt;Jt=!1!==o(n)?(k(n,s.swapClass,!0),n):null,c&&c!==Jt&&k(c,s.swapClass,!1)}r(),e(!0),a()}},drop:function(t){var e=t.activeSortable,n=t.putSortable,o=t.dragEl,i=n||this.sortable,r=this.options;Jt&&k(Jt,r.swapClass,!1),Jt&&(r.swap||n&&n.options.swap)&&o!==Jt&&(i.captureAnimationState(),i!==e&&e.captureAnimationState(),function(t,e){var n,o,i=t.parentNode,r=e.parentNode;if(!i||!r||i.isEqualNode(e)||r.isEqualNode(t))return;n=F(t),o=F(e),i.isEqualNode(r)&&n<o&&o++;i.insertBefore(e,i.children[n]),r.insertBefore(t,r.children[o])}(o,Jt),i.animateAll(),i!==e&&e.animateAll())},nulling:function(){Jt=null}},a(t,{pluginName:"swap",eventProperties:function(){return{swapItem:Jt}}})}),Rt.mount(new function(){function t(o){for(var t in this)"_"===t.charAt(0)&&"function"==typeof this[t]&&(this[t]=this[t].bind(this));o.options.supportPointer?d(document,"pointerup",this._deselectMultiDrag):(d(document,"mouseup",this._deselectMultiDrag),d(document,"touchend",this._deselectMultiDrag)),d(document,"keydown",this._checkKeyDown),d(document,"keyup",this._checkKeyUp),this.defaults={selectedClass:"sortable-selected",multiDragKey:null,setData:function(t,e){var n="";se.length&&ie===o?se.forEach(function(t,e){n+=(e?", ":"")+t.textContent}):n=e.textContent,t.setData("Text",n)}}}return t.prototype={multiDragKeyDown:!1,isMultiDrag:!1,delayStartGlobal:function(t){var e=t.dragEl;re=e},delayEnded:function(){this.isMultiDrag=~se.indexOf(re)},setupClone:function(t){var e=t.sortable,n=t.cancel;if(this.isMultiDrag){for(var o=0;o<se.length;o++)ce.push(S(se[o])),ce[o].sortableIndex=se[o].sortableIndex,ce[o].draggable=!1,ce[o].style["will-change"]="",k(ce[o],this.options.selectedClass,!1),se[o]===re&&k(ce[o],this.options.chosenClass,!1);e._hideClone(),n()}},clone:function(t){var e=t.sortable,n=t.rootEl,o=t.dispatchSortableEvent,i=t.cancel;this.isMultiDrag&&(this.options.removeCloneOnHide||se.length&&ie===e&&(fe(!0,n),o("clone"),i()))},showClone:function(t){var e=t.cloneNowShown,n=t.rootEl,o=t.cancel;this.isMultiDrag&&(fe(!1,n),ce.forEach(function(t){R(t,"display","")}),e(),le=!1,o())},hideClone:function(t){var e=this,n=(t.sortable,t.cloneNowHidden),o=t.cancel;this.isMultiDrag&&(ce.forEach(function(t){R(t,"display","none"),e.options.removeCloneOnHide&&t.parentNode&&t.parentNode.removeChild(t)}),n(),le=!0,o())},dragStartGlobal:function(t){t.sortable;!this.isMultiDrag&&ie&&ie.multiDrag._deselectMultiDrag(),se.forEach(function(t){t.sortableIndex=F(t)}),se=se.sort(function(t,e){return t.sortableIndex-e.sortableIndex}),he=!0},dragStarted:function(t){var e=this,n=t.sortable;if(this.isMultiDrag){if(this.options.sort&&(n.captureAnimationState(),this.options.animation)){se.forEach(function(t){t!==re&&R(t,"position","absolute")});var o=X(re,!1,!0,!0);se.forEach(function(t){t!==re&&_(t,o)}),ue=de=!0}n.animateAll(function(){ue=de=!1,e.options.animation&&se.forEach(function(t){C(t)}),e.options.sort&&pe()})}},dragOver:function(t){var e=t.target,n=t.completed,o=t.cancel;de&&~se.indexOf(e)&&(n(!1),o())},revert:function(t){var e=t.fromSortable,n=t.rootEl,o=t.sortable,i=t.dragRect;1<se.length&&(se.forEach(function(t){o.addAnimationState({target:t,rect:de?X(t):i}),C(t),t.fromRect=i,e.removeAnimationState(t)}),de=!1,function(o,i){se.forEach(function(t,e){var n=i.children[t.sortableIndex+(o?Number(e):0)];n?i.insertBefore(t,n):i.appendChild(t)})}(!this.options.removeCloneOnHide,n))},dragOverCompleted:function(t){var e=t.sortable,n=t.isOwner,o=t.insertion,i=t.activeSortable,r=t.parentEl,a=t.putSortable,l=this.options;if(o){if(n&&i._hideClone(),ue=!1,l.animation&&1<se.length&&(de||!n&&!i.options.sort&&!a)){var s=X(re,!1,!0,!0);se.forEach(function(t){t!==re&&(_(t,s),r.appendChild(t))}),de=!0}if(!n)if(de||pe(),1<se.length){var c=le;i._showClone(e),i.options.animation&&!le&&c&&ce.forEach(function(t){i.addAnimationState({target:t,rect:ae}),t.fromRect=ae,t.thisAnimationDuration=null})}else i._showClone(e)}},dragOverAnimationCapture:function(t){var e=t.dragRect,n=t.isOwner,o=t.activeSortable;if(se.forEach(function(t){t.thisAnimationDuration=null}),o.options.animation&&!n&&o.multiDrag.isMultiDrag){ae=a({},e);var i=v(re,!0);ae.top-=i.f,ae.left-=i.e}},dragOverAnimationComplete:function(){de&&(de=!1,pe())},drop:function(t){var e=t.originalEvent,n=t.rootEl,o=t.parentEl,i=t.sortable,r=t.dispatchSortableEvent,a=t.oldIndex,l=t.putSortable,s=l||this.sortable;if(e){var c=this.options,u=o.children;if(!he)if(c.multiDragKey&&!this.multiDragKeyDown&&this._deselectMultiDrag(),k(re,c.selectedClass,!~se.indexOf(re)),~se.indexOf(re))se.splice(se.indexOf(re),1),oe=null,N({sortable:i,rootEl:n,name:"deselect",targetEl:re,originalEvt:e});else{if(se.push(re),N({sortable:i,rootEl:n,name:"select",targetEl:re,originalEvt:e}),e.shiftKey&&oe&&i.el.contains(oe)){var d,h,f=F(oe),p=F(re);if(~f&&~p&&f!==p)for(d=f<p?(h=f,p):(h=p,f+1);h<d;h++)~se.indexOf(u[h])||(k(u[h],c.selectedClass,!0),se.push(u[h]),N({sortable:i,rootEl:n,name:"select",targetEl:u[h],originalEvt:e}))}else oe=re;ie=s}if(he&&this.isMultiDrag){if((o[j].options.sort||o!==n)&&1<se.length){var g=X(re),v=F(re,":not(."+this.options.selectedClass+")");if(!ue&&c.animation&&(re.thisAnimationDuration=null),s.captureAnimationState(),!ue&&(c.animation&&(re.fromRect=g,se.forEach(function(t){if(t.thisAnimationDuration=null,t!==re){var e=de?X(t):g;t.fromRect=e,s.addAnimationState({target:t,rect:e})}})),pe(),se.forEach(function(t){u[v]?o.insertBefore(t,u[v]):o.appendChild(t),v++}),a===F(re))){var m=!1;se.forEach(function(t){t.sortableIndex===F(t)||(m=!0)}),m&&r("update")}se.forEach(function(t){C(t)}),s.animateAll()}ie=s}(n===o||l&&"clone"!==l.lastPutMode)&&ce.forEach(function(t){t.parentNode&&t.parentNode.removeChild(t)})}},nullingGlobal:function(){this.isMultiDrag=he=!1,ce.length=0},destroyGlobal:function(){this._deselectMultiDrag(),s(document,"pointerup",this._deselectMultiDrag),s(document,"mouseup",this._deselectMultiDrag),s(document,"touchend",this._deselectMultiDrag),s(document,"keydown",this._checkKeyDown),s(document,"keyup",this._checkKeyUp)},_deselectMultiDrag:function(t){if(!(void 0!==he&&he||ie!==this.sortable||t&&P(t.target,this.options.draggable,this.sortable.el,!1)||t&&0!==t.button))for(;se.length;){var e=se[0];k(e,this.options.selectedClass,!1),se.shift(),N({sortable:this.sortable,rootEl:this.sortable.el,name:"deselect",targetEl:e,originalEvt:t})}},_checkKeyDown:function(t){t.key===this.options.multiDragKey&&(this.multiDragKeyDown=!0)},_checkKeyUp:function(t){t.key===this.options.multiDragKey&&(this.multiDragKeyDown=!1)}},a(t,{pluginName:"multiDrag",utils:{select:function(t){var e=t.parentNode[j];e&&e.options.multiDrag&&!~se.indexOf(t)&&(ie&&ie!==e&&(ie.multiDrag._deselectMultiDrag(),ie=e),k(t,e.options.selectedClass,!0),se.push(t))},deselect:function(t){var e=t.parentNode[j],n=se.indexOf(t);e&&e.options.multiDrag&&~n&&(k(t,e.options.selectedClass,!1),se.splice(n,1))}},eventProperties:function(){var n=this,o=[],i=[];return se.forEach(function(t){var e;o.push({multiDragElement:t,index:t.sortableIndex}),e=de&&t!==re?-1:de?F(t,":not(."+n.options.selectedClass+")"):F(t),i.push({multiDragElement:t,index:e})}),{items:e(se),clones:[].concat(ce),oldIndicies:o,newIndicies:i}},optionListeners:{multiDragKey:function(t){return"ctrl"===(t=t.toLowerCase())?t="Control":1<t.length&&(t=t.charAt(0).toUpperCase()+t.substr(1)),t}}})}),Rt});
diff --git a/asset/js/vendor/flatpickr.js b/asset/js/vendor/flatpickr.js
new file mode 100644
index 0000000..bb21f88
--- /dev/null
+++ b/asset/js/vendor/flatpickr.js
@@ -0,0 +1,2705 @@
+/* flatpickr v4.6.9, @license MIT */
+(function (global, factory) {
+ typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
+ typeof define === 'function' && define.icinga ? define(factory) :
+ (global = typeof globalThis !== 'undefined' ? globalThis : global || self, global.flatpickr = factory());
+}(this, (function () { 'use strict';
+
+ /*! *****************************************************************************
+ Copyright (c) Microsoft Corporation.
+
+ Permission to use, copy, modify, and/or distribute this software for any
+ purpose with or without fee is hereby granted.
+
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
+ REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
+ INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
+ OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ PERFORMANCE OF THIS SOFTWARE.
+ ***************************************************************************** */
+
+ var __assign = function() {
+ __assign = Object.assign || function __assign(t) {
+ for (var s, i = 1, n = arguments.length; i < n; i++) {
+ s = arguments[i];
+ for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p];
+ }
+ return t;
+ };
+ return __assign.apply(this, arguments);
+ };
+
+ function __spreadArrays() {
+ for (var s = 0, i = 0, il = arguments.length; i < il; i++) s += arguments[i].length;
+ for (var r = Array(s), k = 0, i = 0; i < il; i++)
+ for (var a = arguments[i], j = 0, jl = a.length; j < jl; j++, k++)
+ r[k] = a[j];
+ return r;
+ }
+
+ var HOOKS = [
+ "onChange",
+ "onClose",
+ "onDayCreate",
+ "onDestroy",
+ "onKeyDown",
+ "onMonthChange",
+ "onOpen",
+ "onParseConfig",
+ "onReady",
+ "onValueUpdate",
+ "onYearChange",
+ "onPreCalendarPosition",
+ ];
+ var defaults = {
+ _disable: [],
+ allowInput: false,
+ allowInvalidPreload: false,
+ altFormat: "F j, Y",
+ altInput: false,
+ altInputClass: "form-control input",
+ animate: typeof window === "object" &&
+ window.navigator.userAgent.indexOf("MSIE") === -1,
+ ariaDateFormat: "F j, Y",
+ autoFillDefaultTime: true,
+ clickOpens: true,
+ closeOnSelect: true,
+ conjunction: ", ",
+ dateFormat: "Y-m-d",
+ defaultHour: 12,
+ defaultMinute: 0,
+ defaultSeconds: 0,
+ disable: [],
+ disableMobile: false,
+ enableSeconds: false,
+ enableTime: false,
+ errorHandler: function (err) {
+ return typeof console !== "undefined" && console.warn(err);
+ },
+ getWeek: function (givenDate) {
+ var date = new Date(givenDate.getTime());
+ date.setHours(0, 0, 0, 0);
+ // Thursday in current week decides the year.
+ date.setDate(date.getDate() + 3 - ((date.getDay() + 6) % 7));
+ // January 4 is always in week 1.
+ var week1 = new Date(date.getFullYear(), 0, 4);
+ // Adjust to Thursday in week 1 and count number of weeks from date to week1.
+ return (1 +
+ Math.round(((date.getTime() - week1.getTime()) / 86400000 -
+ 3 +
+ ((week1.getDay() + 6) % 7)) /
+ 7));
+ },
+ hourIncrement: 1,
+ ignoredFocusElements: [],
+ inline: false,
+ locale: "default",
+ minuteIncrement: 5,
+ mode: "single",
+ monthSelectorType: "dropdown",
+ nextArrow: "<svg version='1.1' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink' viewBox='0 0 17 17'><g></g><path d='M13.207 8.472l-7.854 7.854-0.707-0.707 7.146-7.146-7.146-7.148 0.707-0.707 7.854 7.854z' /></svg>",
+ noCalendar: false,
+ now: new Date(),
+ onChange: [],
+ onClose: [],
+ onDayCreate: [],
+ onDestroy: [],
+ onKeyDown: [],
+ onMonthChange: [],
+ onOpen: [],
+ onParseConfig: [],
+ onReady: [],
+ onValueUpdate: [],
+ onYearChange: [],
+ onPreCalendarPosition: [],
+ plugins: [],
+ position: "auto",
+ positionElement: undefined,
+ prevArrow: "<svg version='1.1' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink' viewBox='0 0 17 17'><g></g><path d='M5.207 8.471l7.146 7.147-0.707 0.707-7.853-7.854 7.854-7.853 0.707 0.707-7.147 7.146z' /></svg>",
+ shorthandCurrentMonth: false,
+ showMonths: 1,
+ static: false,
+ time_24hr: false,
+ weekNumbers: false,
+ wrap: false,
+ };
+
+ var english = {
+ weekdays: {
+ shorthand: ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"],
+ longhand: [
+ "Sunday",
+ "Monday",
+ "Tuesday",
+ "Wednesday",
+ "Thursday",
+ "Friday",
+ "Saturday",
+ ],
+ },
+ months: {
+ shorthand: [
+ "Jan",
+ "Feb",
+ "Mar",
+ "Apr",
+ "May",
+ "Jun",
+ "Jul",
+ "Aug",
+ "Sep",
+ "Oct",
+ "Nov",
+ "Dec",
+ ],
+ longhand: [
+ "January",
+ "February",
+ "March",
+ "April",
+ "May",
+ "June",
+ "July",
+ "August",
+ "September",
+ "October",
+ "November",
+ "December",
+ ],
+ },
+ daysInMonth: [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31],
+ firstDayOfWeek: 0,
+ ordinal: function (nth) {
+ var s = nth % 100;
+ if (s > 3 && s < 21)
+ return "th";
+ switch (s % 10) {
+ case 1:
+ return "st";
+ case 2:
+ return "nd";
+ case 3:
+ return "rd";
+ default:
+ return "th";
+ }
+ },
+ rangeSeparator: " to ",
+ weekAbbreviation: "Wk",
+ scrollTitle: "Scroll to increment",
+ toggleTitle: "Click to toggle",
+ amPM: ["AM", "PM"],
+ yearAriaLabel: "Year",
+ monthAriaLabel: "Month",
+ hourAriaLabel: "Hour",
+ minuteAriaLabel: "Minute",
+ time_24hr: false,
+ };
+
+ var pad = function (number, length) {
+ if (length === void 0) { length = 2; }
+ return ("000" + number).slice(length * -1);
+ };
+ var int = function (bool) { return (bool === true ? 1 : 0); };
+ /* istanbul ignore next */
+ function debounce(fn, wait) {
+ var t;
+ return function () {
+ var _this = this;
+ var args = arguments;
+ clearTimeout(t);
+ t = setTimeout(function () { return fn.apply(_this, args); }, wait);
+ };
+ }
+ var arrayify = function (obj) {
+ return obj instanceof Array ? obj : [obj];
+ };
+
+ function toggleClass(elem, className, bool) {
+ if (bool === true)
+ return elem.classList.add(className);
+ elem.classList.remove(className);
+ }
+ function createElement(tag, className, content) {
+ var e = window.document.createElement(tag);
+ className = className || "";
+ content = content || "";
+ e.className = className;
+ if (content !== undefined)
+ e.textContent = content;
+ return e;
+ }
+ function clearNode(node) {
+ while (node.firstChild)
+ node.removeChild(node.firstChild);
+ }
+ function findParent(node, condition) {
+ if (condition(node))
+ return node;
+ else if (node.parentNode)
+ return findParent(node.parentNode, condition);
+ return undefined; // nothing found
+ }
+ function createNumberInput(inputClassName, opts) {
+ var wrapper = createElement("div", "numInputWrapper"), numInput = createElement("input", "numInput " + inputClassName), arrowUp = createElement("span", "arrowUp"), arrowDown = createElement("span", "arrowDown");
+ if (navigator.userAgent.indexOf("MSIE 9.0") === -1) {
+ numInput.type = "number";
+ }
+ else {
+ numInput.type = "text";
+ numInput.pattern = "\\d*";
+ }
+ if (opts !== undefined)
+ for (var key in opts)
+ numInput.setAttribute(key, opts[key]);
+ wrapper.appendChild(numInput);
+ wrapper.appendChild(arrowUp);
+ wrapper.appendChild(arrowDown);
+ return wrapper;
+ }
+ function getEventTarget(event) {
+ try {
+ if (typeof event.composedPath === "function") {
+ var path = event.composedPath();
+ return path[0];
+ }
+ return event.target;
+ }
+ catch (error) {
+ return event.target;
+ }
+ }
+
+ var doNothing = function () { return undefined; };
+ var monthToStr = function (monthNumber, shorthand, locale) { return locale.months[shorthand ? "shorthand" : "longhand"][monthNumber]; };
+ var revFormat = {
+ D: doNothing,
+ F: function (dateObj, monthName, locale) {
+ dateObj.setMonth(locale.months.longhand.indexOf(monthName));
+ },
+ G: function (dateObj, hour) {
+ dateObj.setHours(parseFloat(hour));
+ },
+ H: function (dateObj, hour) {
+ dateObj.setHours(parseFloat(hour));
+ },
+ J: function (dateObj, day) {
+ dateObj.setDate(parseFloat(day));
+ },
+ K: function (dateObj, amPM, locale) {
+ dateObj.setHours((dateObj.getHours() % 12) +
+ 12 * int(new RegExp(locale.amPM[1], "i").test(amPM)));
+ },
+ M: function (dateObj, shortMonth, locale) {
+ dateObj.setMonth(locale.months.shorthand.indexOf(shortMonth));
+ },
+ S: function (dateObj, seconds) {
+ dateObj.setSeconds(parseFloat(seconds));
+ },
+ U: function (_, unixSeconds) { return new Date(parseFloat(unixSeconds) * 1000); },
+ W: function (dateObj, weekNum, locale) {
+ var weekNumber = parseInt(weekNum);
+ var date = new Date(dateObj.getFullYear(), 0, 2 + (weekNumber - 1) * 7, 0, 0, 0, 0);
+ date.setDate(date.getDate() - date.getDay() + locale.firstDayOfWeek);
+ return date;
+ },
+ Y: function (dateObj, year) {
+ dateObj.setFullYear(parseFloat(year));
+ },
+ Z: function (_, ISODate) { return new Date(ISODate); },
+ d: function (dateObj, day) {
+ dateObj.setDate(parseFloat(day));
+ },
+ h: function (dateObj, hour) {
+ dateObj.setHours(parseFloat(hour));
+ },
+ i: function (dateObj, minutes) {
+ dateObj.setMinutes(parseFloat(minutes));
+ },
+ j: function (dateObj, day) {
+ dateObj.setDate(parseFloat(day));
+ },
+ l: doNothing,
+ m: function (dateObj, month) {
+ dateObj.setMonth(parseFloat(month) - 1);
+ },
+ n: function (dateObj, month) {
+ dateObj.setMonth(parseFloat(month) - 1);
+ },
+ s: function (dateObj, seconds) {
+ dateObj.setSeconds(parseFloat(seconds));
+ },
+ u: function (_, unixMillSeconds) {
+ return new Date(parseFloat(unixMillSeconds));
+ },
+ w: doNothing,
+ y: function (dateObj, year) {
+ dateObj.setFullYear(2000 + parseFloat(year));
+ },
+ };
+ var tokenRegex = {
+ D: "(\\w+)",
+ F: "(\\w+)",
+ G: "(\\d\\d|\\d)",
+ H: "(\\d\\d|\\d)",
+ J: "(\\d\\d|\\d)\\w+",
+ K: "",
+ M: "(\\w+)",
+ S: "(\\d\\d|\\d)",
+ U: "(.+)",
+ W: "(\\d\\d|\\d)",
+ Y: "(\\d{4})",
+ Z: "(.+)",
+ d: "(\\d\\d|\\d)",
+ h: "(\\d\\d|\\d)",
+ i: "(\\d\\d|\\d)",
+ j: "(\\d\\d|\\d)",
+ l: "(\\w+)",
+ m: "(\\d\\d|\\d)",
+ n: "(\\d\\d|\\d)",
+ s: "(\\d\\d|\\d)",
+ u: "(.+)",
+ w: "(\\d\\d|\\d)",
+ y: "(\\d{2})",
+ };
+ var formats = {
+ // get the date in UTC
+ Z: function (date) { return date.toISOString(); },
+ // weekday name, short, e.g. Thu
+ D: function (date, locale, options) {
+ return locale.weekdays.shorthand[formats.w(date, locale, options)];
+ },
+ // full month name e.g. January
+ F: function (date, locale, options) {
+ return monthToStr(formats.n(date, locale, options) - 1, false, locale);
+ },
+ // padded hour 1-12
+ G: function (date, locale, options) {
+ return pad(formats.h(date, locale, options));
+ },
+ // hours with leading zero e.g. 03
+ H: function (date) { return pad(date.getHours()); },
+ // day (1-30) with ordinal suffix e.g. 1st, 2nd
+ J: function (date, locale) {
+ return locale.ordinal !== undefined
+ ? date.getDate() + locale.ordinal(date.getDate())
+ : date.getDate();
+ },
+ // AM/PM
+ K: function (date, locale) { return locale.amPM[int(date.getHours() > 11)]; },
+ // shorthand month e.g. Jan, Sep, Oct, etc
+ M: function (date, locale) {
+ return monthToStr(date.getMonth(), true, locale);
+ },
+ // seconds 00-59
+ S: function (date) { return pad(date.getSeconds()); },
+ // unix timestamp
+ U: function (date) { return date.getTime() / 1000; },
+ W: function (date, _, options) {
+ return options.getWeek(date);
+ },
+ // full year e.g. 2016, padded (0001-9999)
+ Y: function (date) { return pad(date.getFullYear(), 4); },
+ // day in month, padded (01-30)
+ d: function (date) { return pad(date.getDate()); },
+ // hour from 1-12 (am/pm)
+ h: function (date) { return (date.getHours() % 12 ? date.getHours() % 12 : 12); },
+ // minutes, padded with leading zero e.g. 09
+ i: function (date) { return pad(date.getMinutes()); },
+ // day in month (1-30)
+ j: function (date) { return date.getDate(); },
+ // weekday name, full, e.g. Thursday
+ l: function (date, locale) {
+ return locale.weekdays.longhand[date.getDay()];
+ },
+ // padded month number (01-12)
+ m: function (date) { return pad(date.getMonth() + 1); },
+ // the month number (1-12)
+ n: function (date) { return date.getMonth() + 1; },
+ // seconds 0-59
+ s: function (date) { return date.getSeconds(); },
+ // Unix Milliseconds
+ u: function (date) { return date.getTime(); },
+ // number of the day of the week
+ w: function (date) { return date.getDay(); },
+ // last two digits of year e.g. 16 for 2016
+ y: function (date) { return String(date.getFullYear()).substring(2); },
+ };
+
+ var createDateFormatter = function (_a) {
+ var _b = _a.config, config = _b === void 0 ? defaults : _b, _c = _a.l10n, l10n = _c === void 0 ? english : _c, _d = _a.isMobile, isMobile = _d === void 0 ? false : _d;
+ return function (dateObj, frmt, overrideLocale) {
+ var locale = overrideLocale || l10n;
+ if (config.formatDate !== undefined && !isMobile) {
+ return config.formatDate(dateObj, frmt, locale);
+ }
+ return frmt
+ .split("")
+ .map(function (c, i, arr) {
+ return formats[c] && arr[i - 1] !== "\\"
+ ? formats[c](dateObj, locale, config)
+ : c !== "\\"
+ ? c
+ : "";
+ })
+ .join("");
+ };
+ };
+ var createDateParser = function (_a) {
+ var _b = _a.config, config = _b === void 0 ? defaults : _b, _c = _a.l10n, l10n = _c === void 0 ? english : _c;
+ return function (date, givenFormat, timeless, customLocale) {
+ if (date !== 0 && !date)
+ return undefined;
+ var locale = customLocale || l10n;
+ var parsedDate;
+ var dateOrig = date;
+ if (date instanceof Date)
+ parsedDate = new Date(date.getTime());
+ else if (typeof date !== "string" &&
+ date.toFixed !== undefined // timestamp
+ )
+ // create a copy
+ parsedDate = new Date(date);
+ else if (typeof date === "string") {
+ // date string
+ var format = givenFormat || (config || defaults).dateFormat;
+ var datestr = String(date).trim();
+ if (datestr === "today") {
+ parsedDate = new Date();
+ timeless = true;
+ }
+ else if (config && config.parseDate) {
+ parsedDate = config.parseDate(date, format);
+ }
+ else if (/Z$/.test(datestr) ||
+ /GMT$/.test(datestr) // datestrings w/ timezone
+ ) {
+ parsedDate = new Date(date);
+ }
+ else {
+ var matched = void 0, ops = [];
+ for (var i = 0, matchIndex = 0, regexStr = ""; i < format.length; i++) {
+ var token_1 = format[i];
+ var isBackSlash = token_1 === "\\";
+ var escaped = format[i - 1] === "\\" || isBackSlash;
+ if (tokenRegex[token_1] && !escaped) {
+ regexStr += tokenRegex[token_1];
+ var match = new RegExp(regexStr).exec(date);
+ if (match && (matched = true)) {
+ ops[token_1 !== "Y" ? "push" : "unshift"]({
+ fn: revFormat[token_1],
+ val: match[++matchIndex],
+ });
+ }
+ }
+ else if (!isBackSlash)
+ regexStr += "."; // don't really care
+ }
+ parsedDate =
+ !config || !config.noCalendar
+ ? new Date(new Date().getFullYear(), 0, 1, 0, 0, 0, 0)
+ : new Date(new Date().setHours(0, 0, 0, 0));
+ ops.forEach(function (_a) {
+ var fn = _a.fn, val = _a.val;
+ return (parsedDate = fn(parsedDate, val, locale) || parsedDate);
+ });
+ parsedDate = matched ? parsedDate : undefined;
+ }
+ }
+ /* istanbul ignore next */
+ if (!(parsedDate instanceof Date && !isNaN(parsedDate.getTime()))) {
+ config.errorHandler(new Error("Invalid date provided: " + dateOrig));
+ return undefined;
+ }
+ if (timeless === true)
+ parsedDate.setHours(0, 0, 0, 0);
+ return parsedDate;
+ };
+ };
+ /**
+ * Compute the difference in dates, measured in ms
+ */
+ function compareDates(date1, date2, timeless) {
+ if (timeless === void 0) { timeless = true; }
+ if (timeless !== false) {
+ return (new Date(date1.getTime()).setHours(0, 0, 0, 0) -
+ new Date(date2.getTime()).setHours(0, 0, 0, 0));
+ }
+ return date1.getTime() - date2.getTime();
+ }
+ var isBetween = function (ts, ts1, ts2) {
+ return ts > Math.min(ts1, ts2) && ts < Math.max(ts1, ts2);
+ };
+ var calculateSecondsSinceMidnight = function (hours, minutes, seconds) {
+ return hours * 3600 + minutes * 60 + seconds;
+ };
+ var parseSeconds = function (secondsSinceMidnight) {
+ var hours = Math.floor(secondsSinceMidnight / 3600), minutes = (secondsSinceMidnight - hours * 3600) / 60;
+ return [hours, minutes, secondsSinceMidnight - hours * 3600 - minutes * 60];
+ };
+ var duration = {
+ DAY: 86400000,
+ };
+ function getDefaultHours(config) {
+ var hours = config.defaultHour;
+ var minutes = config.defaultMinute;
+ var seconds = config.defaultSeconds;
+ if (config.minDate !== undefined) {
+ var minHour = config.minDate.getHours();
+ var minMinutes = config.minDate.getMinutes();
+ var minSeconds = config.minDate.getSeconds();
+ if (hours < minHour) {
+ hours = minHour;
+ }
+ if (hours === minHour && minutes < minMinutes) {
+ minutes = minMinutes;
+ }
+ if (hours === minHour && minutes === minMinutes && seconds < minSeconds)
+ seconds = config.minDate.getSeconds();
+ }
+ if (config.maxDate !== undefined) {
+ var maxHr = config.maxDate.getHours();
+ var maxMinutes = config.maxDate.getMinutes();
+ hours = Math.min(hours, maxHr);
+ if (hours === maxHr)
+ minutes = Math.min(maxMinutes, minutes);
+ if (hours === maxHr && minutes === maxMinutes)
+ seconds = config.maxDate.getSeconds();
+ }
+ return { hours: hours, minutes: minutes, seconds: seconds };
+ }
+
+ if (typeof Object.assign !== "function") {
+ Object.assign = function (target) {
+ var args = [];
+ for (var _i = 1; _i < arguments.length; _i++) {
+ args[_i - 1] = arguments[_i];
+ }
+ if (!target) {
+ throw TypeError("Cannot convert undefined or null to object");
+ }
+ var _loop_1 = function (source) {
+ if (source) {
+ Object.keys(source).forEach(function (key) { return (target[key] = source[key]); });
+ }
+ };
+ for (var _a = 0, args_1 = args; _a < args_1.length; _a++) {
+ var source = args_1[_a];
+ _loop_1(source);
+ }
+ return target;
+ };
+ }
+
+ var DEBOUNCED_CHANGE_MS = 300;
+ function FlatpickrInstance(element, instanceConfig) {
+ var self = {
+ config: __assign(__assign({}, defaults), flatpickr.defaultConfig),
+ l10n: english,
+ };
+ self.parseDate = createDateParser({ config: self.config, l10n: self.l10n });
+ self._handlers = [];
+ self.pluginElements = [];
+ self.loadedPlugins = [];
+ self._bind = bind;
+ self._setHoursFromDate = setHoursFromDate;
+ self._positionCalendar = positionCalendar;
+ self.changeMonth = changeMonth;
+ self.changeYear = changeYear;
+ self.clear = clear;
+ self.close = close;
+ self._createElement = createElement;
+ self.destroy = destroy;
+ self.isEnabled = isEnabled;
+ self.jumpToDate = jumpToDate;
+ self.open = open;
+ self.redraw = redraw;
+ self.set = set;
+ self.setDate = setDate;
+ self.toggle = toggle;
+ function setupHelperFunctions() {
+ self.utils = {
+ getDaysInMonth: function (month, yr) {
+ if (month === void 0) { month = self.currentMonth; }
+ if (yr === void 0) { yr = self.currentYear; }
+ if (month === 1 && ((yr % 4 === 0 && yr % 100 !== 0) || yr % 400 === 0))
+ return 29;
+ return self.l10n.daysInMonth[month];
+ },
+ };
+ }
+ function init() {
+ self.element = self.input = element;
+ self.isOpen = false;
+ parseConfig();
+ setupLocale();
+ setupInputs();
+ setupDates();
+ setupHelperFunctions();
+ if (!self.isMobile)
+ build();
+ bindEvents();
+ if (self.selectedDates.length || self.config.noCalendar) {
+ if (self.config.enableTime) {
+ setHoursFromDate(self.config.noCalendar ? self.latestSelectedDateObj : undefined);
+ }
+ updateValue(false);
+ }
+ setCalendarWidth();
+ var isSafari = /^((?!chrome|android).)*safari/i.test(navigator.userAgent);
+ /* TODO: investigate this further
+
+ Currently, there is weird positioning behavior in safari causing pages
+ to scroll up. https://github.com/chmln/flatpickr/issues/563
+
+ However, most browsers are not Safari and positioning is expensive when used
+ in scale. https://github.com/chmln/flatpickr/issues/1096
+ */
+ if (!self.isMobile && isSafari) {
+ positionCalendar();
+ }
+ triggerEvent("onReady");
+ }
+ function bindToInstance(fn) {
+ return fn.bind(self);
+ }
+ function setCalendarWidth() {
+ var config = self.config;
+ if (config.weekNumbers === false && config.showMonths === 1) {
+ return;
+ }
+ else if (config.noCalendar !== true) {
+ window.requestAnimationFrame(function () {
+ if (self.calendarContainer !== undefined) {
+ self.calendarContainer.style.visibility = "hidden";
+ self.calendarContainer.style.display = "block";
+ }
+ if (self.daysContainer !== undefined) {
+ var daysWidth = (self.days.offsetWidth + 1) * config.showMonths;
+ self.daysContainer.style.width = daysWidth + "px";
+ self.calendarContainer.style.width =
+ daysWidth +
+ (self.weekWrapper !== undefined
+ ? self.weekWrapper.offsetWidth
+ : 0) +
+ "px";
+ self.calendarContainer.style.removeProperty("visibility");
+ self.calendarContainer.style.removeProperty("display");
+ }
+ });
+ }
+ }
+ /**
+ * The handler for all events targeting the time inputs
+ */
+ function updateTime(e) {
+ if (self.selectedDates.length === 0) {
+ var defaultDate = self.config.minDate === undefined ||
+ compareDates(new Date(), self.config.minDate) >= 0
+ ? new Date()
+ : new Date(self.config.minDate.getTime());
+ var defaults = getDefaultHours(self.config);
+ defaultDate.setHours(defaults.hours, defaults.minutes, defaults.seconds, defaultDate.getMilliseconds());
+ self.selectedDates = [defaultDate];
+ self.latestSelectedDateObj = defaultDate;
+ }
+ if (e !== undefined && e.type !== "blur") {
+ timeWrapper(e);
+ }
+ var prevValue = self._input.value;
+ setHoursFromInputs();
+ updateValue();
+ if (self._input.value !== prevValue) {
+ self._debouncedChange();
+ }
+ }
+ function ampm2military(hour, amPM) {
+ return (hour % 12) + 12 * int(amPM === self.l10n.amPM[1]);
+ }
+ function military2ampm(hour) {
+ switch (hour % 24) {
+ case 0:
+ case 12:
+ return 12;
+ default:
+ return hour % 12;
+ }
+ }
+ /**
+ * Syncs the selected date object time with user's time input
+ */
+ function setHoursFromInputs() {
+ if (self.hourElement === undefined || self.minuteElement === undefined)
+ return;
+ var hours = (parseInt(self.hourElement.value.slice(-2), 10) || 0) % 24, minutes = (parseInt(self.minuteElement.value, 10) || 0) % 60, seconds = self.secondElement !== undefined
+ ? (parseInt(self.secondElement.value, 10) || 0) % 60
+ : 0;
+ if (self.amPM !== undefined) {
+ hours = ampm2military(hours, self.amPM.textContent);
+ }
+ var limitMinHours = self.config.minTime !== undefined ||
+ (self.config.minDate &&
+ self.minDateHasTime &&
+ self.latestSelectedDateObj &&
+ compareDates(self.latestSelectedDateObj, self.config.minDate, true) ===
+ 0);
+ var limitMaxHours = self.config.maxTime !== undefined ||
+ (self.config.maxDate &&
+ self.maxDateHasTime &&
+ self.latestSelectedDateObj &&
+ compareDates(self.latestSelectedDateObj, self.config.maxDate, true) ===
+ 0);
+ if (self.config.maxTime !== undefined &&
+ self.config.minTime !== undefined &&
+ self.config.minTime > self.config.maxTime) {
+ var minBound = calculateSecondsSinceMidnight(self.config.minTime.getHours(), self.config.minTime.getMinutes(), self.config.minTime.getSeconds());
+ var maxBound = calculateSecondsSinceMidnight(self.config.maxTime.getHours(), self.config.maxTime.getMinutes(), self.config.maxTime.getSeconds());
+ var currentTime = calculateSecondsSinceMidnight(hours, minutes, seconds);
+ if (currentTime > maxBound && currentTime < minBound) {
+ var result = parseSeconds(minBound);
+ hours = result[0];
+ minutes = result[1];
+ seconds = result[2];
+ }
+ }
+ else {
+ if (limitMaxHours) {
+ var maxTime = self.config.maxTime !== undefined
+ ? self.config.maxTime
+ : self.config.maxDate;
+ hours = Math.min(hours, maxTime.getHours());
+ if (hours === maxTime.getHours())
+ minutes = Math.min(minutes, maxTime.getMinutes());
+ if (minutes === maxTime.getMinutes())
+ seconds = Math.min(seconds, maxTime.getSeconds());
+ }
+ if (limitMinHours) {
+ var minTime = self.config.minTime !== undefined
+ ? self.config.minTime
+ : self.config.minDate;
+ hours = Math.max(hours, minTime.getHours());
+ if (hours === minTime.getHours() && minutes < minTime.getMinutes())
+ minutes = minTime.getMinutes();
+ if (minutes === minTime.getMinutes())
+ seconds = Math.max(seconds, minTime.getSeconds());
+ }
+ }
+ setHours(hours, minutes, seconds);
+ }
+ /**
+ * Syncs time input values with a date
+ */
+ function setHoursFromDate(dateObj) {
+ var date = dateObj || self.latestSelectedDateObj;
+ if (date) {
+ setHours(date.getHours(), date.getMinutes(), date.getSeconds());
+ }
+ }
+ /**
+ * Sets the hours, minutes, and optionally seconds
+ * of the latest selected date object and the
+ * corresponding time inputs
+ * @param {Number} hours the hour. whether its military
+ * or am-pm gets inferred from config
+ * @param {Number} minutes the minutes
+ * @param {Number} seconds the seconds (optional)
+ */
+ function setHours(hours, minutes, seconds) {
+ if (self.latestSelectedDateObj !== undefined) {
+ self.latestSelectedDateObj.setHours(hours % 24, minutes, seconds || 0, 0);
+ }
+ if (!self.hourElement || !self.minuteElement || self.isMobile)
+ return;
+ self.hourElement.value = pad(!self.config.time_24hr
+ ? ((12 + hours) % 12) + 12 * int(hours % 12 === 0)
+ : hours);
+ self.minuteElement.value = pad(minutes);
+ if (self.amPM !== undefined)
+ self.amPM.textContent = self.l10n.amPM[int(hours >= 12)];
+ if (self.secondElement !== undefined)
+ self.secondElement.value = pad(seconds);
+ }
+ /**
+ * Handles the year input and incrementing events
+ * @param {Event} event the keyup or increment event
+ */
+ function onYearInput(event) {
+ var eventTarget = getEventTarget(event);
+ var year = parseInt(eventTarget.value) + (event.delta || 0);
+ if (year / 1000 > 1 ||
+ (event.key === "Enter" && !/[^\d]/.test(year.toString()))) {
+ changeYear(year);
+ }
+ }
+ /**
+ * Essentially addEventListener + tracking
+ * @param {Element} element the element to addEventListener to
+ * @param {String} event the event name
+ * @param {Function} handler the event handler
+ */
+ function bind(element, event, handler, options) {
+ if (event instanceof Array)
+ return event.forEach(function (ev) { return bind(element, ev, handler, options); });
+ if (element instanceof Array)
+ return element.forEach(function (el) { return bind(el, event, handler, options); });
+ element.addEventListener(event, handler, options);
+ self._handlers.push({
+ remove: function () { return element.removeEventListener(event, handler); },
+ });
+ }
+ function triggerChange() {
+ triggerEvent("onChange");
+ }
+ /**
+ * Adds all the necessary event listeners
+ */
+ function bindEvents() {
+ if (self.config.wrap) {
+ ["open", "close", "toggle", "clear"].forEach(function (evt) {
+ Array.prototype.forEach.call(self.element.querySelectorAll("[data-" + evt + "]"), function (el) {
+ return bind(el, "click", self[evt]);
+ });
+ });
+ }
+ if (self.isMobile) {
+ setupMobile();
+ return;
+ }
+ var debouncedResize = debounce(onResize, 50);
+ self._debouncedChange = debounce(triggerChange, DEBOUNCED_CHANGE_MS);
+ if (self.daysContainer && !/iPhone|iPad|iPod/i.test(navigator.userAgent))
+ bind(self.daysContainer, "mouseover", function (e) {
+ if (self.config.mode === "range")
+ onMouseOver(getEventTarget(e));
+ });
+ bind(self._input, "keydown", onKeyDown);
+ if (self.calendarContainer !== undefined) {
+ bind(self.calendarContainer, "keydown", onKeyDown);
+ }
+ if (!self.config.inline && !self.config.static)
+ bind(window, "resize", debouncedResize);
+ if (window.ontouchstart !== undefined)
+ bind(window.document, "touchstart", documentClick);
+ else
+ bind(window.document, "mousedown", documentClick);
+ bind(window.document, "focus", documentClick, { capture: true });
+ if (self.config.clickOpens === true) {
+ bind(self._input, "focus", self.open);
+ bind(self._input, "click", self.open);
+ }
+ if (self.daysContainer !== undefined) {
+ bind(self.monthNav, "click", onMonthNavClick);
+ bind(self.monthNav, ["keyup", "increment"], onYearInput);
+ bind(self.daysContainer, "click", selectDate);
+ }
+ if (self.timeContainer !== undefined &&
+ self.minuteElement !== undefined &&
+ self.hourElement !== undefined) {
+ var selText = function (e) {
+ return getEventTarget(e).select();
+ };
+ bind(self.timeContainer, ["increment"], updateTime);
+ bind(self.timeContainer, "blur", updateTime, { capture: true });
+ bind(self.timeContainer, "click", timeIncrement);
+ bind([self.hourElement, self.minuteElement], ["focus", "click"], selText);
+ if (self.secondElement !== undefined)
+ bind(self.secondElement, "focus", function () { return self.secondElement && self.secondElement.select(); });
+ if (self.amPM !== undefined) {
+ bind(self.amPM, "click", function (e) {
+ updateTime(e);
+ triggerChange();
+ });
+ }
+ }
+ if (self.config.allowInput) {
+ bind(self._input, "blur", onBlur);
+ }
+ }
+ /**
+ * Set the calendar view to a particular date.
+ * @param {Date} jumpDate the date to set the view to
+ * @param {boolean} triggerChange if change events should be triggered
+ */
+ function jumpToDate(jumpDate, triggerChange) {
+ var jumpTo = jumpDate !== undefined
+ ? self.parseDate(jumpDate)
+ : self.latestSelectedDateObj ||
+ (self.config.minDate && self.config.minDate > self.now
+ ? self.config.minDate
+ : self.config.maxDate && self.config.maxDate < self.now
+ ? self.config.maxDate
+ : self.now);
+ var oldYear = self.currentYear;
+ var oldMonth = self.currentMonth;
+ try {
+ if (jumpTo !== undefined) {
+ self.currentYear = jumpTo.getFullYear();
+ self.currentMonth = jumpTo.getMonth();
+ }
+ }
+ catch (e) {
+ /* istanbul ignore next */
+ e.message = "Invalid date supplied: " + jumpTo;
+ self.config.errorHandler(e);
+ }
+ if (triggerChange && self.currentYear !== oldYear) {
+ triggerEvent("onYearChange");
+ buildMonthSwitch();
+ }
+ if (triggerChange &&
+ (self.currentYear !== oldYear || self.currentMonth !== oldMonth)) {
+ triggerEvent("onMonthChange");
+ }
+ self.redraw();
+ }
+ /**
+ * The up/down arrow handler for time inputs
+ * @param {Event} e the click event
+ */
+ function timeIncrement(e) {
+ var eventTarget = getEventTarget(e);
+ if (~eventTarget.className.indexOf("arrow"))
+ incrementNumInput(e, eventTarget.classList.contains("arrowUp") ? 1 : -1);
+ }
+ /**
+ * Increments/decrements the value of input associ-
+ * ated with the up/down arrow by dispatching an
+ * "increment" event on the input.
+ *
+ * @param {Event} e the click event
+ * @param {Number} delta the diff (usually 1 or -1)
+ * @param {Element} inputElem the input element
+ */
+ function incrementNumInput(e, delta, inputElem) {
+ var target = e && getEventTarget(e);
+ var input = inputElem ||
+ (target && target.parentNode && target.parentNode.firstChild);
+ var event = createEvent("increment");
+ event.delta = delta;
+ input && input.dispatchEvent(event);
+ }
+ function build() {
+ var fragment = window.document.createDocumentFragment();
+ self.calendarContainer = createElement("div", "flatpickr-calendar");
+ self.calendarContainer.tabIndex = -1;
+ if (!self.config.noCalendar) {
+ fragment.appendChild(buildMonthNav());
+ self.innerContainer = createElement("div", "flatpickr-innerContainer");
+ if (self.config.weekNumbers) {
+ var _a = buildWeeks(), weekWrapper = _a.weekWrapper, weekNumbers = _a.weekNumbers;
+ self.innerContainer.appendChild(weekWrapper);
+ self.weekNumbers = weekNumbers;
+ self.weekWrapper = weekWrapper;
+ }
+ self.rContainer = createElement("div", "flatpickr-rContainer");
+ self.rContainer.appendChild(buildWeekdays());
+ if (!self.daysContainer) {
+ self.daysContainer = createElement("div", "flatpickr-days");
+ self.daysContainer.tabIndex = -1;
+ }
+ buildDays();
+ self.rContainer.appendChild(self.daysContainer);
+ self.innerContainer.appendChild(self.rContainer);
+ fragment.appendChild(self.innerContainer);
+ }
+ if (self.config.enableTime) {
+ fragment.appendChild(buildTime());
+ }
+ toggleClass(self.calendarContainer, "rangeMode", self.config.mode === "range");
+ toggleClass(self.calendarContainer, "animate", self.config.animate === true);
+ toggleClass(self.calendarContainer, "multiMonth", self.config.showMonths > 1);
+ self.calendarContainer.appendChild(fragment);
+ var customAppend = self.config.appendTo !== undefined &&
+ self.config.appendTo.nodeType !== undefined;
+ if (self.config.inline || self.config.static) {
+ self.calendarContainer.classList.add(self.config.inline ? "inline" : "static");
+ if (self.config.inline) {
+ if (!customAppend && self.element.parentNode)
+ self.element.parentNode.insertBefore(self.calendarContainer, self._input.nextSibling);
+ else if (self.config.appendTo !== undefined)
+ self.config.appendTo.appendChild(self.calendarContainer);
+ }
+ if (self.config.static) {
+ var wrapper = createElement("div", "flatpickr-wrapper");
+ if (self.element.parentNode)
+ self.element.parentNode.insertBefore(wrapper, self.element);
+ wrapper.appendChild(self.element);
+ if (self.altInput)
+ wrapper.appendChild(self.altInput);
+ wrapper.appendChild(self.calendarContainer);
+ }
+ }
+ if (!self.config.static && !self.config.inline)
+ (self.config.appendTo !== undefined
+ ? self.config.appendTo
+ : window.document.body).appendChild(self.calendarContainer);
+ }
+ function createDay(className, date, dayNumber, i) {
+ var dateIsEnabled = isEnabled(date, true), dayElement = createElement("span", "flatpickr-day " + className, date.getDate().toString());
+ dayElement.dateObj = date;
+ dayElement.$i = i;
+ dayElement.setAttribute("aria-label", self.formatDate(date, self.config.ariaDateFormat));
+ if (className.indexOf("hidden") === -1 &&
+ compareDates(date, self.now) === 0) {
+ self.todayDateElem = dayElement;
+ dayElement.classList.add("today");
+ dayElement.setAttribute("aria-current", "date");
+ }
+ if (dateIsEnabled) {
+ dayElement.tabIndex = -1;
+ if (isDateSelected(date)) {
+ dayElement.classList.add("selected");
+ self.selectedDateElem = dayElement;
+ if (self.config.mode === "range") {
+ toggleClass(dayElement, "startRange", self.selectedDates[0] &&
+ compareDates(date, self.selectedDates[0], true) === 0);
+ toggleClass(dayElement, "endRange", self.selectedDates[1] &&
+ compareDates(date, self.selectedDates[1], true) === 0);
+ if (className === "nextMonthDay")
+ dayElement.classList.add("inRange");
+ }
+ }
+ }
+ else {
+ dayElement.classList.add("flatpickr-disabled");
+ }
+ if (self.config.mode === "range") {
+ if (isDateInRange(date) && !isDateSelected(date))
+ dayElement.classList.add("inRange");
+ }
+ if (self.weekNumbers &&
+ self.config.showMonths === 1 &&
+ className !== "prevMonthDay" &&
+ dayNumber % 7 === 1) {
+ self.weekNumbers.insertAdjacentHTML("beforeend", "<span class='flatpickr-day'>" + self.config.getWeek(date) + "</span>");
+ }
+ triggerEvent("onDayCreate", dayElement);
+ return dayElement;
+ }
+ function focusOnDayElem(targetNode) {
+ targetNode.focus();
+ if (self.config.mode === "range")
+ onMouseOver(targetNode);
+ }
+ function getFirstAvailableDay(delta) {
+ var startMonth = delta > 0 ? 0 : self.config.showMonths - 1;
+ var endMonth = delta > 0 ? self.config.showMonths : -1;
+ for (var m = startMonth; m != endMonth; m += delta) {
+ var month = self.daysContainer.children[m];
+ var startIndex = delta > 0 ? 0 : month.children.length - 1;
+ var endIndex = delta > 0 ? month.children.length : -1;
+ for (var i = startIndex; i != endIndex; i += delta) {
+ var c = month.children[i];
+ if (c.className.indexOf("hidden") === -1 && isEnabled(c.dateObj))
+ return c;
+ }
+ }
+ return undefined;
+ }
+ function getNextAvailableDay(current, delta) {
+ var givenMonth = current.className.indexOf("Month") === -1
+ ? current.dateObj.getMonth()
+ : self.currentMonth;
+ var endMonth = delta > 0 ? self.config.showMonths : -1;
+ var loopDelta = delta > 0 ? 1 : -1;
+ for (var m = givenMonth - self.currentMonth; m != endMonth; m += loopDelta) {
+ var month = self.daysContainer.children[m];
+ var startIndex = givenMonth - self.currentMonth === m
+ ? current.$i + delta
+ : delta < 0
+ ? month.children.length - 1
+ : 0;
+ var numMonthDays = month.children.length;
+ for (var i = startIndex; i >= 0 && i < numMonthDays && i != (delta > 0 ? numMonthDays : -1); i += loopDelta) {
+ var c = month.children[i];
+ if (c.className.indexOf("hidden") === -1 &&
+ isEnabled(c.dateObj) &&
+ Math.abs(current.$i - i) >= Math.abs(delta))
+ return focusOnDayElem(c);
+ }
+ }
+ self.changeMonth(loopDelta);
+ focusOnDay(getFirstAvailableDay(loopDelta), 0);
+ return undefined;
+ }
+ function focusOnDay(current, offset) {
+ var dayFocused = isInView(document.activeElement || document.body);
+ var startElem = current !== undefined
+ ? current
+ : dayFocused
+ ? document.activeElement
+ : self.selectedDateElem !== undefined && isInView(self.selectedDateElem)
+ ? self.selectedDateElem
+ : self.todayDateElem !== undefined && isInView(self.todayDateElem)
+ ? self.todayDateElem
+ : getFirstAvailableDay(offset > 0 ? 1 : -1);
+ if (startElem === undefined) {
+ self._input.focus();
+ }
+ else if (!dayFocused) {
+ focusOnDayElem(startElem);
+ }
+ else {
+ getNextAvailableDay(startElem, offset);
+ }
+ }
+ function buildMonthDays(year, month) {
+ var firstOfMonth = (new Date(year, month, 1).getDay() - self.l10n.firstDayOfWeek + 7) % 7;
+ var prevMonthDays = self.utils.getDaysInMonth((month - 1 + 12) % 12, year);
+ var daysInMonth = self.utils.getDaysInMonth(month, year), days = window.document.createDocumentFragment(), isMultiMonth = self.config.showMonths > 1, prevMonthDayClass = isMultiMonth ? "prevMonthDay hidden" : "prevMonthDay", nextMonthDayClass = isMultiMonth ? "nextMonthDay hidden" : "nextMonthDay";
+ var dayNumber = prevMonthDays + 1 - firstOfMonth, dayIndex = 0;
+ // prepend days from the ending of previous month
+ for (; dayNumber <= prevMonthDays; dayNumber++, dayIndex++) {
+ days.appendChild(createDay(prevMonthDayClass, new Date(year, month - 1, dayNumber), dayNumber, dayIndex));
+ }
+ // Start at 1 since there is no 0th day
+ for (dayNumber = 1; dayNumber <= daysInMonth; dayNumber++, dayIndex++) {
+ days.appendChild(createDay("", new Date(year, month, dayNumber), dayNumber, dayIndex));
+ }
+ // append days from the next month
+ for (var dayNum = daysInMonth + 1; dayNum <= 42 - firstOfMonth &&
+ (self.config.showMonths === 1 || dayIndex % 7 !== 0); dayNum++, dayIndex++) {
+ days.appendChild(createDay(nextMonthDayClass, new Date(year, month + 1, dayNum % daysInMonth), dayNum, dayIndex));
+ }
+ //updateNavigationCurrentMonth();
+ var dayContainer = createElement("div", "dayContainer");
+ dayContainer.appendChild(days);
+ return dayContainer;
+ }
+ function buildDays() {
+ if (self.daysContainer === undefined) {
+ return;
+ }
+ clearNode(self.daysContainer);
+ // TODO: week numbers for each month
+ if (self.weekNumbers)
+ clearNode(self.weekNumbers);
+ var frag = document.createDocumentFragment();
+ for (var i = 0; i < self.config.showMonths; i++) {
+ var d = new Date(self.currentYear, self.currentMonth, 1);
+ d.setMonth(self.currentMonth + i);
+ frag.appendChild(buildMonthDays(d.getFullYear(), d.getMonth()));
+ }
+ self.daysContainer.appendChild(frag);
+ self.days = self.daysContainer.firstChild;
+ if (self.config.mode === "range" && self.selectedDates.length === 1) {
+ onMouseOver();
+ }
+ }
+ function buildMonthSwitch() {
+ if (self.config.showMonths > 1 ||
+ self.config.monthSelectorType !== "dropdown")
+ return;
+ var shouldBuildMonth = function (month) {
+ if (self.config.minDate !== undefined &&
+ self.currentYear === self.config.minDate.getFullYear() &&
+ month < self.config.minDate.getMonth()) {
+ return false;
+ }
+ return !(self.config.maxDate !== undefined &&
+ self.currentYear === self.config.maxDate.getFullYear() &&
+ month > self.config.maxDate.getMonth());
+ };
+ self.monthsDropdownContainer.tabIndex = -1;
+ self.monthsDropdownContainer.innerHTML = "";
+ for (var i = 0; i < 12; i++) {
+ if (!shouldBuildMonth(i))
+ continue;
+ var month = createElement("option", "flatpickr-monthDropdown-month");
+ month.value = new Date(self.currentYear, i).getMonth().toString();
+ month.textContent = monthToStr(i, self.config.shorthandCurrentMonth, self.l10n);
+ month.tabIndex = -1;
+ if (self.currentMonth === i) {
+ month.selected = true;
+ }
+ self.monthsDropdownContainer.appendChild(month);
+ }
+ }
+ function buildMonth() {
+ var container = createElement("div", "flatpickr-month");
+ var monthNavFragment = window.document.createDocumentFragment();
+ var monthElement;
+ if (self.config.showMonths > 1 ||
+ self.config.monthSelectorType === "static") {
+ monthElement = createElement("span", "cur-month");
+ }
+ else {
+ self.monthsDropdownContainer = createElement("select", "flatpickr-monthDropdown-months");
+ self.monthsDropdownContainer.setAttribute("aria-label", self.l10n.monthAriaLabel);
+ bind(self.monthsDropdownContainer, "change", function (e) {
+ var target = getEventTarget(e);
+ var selectedMonth = parseInt(target.value, 10);
+ self.changeMonth(selectedMonth - self.currentMonth);
+ triggerEvent("onMonthChange");
+ });
+ buildMonthSwitch();
+ monthElement = self.monthsDropdownContainer;
+ }
+ var yearInput = createNumberInput("cur-year", { tabindex: "-1" });
+ var yearElement = yearInput.getElementsByTagName("input")[0];
+ yearElement.setAttribute("aria-label", self.l10n.yearAriaLabel);
+ if (self.config.minDate) {
+ yearElement.setAttribute("min", self.config.minDate.getFullYear().toString());
+ }
+ if (self.config.maxDate) {
+ yearElement.setAttribute("max", self.config.maxDate.getFullYear().toString());
+ yearElement.disabled =
+ !!self.config.minDate &&
+ self.config.minDate.getFullYear() === self.config.maxDate.getFullYear();
+ }
+ var currentMonth = createElement("div", "flatpickr-current-month");
+ currentMonth.appendChild(monthElement);
+ currentMonth.appendChild(yearInput);
+ monthNavFragment.appendChild(currentMonth);
+ container.appendChild(monthNavFragment);
+ return {
+ container: container,
+ yearElement: yearElement,
+ monthElement: monthElement,
+ };
+ }
+ function buildMonths() {
+ clearNode(self.monthNav);
+ self.monthNav.appendChild(self.prevMonthNav);
+ if (self.config.showMonths) {
+ self.yearElements = [];
+ self.monthElements = [];
+ }
+ for (var m = self.config.showMonths; m--;) {
+ var month = buildMonth();
+ self.yearElements.push(month.yearElement);
+ self.monthElements.push(month.monthElement);
+ self.monthNav.appendChild(month.container);
+ }
+ self.monthNav.appendChild(self.nextMonthNav);
+ }
+ function buildMonthNav() {
+ self.monthNav = createElement("div", "flatpickr-months");
+ self.yearElements = [];
+ self.monthElements = [];
+ self.prevMonthNav = createElement("span", "flatpickr-prev-month");
+ self.prevMonthNav.innerHTML = self.config.prevArrow;
+ self.nextMonthNav = createElement("span", "flatpickr-next-month");
+ self.nextMonthNav.innerHTML = self.config.nextArrow;
+ buildMonths();
+ Object.defineProperty(self, "_hidePrevMonthArrow", {
+ get: function () { return self.__hidePrevMonthArrow; },
+ set: function (bool) {
+ if (self.__hidePrevMonthArrow !== bool) {
+ toggleClass(self.prevMonthNav, "flatpickr-disabled", bool);
+ self.__hidePrevMonthArrow = bool;
+ }
+ },
+ });
+ Object.defineProperty(self, "_hideNextMonthArrow", {
+ get: function () { return self.__hideNextMonthArrow; },
+ set: function (bool) {
+ if (self.__hideNextMonthArrow !== bool) {
+ toggleClass(self.nextMonthNav, "flatpickr-disabled", bool);
+ self.__hideNextMonthArrow = bool;
+ }
+ },
+ });
+ self.currentYearElement = self.yearElements[0];
+ updateNavigationCurrentMonth();
+ return self.monthNav;
+ }
+ function buildTime() {
+ self.calendarContainer.classList.add("hasTime");
+ if (self.config.noCalendar)
+ self.calendarContainer.classList.add("noCalendar");
+ var defaults = getDefaultHours(self.config);
+ self.timeContainer = createElement("div", "flatpickr-time");
+ self.timeContainer.tabIndex = -1;
+ var separator = createElement("span", "flatpickr-time-separator", ":");
+ var hourInput = createNumberInput("flatpickr-hour", {
+ "aria-label": self.l10n.hourAriaLabel,
+ });
+ self.hourElement = hourInput.getElementsByTagName("input")[0];
+ var minuteInput = createNumberInput("flatpickr-minute", {
+ "aria-label": self.l10n.minuteAriaLabel,
+ });
+ self.minuteElement = minuteInput.getElementsByTagName("input")[0];
+ self.hourElement.tabIndex = self.minuteElement.tabIndex = -1;
+ self.hourElement.value = pad(self.latestSelectedDateObj
+ ? self.latestSelectedDateObj.getHours()
+ : self.config.time_24hr
+ ? defaults.hours
+ : military2ampm(defaults.hours));
+ self.minuteElement.value = pad(self.latestSelectedDateObj
+ ? self.latestSelectedDateObj.getMinutes()
+ : defaults.minutes);
+ self.hourElement.setAttribute("step", self.config.hourIncrement.toString());
+ self.minuteElement.setAttribute("step", self.config.minuteIncrement.toString());
+ self.hourElement.setAttribute("min", self.config.time_24hr ? "0" : "1");
+ self.hourElement.setAttribute("max", self.config.time_24hr ? "23" : "12");
+ self.hourElement.setAttribute("maxlength", "2");
+ self.minuteElement.setAttribute("min", "0");
+ self.minuteElement.setAttribute("max", "59");
+ self.minuteElement.setAttribute("maxlength", "2");
+ self.timeContainer.appendChild(hourInput);
+ self.timeContainer.appendChild(separator);
+ self.timeContainer.appendChild(minuteInput);
+ if (self.config.time_24hr)
+ self.timeContainer.classList.add("time24hr");
+ if (self.config.enableSeconds) {
+ self.timeContainer.classList.add("hasSeconds");
+ var secondInput = createNumberInput("flatpickr-second");
+ self.secondElement = secondInput.getElementsByTagName("input")[0];
+ self.secondElement.value = pad(self.latestSelectedDateObj
+ ? self.latestSelectedDateObj.getSeconds()
+ : defaults.seconds);
+ self.secondElement.setAttribute("step", self.minuteElement.getAttribute("step"));
+ self.secondElement.setAttribute("min", "0");
+ self.secondElement.setAttribute("max", "59");
+ self.secondElement.setAttribute("maxlength", "2");
+ self.timeContainer.appendChild(createElement("span", "flatpickr-time-separator", ":"));
+ self.timeContainer.appendChild(secondInput);
+ }
+ if (!self.config.time_24hr) {
+ // add self.amPM if appropriate
+ self.amPM = createElement("span", "flatpickr-am-pm", self.l10n.amPM[int((self.latestSelectedDateObj
+ ? self.hourElement.value
+ : self.config.defaultHour) > 11)]);
+ self.amPM.title = self.l10n.toggleTitle;
+ self.amPM.tabIndex = -1;
+ self.timeContainer.appendChild(self.amPM);
+ }
+ return self.timeContainer;
+ }
+ function buildWeekdays() {
+ if (!self.weekdayContainer)
+ self.weekdayContainer = createElement("div", "flatpickr-weekdays");
+ else
+ clearNode(self.weekdayContainer);
+ for (var i = self.config.showMonths; i--;) {
+ var container = createElement("div", "flatpickr-weekdaycontainer");
+ self.weekdayContainer.appendChild(container);
+ }
+ updateWeekdays();
+ return self.weekdayContainer;
+ }
+ function updateWeekdays() {
+ if (!self.weekdayContainer) {
+ return;
+ }
+ var firstDayOfWeek = self.l10n.firstDayOfWeek;
+ var weekdays = __spreadArrays(self.l10n.weekdays.shorthand);
+ if (firstDayOfWeek > 0 && firstDayOfWeek < weekdays.length) {
+ weekdays = __spreadArrays(weekdays.splice(firstDayOfWeek, weekdays.length), weekdays.splice(0, firstDayOfWeek));
+ }
+ for (var i = self.config.showMonths; i--;) {
+ self.weekdayContainer.children[i].innerHTML = "\n <span class='flatpickr-weekday'>\n " + weekdays.join("</span><span class='flatpickr-weekday'>") + "\n </span>\n ";
+ }
+ }
+ /* istanbul ignore next */
+ function buildWeeks() {
+ self.calendarContainer.classList.add("hasWeeks");
+ var weekWrapper = createElement("div", "flatpickr-weekwrapper");
+ weekWrapper.appendChild(createElement("span", "flatpickr-weekday", self.l10n.weekAbbreviation));
+ var weekNumbers = createElement("div", "flatpickr-weeks");
+ weekWrapper.appendChild(weekNumbers);
+ return {
+ weekWrapper: weekWrapper,
+ weekNumbers: weekNumbers,
+ };
+ }
+ function changeMonth(value, isOffset) {
+ if (isOffset === void 0) { isOffset = true; }
+ var delta = isOffset ? value : value - self.currentMonth;
+ if ((delta < 0 && self._hidePrevMonthArrow === true) ||
+ (delta > 0 && self._hideNextMonthArrow === true))
+ return;
+ self.currentMonth += delta;
+ if (self.currentMonth < 0 || self.currentMonth > 11) {
+ self.currentYear += self.currentMonth > 11 ? 1 : -1;
+ self.currentMonth = (self.currentMonth + 12) % 12;
+ triggerEvent("onYearChange");
+ buildMonthSwitch();
+ }
+ buildDays();
+ triggerEvent("onMonthChange");
+ updateNavigationCurrentMonth();
+ }
+ function clear(triggerChangeEvent, toInitial) {
+ if (triggerChangeEvent === void 0) { triggerChangeEvent = true; }
+ if (toInitial === void 0) { toInitial = true; }
+ self.input.value = "";
+ if (self.altInput !== undefined)
+ self.altInput.value = "";
+ if (self.mobileInput !== undefined)
+ self.mobileInput.value = "";
+ self.selectedDates = [];
+ self.latestSelectedDateObj = undefined;
+ if (toInitial === true) {
+ self.currentYear = self._initialDate.getFullYear();
+ self.currentMonth = self._initialDate.getMonth();
+ }
+ if (self.config.enableTime === true) {
+ var _a = getDefaultHours(self.config), hours = _a.hours, minutes = _a.minutes, seconds = _a.seconds;
+ setHours(hours, minutes, seconds);
+ }
+ self.redraw();
+ if (triggerChangeEvent)
+ // triggerChangeEvent is true (default) or an Event
+ triggerEvent("onChange");
+ }
+ function close() {
+ self.isOpen = false;
+ if (!self.isMobile) {
+ if (self.calendarContainer !== undefined) {
+ self.calendarContainer.classList.remove("open");
+ }
+ if (self._input !== undefined) {
+ self._input.classList.remove("active");
+ }
+ }
+ triggerEvent("onClose");
+ }
+ function destroy() {
+ if (self.config !== undefined)
+ triggerEvent("onDestroy");
+ for (var i = self._handlers.length; i--;) {
+ self._handlers[i].remove();
+ }
+ self._handlers = [];
+ if (self.mobileInput) {
+ if (self.mobileInput.parentNode)
+ self.mobileInput.parentNode.removeChild(self.mobileInput);
+ self.mobileInput = undefined;
+ }
+ else if (self.calendarContainer && self.calendarContainer.parentNode) {
+ if (self.config.static && self.calendarContainer.parentNode) {
+ var wrapper = self.calendarContainer.parentNode;
+ wrapper.lastChild && wrapper.removeChild(wrapper.lastChild);
+ if (wrapper.parentNode) {
+ while (wrapper.firstChild)
+ wrapper.parentNode.insertBefore(wrapper.firstChild, wrapper);
+ wrapper.parentNode.removeChild(wrapper);
+ }
+ }
+ else
+ self.calendarContainer.parentNode.removeChild(self.calendarContainer);
+ }
+ if (self.altInput) {
+ self.input.type = "text";
+ if (self.altInput.parentNode)
+ self.altInput.parentNode.removeChild(self.altInput);
+ delete self.altInput;
+ }
+ if (self.input) {
+ self.input.type = self.input._type;
+ self.input.classList.remove("flatpickr-input");
+ self.input.removeAttribute("readonly");
+ }
+ [
+ "_showTimeInput",
+ "latestSelectedDateObj",
+ "_hideNextMonthArrow",
+ "_hidePrevMonthArrow",
+ "__hideNextMonthArrow",
+ "__hidePrevMonthArrow",
+ "isMobile",
+ "isOpen",
+ "selectedDateElem",
+ "minDateHasTime",
+ "maxDateHasTime",
+ "days",
+ "daysContainer",
+ "_input",
+ "_positionElement",
+ "innerContainer",
+ "rContainer",
+ "monthNav",
+ "todayDateElem",
+ "calendarContainer",
+ "weekdayContainer",
+ "prevMonthNav",
+ "nextMonthNav",
+ "monthsDropdownContainer",
+ "currentMonthElement",
+ "currentYearElement",
+ "navigationCurrentMonth",
+ "selectedDateElem",
+ "config",
+ ].forEach(function (k) {
+ try {
+ delete self[k];
+ }
+ catch (_) { }
+ });
+ }
+ function isCalendarElem(elem) {
+ if (self.config.appendTo && self.config.appendTo.contains(elem))
+ return true;
+ return self.calendarContainer.contains(elem);
+ }
+ function documentClick(e) {
+ if (self.isOpen && !self.config.inline) {
+ var eventTarget_1 = getEventTarget(e);
+ var isCalendarElement = isCalendarElem(eventTarget_1);
+ var isInput = eventTarget_1 === self.input ||
+ eventTarget_1 === self.altInput ||
+ self.element.contains(eventTarget_1) ||
+ // web components
+ // e.path is not present in all browsers. circumventing typechecks
+ (e.path &&
+ e.path.indexOf &&
+ (~e.path.indexOf(self.input) ||
+ ~e.path.indexOf(self.altInput)));
+ var lostFocus = e.type === "blur"
+ ? isInput &&
+ e.relatedTarget &&
+ !isCalendarElem(e.relatedTarget)
+ : !isInput &&
+ !isCalendarElement &&
+ !isCalendarElem(e.relatedTarget);
+ var isIgnored = !self.config.ignoredFocusElements.some(function (elem) {
+ return elem.contains(eventTarget_1);
+ });
+ if (lostFocus && isIgnored) {
+ if (self.timeContainer !== undefined &&
+ self.minuteElement !== undefined &&
+ self.hourElement !== undefined &&
+ self.input.value !== "" &&
+ self.input.value !== undefined) {
+ updateTime();
+ }
+ self.close();
+ if (self.config &&
+ self.config.mode === "range" &&
+ self.selectedDates.length === 1) {
+ self.clear(false);
+ self.redraw();
+ }
+ }
+ }
+ }
+ function changeYear(newYear) {
+ if (!newYear ||
+ (self.config.minDate && newYear < self.config.minDate.getFullYear()) ||
+ (self.config.maxDate && newYear > self.config.maxDate.getFullYear()))
+ return;
+ var newYearNum = newYear, isNewYear = self.currentYear !== newYearNum;
+ self.currentYear = newYearNum || self.currentYear;
+ if (self.config.maxDate &&
+ self.currentYear === self.config.maxDate.getFullYear()) {
+ self.currentMonth = Math.min(self.config.maxDate.getMonth(), self.currentMonth);
+ }
+ else if (self.config.minDate &&
+ self.currentYear === self.config.minDate.getFullYear()) {
+ self.currentMonth = Math.max(self.config.minDate.getMonth(), self.currentMonth);
+ }
+ if (isNewYear) {
+ self.redraw();
+ triggerEvent("onYearChange");
+ buildMonthSwitch();
+ }
+ }
+ function isEnabled(date, timeless) {
+ var _a;
+ if (timeless === void 0) { timeless = true; }
+ var dateToCheck = self.parseDate(date, undefined, timeless); // timeless
+ if ((self.config.minDate &&
+ dateToCheck &&
+ compareDates(dateToCheck, self.config.minDate, timeless !== undefined ? timeless : !self.minDateHasTime) < 0) ||
+ (self.config.maxDate &&
+ dateToCheck &&
+ compareDates(dateToCheck, self.config.maxDate, timeless !== undefined ? timeless : !self.maxDateHasTime) > 0))
+ return false;
+ if (!self.config.enable && self.config.disable.length === 0)
+ return true;
+ if (dateToCheck === undefined)
+ return false;
+ var bool = !!self.config.enable, array = (_a = self.config.enable) !== null && _a !== void 0 ? _a : self.config.disable;
+ for (var i = 0, d = void 0; i < array.length; i++) {
+ d = array[i];
+ if (typeof d === "function" &&
+ d(dateToCheck) // disabled by function
+ )
+ return bool;
+ else if (d instanceof Date &&
+ dateToCheck !== undefined &&
+ d.getTime() === dateToCheck.getTime())
+ // disabled by date
+ return bool;
+ else if (typeof d === "string") {
+ // disabled by date string
+ var parsed = self.parseDate(d, undefined, true);
+ return parsed && parsed.getTime() === dateToCheck.getTime()
+ ? bool
+ : !bool;
+ }
+ else if (
+ // disabled by range
+ typeof d === "object" &&
+ dateToCheck !== undefined &&
+ d.from &&
+ d.to &&
+ dateToCheck.getTime() >= d.from.getTime() &&
+ dateToCheck.getTime() <= d.to.getTime())
+ return bool;
+ }
+ return !bool;
+ }
+ function isInView(elem) {
+ if (self.daysContainer !== undefined)
+ return (elem.className.indexOf("hidden") === -1 &&
+ elem.className.indexOf("flatpickr-disabled") === -1 &&
+ self.daysContainer.contains(elem));
+ return false;
+ }
+ function onBlur(e) {
+ var isInput = e.target === self._input;
+ if (isInput &&
+ (self.selectedDates.length > 0 || self._input.value.length > 0) &&
+ !(e.relatedTarget && isCalendarElem(e.relatedTarget))) {
+ self.setDate(self._input.value, true, e.target === self.altInput
+ ? self.config.altFormat
+ : self.config.dateFormat);
+ }
+ }
+ function onKeyDown(e) {
+ // e.key e.keyCode
+ // "Backspace" 8
+ // "Tab" 9
+ // "Enter" 13
+ // "Escape" (IE "Esc") 27
+ // "ArrowLeft" (IE "Left") 37
+ // "ArrowUp" (IE "Up") 38
+ // "ArrowRight" (IE "Right") 39
+ // "ArrowDown" (IE "Down") 40
+ // "Delete" (IE "Del") 46
+ var eventTarget = getEventTarget(e);
+ var isInput = self.config.wrap
+ ? element.contains(eventTarget)
+ : eventTarget === self._input;
+ var allowInput = self.config.allowInput;
+ var allowKeydown = self.isOpen && (!allowInput || !isInput);
+ var allowInlineKeydown = self.config.inline && isInput && !allowInput;
+ if (e.keyCode === 13 && isInput) {
+ if (allowInput) {
+ self.setDate(self._input.value, true, eventTarget === self.altInput
+ ? self.config.altFormat
+ : self.config.dateFormat);
+ return eventTarget.blur();
+ }
+ else {
+ self.open();
+ }
+ }
+ else if (isCalendarElem(eventTarget) ||
+ allowKeydown ||
+ allowInlineKeydown) {
+ var isTimeObj = !!self.timeContainer &&
+ self.timeContainer.contains(eventTarget);
+ switch (e.keyCode) {
+ case 13:
+ if (isTimeObj) {
+ e.preventDefault();
+ updateTime();
+ focusAndClose();
+ }
+ else
+ selectDate(e);
+ break;
+ case 27: // escape
+ e.preventDefault();
+ focusAndClose();
+ break;
+ case 8:
+ case 46:
+ if (isInput && !self.config.allowInput) {
+ e.preventDefault();
+ self.clear();
+ }
+ break;
+ case 37:
+ case 39:
+ if (!isTimeObj && !isInput) {
+ e.preventDefault();
+ if (self.daysContainer !== undefined &&
+ (allowInput === false ||
+ (document.activeElement && isInView(document.activeElement)))) {
+ var delta_1 = e.keyCode === 39 ? 1 : -1;
+ if (!e.ctrlKey)
+ focusOnDay(undefined, delta_1);
+ else {
+ e.stopPropagation();
+ changeMonth(delta_1);
+ focusOnDay(getFirstAvailableDay(1), 0);
+ }
+ }
+ }
+ else if (self.hourElement)
+ self.hourElement.focus();
+ break;
+ case 38:
+ case 40:
+ e.preventDefault();
+ var delta = e.keyCode === 40 ? 1 : -1;
+ if ((self.daysContainer &&
+ eventTarget.$i !== undefined) ||
+ eventTarget === self.input ||
+ eventTarget === self.altInput) {
+ if (e.ctrlKey) {
+ e.stopPropagation();
+ changeYear(self.currentYear - delta);
+ focusOnDay(getFirstAvailableDay(1), 0);
+ }
+ else if (!isTimeObj)
+ focusOnDay(undefined, delta * 7);
+ }
+ else if (eventTarget === self.currentYearElement) {
+ changeYear(self.currentYear - delta);
+ }
+ else if (self.config.enableTime) {
+ if (!isTimeObj && self.hourElement)
+ self.hourElement.focus();
+ updateTime(e);
+ self._debouncedChange();
+ }
+ break;
+ case 9:
+ if (isTimeObj) {
+ var elems = [
+ self.hourElement,
+ self.minuteElement,
+ self.secondElement,
+ self.amPM,
+ ]
+ .concat(self.pluginElements)
+ .filter(function (x) { return x; });
+ var i = elems.indexOf(eventTarget);
+ if (i !== -1) {
+ var target = elems[i + (e.shiftKey ? -1 : 1)];
+ e.preventDefault();
+ (target || self._input).focus();
+ }
+ }
+ else if (!self.config.noCalendar &&
+ self.daysContainer &&
+ self.daysContainer.contains(eventTarget) &&
+ e.shiftKey) {
+ e.preventDefault();
+ self._input.focus();
+ }
+ break;
+ }
+ }
+ if (self.amPM !== undefined && eventTarget === self.amPM) {
+ switch (e.key) {
+ case self.l10n.amPM[0].charAt(0):
+ case self.l10n.amPM[0].charAt(0).toLowerCase():
+ self.amPM.textContent = self.l10n.amPM[0];
+ setHoursFromInputs();
+ updateValue();
+ break;
+ case self.l10n.amPM[1].charAt(0):
+ case self.l10n.amPM[1].charAt(0).toLowerCase():
+ self.amPM.textContent = self.l10n.amPM[1];
+ setHoursFromInputs();
+ updateValue();
+ break;
+ }
+ }
+ if (isInput || isCalendarElem(eventTarget)) {
+ triggerEvent("onKeyDown", e);
+ }
+ }
+ function onMouseOver(elem) {
+ if (self.selectedDates.length !== 1 ||
+ (elem &&
+ (!elem.classList.contains("flatpickr-day") ||
+ elem.classList.contains("flatpickr-disabled"))))
+ return;
+ var hoverDate = elem
+ ? elem.dateObj.getTime()
+ : self.days.firstElementChild.dateObj.getTime(), initialDate = self.parseDate(self.selectedDates[0], undefined, true).getTime(), rangeStartDate = Math.min(hoverDate, self.selectedDates[0].getTime()), rangeEndDate = Math.max(hoverDate, self.selectedDates[0].getTime());
+ var containsDisabled = false;
+ var minRange = 0, maxRange = 0;
+ for (var t = rangeStartDate; t < rangeEndDate; t += duration.DAY) {
+ if (!isEnabled(new Date(t), true)) {
+ containsDisabled =
+ containsDisabled || (t > rangeStartDate && t < rangeEndDate);
+ if (t < initialDate && (!minRange || t > minRange))
+ minRange = t;
+ else if (t > initialDate && (!maxRange || t < maxRange))
+ maxRange = t;
+ }
+ }
+ for (var m = 0; m < self.config.showMonths; m++) {
+ var month = self.daysContainer.children[m];
+ var _loop_1 = function (i, l) {
+ var dayElem = month.children[i], date = dayElem.dateObj;
+ var timestamp = date.getTime();
+ var outOfRange = (minRange > 0 && timestamp < minRange) ||
+ (maxRange > 0 && timestamp > maxRange);
+ if (outOfRange) {
+ dayElem.classList.add("notAllowed");
+ ["inRange", "startRange", "endRange"].forEach(function (c) {
+ dayElem.classList.remove(c);
+ });
+ return "continue";
+ }
+ else if (containsDisabled && !outOfRange)
+ return "continue";
+ ["startRange", "inRange", "endRange", "notAllowed"].forEach(function (c) {
+ dayElem.classList.remove(c);
+ });
+ if (elem !== undefined) {
+ elem.classList.add(hoverDate <= self.selectedDates[0].getTime()
+ ? "startRange"
+ : "endRange");
+ if (initialDate < hoverDate && timestamp === initialDate)
+ dayElem.classList.add("startRange");
+ else if (initialDate > hoverDate && timestamp === initialDate)
+ dayElem.classList.add("endRange");
+ if (timestamp >= minRange &&
+ (maxRange === 0 || timestamp <= maxRange) &&
+ isBetween(timestamp, initialDate, hoverDate))
+ dayElem.classList.add("inRange");
+ }
+ };
+ for (var i = 0, l = month.children.length; i < l; i++) {
+ _loop_1(i, l);
+ }
+ }
+ }
+ function onResize() {
+ if (self.isOpen && !self.config.static && !self.config.inline)
+ positionCalendar();
+ }
+ function open(e, positionElement) {
+ if (positionElement === void 0) { positionElement = self._positionElement; }
+ if (self.isMobile === true) {
+ if (e) {
+ e.preventDefault();
+ var eventTarget = getEventTarget(e);
+ if (eventTarget) {
+ eventTarget.blur();
+ }
+ }
+ if (self.mobileInput !== undefined) {
+ self.mobileInput.focus();
+ self.mobileInput.click();
+ }
+ triggerEvent("onOpen");
+ return;
+ }
+ else if (self._input.disabled || self.config.inline) {
+ return;
+ }
+ var wasOpen = self.isOpen;
+ self.isOpen = true;
+ if (!wasOpen) {
+ self.calendarContainer.classList.add("open");
+ self._input.classList.add("active");
+ triggerEvent("onOpen");
+ positionCalendar(positionElement);
+ }
+ if (self.config.enableTime === true && self.config.noCalendar === true) {
+ if (self.config.allowInput === false &&
+ (e === undefined ||
+ !self.timeContainer.contains(e.relatedTarget))) {
+ setTimeout(function () { return self.hourElement.select(); }, 50);
+ }
+ }
+ }
+ function minMaxDateSetter(type) {
+ return function (date) {
+ var dateObj = (self.config["_" + type + "Date"] = self.parseDate(date, self.config.dateFormat));
+ var inverseDateObj = self.config["_" + (type === "min" ? "max" : "min") + "Date"];
+ if (dateObj !== undefined) {
+ self[type === "min" ? "minDateHasTime" : "maxDateHasTime"] =
+ dateObj.getHours() > 0 ||
+ dateObj.getMinutes() > 0 ||
+ dateObj.getSeconds() > 0;
+ }
+ if (self.selectedDates) {
+ self.selectedDates = self.selectedDates.filter(function (d) { return isEnabled(d); });
+ if (!self.selectedDates.length && type === "min")
+ setHoursFromDate(dateObj);
+ updateValue();
+ }
+ if (self.daysContainer) {
+ redraw();
+ if (dateObj !== undefined)
+ self.currentYearElement[type] = dateObj.getFullYear().toString();
+ else
+ self.currentYearElement.removeAttribute(type);
+ self.currentYearElement.disabled =
+ !!inverseDateObj &&
+ dateObj !== undefined &&
+ inverseDateObj.getFullYear() === dateObj.getFullYear();
+ }
+ };
+ }
+ function parseConfig() {
+ var boolOpts = [
+ "wrap",
+ "weekNumbers",
+ "allowInput",
+ "allowInvalidPreload",
+ "clickOpens",
+ "time_24hr",
+ "enableTime",
+ "noCalendar",
+ "altInput",
+ "shorthandCurrentMonth",
+ "inline",
+ "static",
+ "enableSeconds",
+ "disableMobile",
+ ];
+ var userConfig = __assign(__assign({}, JSON.parse(JSON.stringify(element.dataset || {}))), instanceConfig);
+ var formats = {};
+ self.config.parseDate = userConfig.parseDate;
+ self.config.formatDate = userConfig.formatDate;
+ Object.defineProperty(self.config, "enable", {
+ get: function () { return self.config._enable; },
+ set: function (dates) {
+ self.config._enable = parseDateRules(dates);
+ },
+ });
+ Object.defineProperty(self.config, "disable", {
+ get: function () { return self.config._disable; },
+ set: function (dates) {
+ self.config._disable = parseDateRules(dates);
+ },
+ });
+ var timeMode = userConfig.mode === "time";
+ if (!userConfig.dateFormat && (userConfig.enableTime || timeMode)) {
+ var defaultDateFormat = flatpickr.defaultConfig.dateFormat || defaults.dateFormat;
+ formats.dateFormat =
+ userConfig.noCalendar || timeMode
+ ? "H:i" + (userConfig.enableSeconds ? ":S" : "")
+ : defaultDateFormat + " H:i" + (userConfig.enableSeconds ? ":S" : "");
+ }
+ if (userConfig.altInput &&
+ (userConfig.enableTime || timeMode) &&
+ !userConfig.altFormat) {
+ var defaultAltFormat = flatpickr.defaultConfig.altFormat || defaults.altFormat;
+ formats.altFormat =
+ userConfig.noCalendar || timeMode
+ ? "h:i" + (userConfig.enableSeconds ? ":S K" : " K")
+ : defaultAltFormat + (" h:i" + (userConfig.enableSeconds ? ":S" : "") + " K");
+ }
+ Object.defineProperty(self.config, "minDate", {
+ get: function () { return self.config._minDate; },
+ set: minMaxDateSetter("min"),
+ });
+ Object.defineProperty(self.config, "maxDate", {
+ get: function () { return self.config._maxDate; },
+ set: minMaxDateSetter("max"),
+ });
+ var minMaxTimeSetter = function (type) { return function (val) {
+ self.config[type === "min" ? "_minTime" : "_maxTime"] = self.parseDate(val, "H:i:S");
+ }; };
+ Object.defineProperty(self.config, "minTime", {
+ get: function () { return self.config._minTime; },
+ set: minMaxTimeSetter("min"),
+ });
+ Object.defineProperty(self.config, "maxTime", {
+ get: function () { return self.config._maxTime; },
+ set: minMaxTimeSetter("max"),
+ });
+ if (userConfig.mode === "time") {
+ self.config.noCalendar = true;
+ self.config.enableTime = true;
+ }
+ Object.assign(self.config, formats, userConfig);
+ for (var i = 0; i < boolOpts.length; i++)
+ // https://github.com/microsoft/TypeScript/issues/31663
+ self.config[boolOpts[i]] =
+ self.config[boolOpts[i]] === true ||
+ self.config[boolOpts[i]] === "true";
+ HOOKS.filter(function (hook) { return self.config[hook] !== undefined; }).forEach(function (hook) {
+ self.config[hook] = arrayify(self.config[hook] || []).map(bindToInstance);
+ });
+ self.isMobile =
+ !self.config.disableMobile &&
+ !self.config.inline &&
+ self.config.mode === "single" &&
+ !self.config.disable.length &&
+ !self.config.enable &&
+ !self.config.weekNumbers &&
+ /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent);
+ for (var i = 0; i < self.config.plugins.length; i++) {
+ var pluginConf = self.config.plugins[i](self) || {};
+ for (var key in pluginConf) {
+ if (HOOKS.indexOf(key) > -1) {
+ self.config[key] = arrayify(pluginConf[key])
+ .map(bindToInstance)
+ .concat(self.config[key]);
+ }
+ else if (typeof userConfig[key] === "undefined")
+ self.config[key] = pluginConf[key];
+ }
+ }
+ if (!userConfig.altInputClass) {
+ self.config.altInputClass =
+ getInputElem().className + " " + self.config.altInputClass;
+ }
+ triggerEvent("onParseConfig");
+ }
+ function getInputElem() {
+ return self.config.wrap
+ ? element.querySelector("[data-input]")
+ : element;
+ }
+ function setupLocale() {
+ if (typeof self.config.locale !== "object" &&
+ typeof flatpickr.l10ns[self.config.locale] === "undefined")
+ self.config.errorHandler(new Error("flatpickr: invalid locale " + self.config.locale));
+ self.l10n = __assign(__assign({}, flatpickr.l10ns.default), (typeof self.config.locale === "object"
+ ? self.config.locale
+ : self.config.locale !== "default"
+ ? flatpickr.l10ns[self.config.locale]
+ : undefined));
+ tokenRegex.K = "(" + self.l10n.amPM[0] + "|" + self.l10n.amPM[1] + "|" + self.l10n.amPM[0].toLowerCase() + "|" + self.l10n.amPM[1].toLowerCase() + ")";
+ var userConfig = __assign(__assign({}, instanceConfig), JSON.parse(JSON.stringify(element.dataset || {})));
+ if (userConfig.time_24hr === undefined &&
+ flatpickr.defaultConfig.time_24hr === undefined) {
+ self.config.time_24hr = self.l10n.time_24hr;
+ }
+ self.formatDate = createDateFormatter(self);
+ self.parseDate = createDateParser({ config: self.config, l10n: self.l10n });
+ }
+ function positionCalendar(customPositionElement) {
+ if (typeof self.config.position === "function") {
+ return void self.config.position(self, customPositionElement);
+ }
+ if (self.calendarContainer === undefined)
+ return;
+ triggerEvent("onPreCalendarPosition");
+ var positionElement = customPositionElement || self._positionElement;
+ var calendarHeight = Array.prototype.reduce.call(self.calendarContainer.children, (function (acc, child) { return acc + child.offsetHeight; }), 0), calendarWidth = self.calendarContainer.offsetWidth, configPos = self.config.position.split(" "), configPosVertical = configPos[0], configPosHorizontal = configPos.length > 1 ? configPos[1] : null, inputBounds = positionElement.getBoundingClientRect(), distanceFromBottom = window.innerHeight - inputBounds.bottom, showOnTop = configPosVertical === "above" ||
+ (configPosVertical !== "below" &&
+ distanceFromBottom < calendarHeight &&
+ inputBounds.top > calendarHeight);
+ var top = window.pageYOffset +
+ inputBounds.top +
+ (!showOnTop ? positionElement.offsetHeight + 2 : -calendarHeight - 2);
+ toggleClass(self.calendarContainer, "arrowTop", !showOnTop);
+ toggleClass(self.calendarContainer, "arrowBottom", showOnTop);
+ if (self.config.inline)
+ return;
+ var left = window.pageXOffset + inputBounds.left;
+ var isCenter = false;
+ var isRight = false;
+ if (configPosHorizontal === "center") {
+ left -= (calendarWidth - inputBounds.width) / 2;
+ isCenter = true;
+ }
+ else if (configPosHorizontal === "right") {
+ left -= calendarWidth - inputBounds.width;
+ isRight = true;
+ }
+ toggleClass(self.calendarContainer, "arrowLeft", !isCenter && !isRight);
+ toggleClass(self.calendarContainer, "arrowCenter", isCenter);
+ toggleClass(self.calendarContainer, "arrowRight", isRight);
+ var right = window.document.body.offsetWidth -
+ (window.pageXOffset + inputBounds.right);
+ var rightMost = left + calendarWidth > window.document.body.offsetWidth;
+ var centerMost = right + calendarWidth > window.document.body.offsetWidth;
+ toggleClass(self.calendarContainer, "rightMost", rightMost);
+ if (self.config.static)
+ return;
+ self.calendarContainer.style.top = top + "px";
+ if (!rightMost) {
+ self.calendarContainer.style.left = left + "px";
+ self.calendarContainer.style.right = "auto";
+ }
+ else if (!centerMost) {
+ self.calendarContainer.style.left = "auto";
+ self.calendarContainer.style.right = right + "px";
+ }
+ else {
+ var doc = getDocumentStyleSheet();
+ // some testing environments don't have css support
+ if (doc === undefined)
+ return;
+ var bodyWidth = window.document.body.offsetWidth;
+ var centerLeft = Math.max(0, bodyWidth / 2 - calendarWidth / 2);
+ var centerBefore = ".flatpickr-calendar.centerMost:before";
+ var centerAfter = ".flatpickr-calendar.centerMost:after";
+ var centerIndex = doc.cssRules.length;
+ var centerStyle = "{left:" + inputBounds.left + "px;right:auto;}";
+ toggleClass(self.calendarContainer, "rightMost", false);
+ toggleClass(self.calendarContainer, "centerMost", true);
+ doc.insertRule(centerBefore + "," + centerAfter + centerStyle, centerIndex);
+ self.calendarContainer.style.left = centerLeft + "px";
+ self.calendarContainer.style.right = "auto";
+ }
+ }
+ function getDocumentStyleSheet() {
+ var editableSheet = null;
+ for (var i = 0; i < document.styleSheets.length; i++) {
+ var sheet = document.styleSheets[i];
+ try {
+ sheet.cssRules;
+ }
+ catch (err) {
+ continue;
+ }
+ editableSheet = sheet;
+ break;
+ }
+ return editableSheet != null ? editableSheet : createStyleSheet();
+ }
+ function createStyleSheet() {
+ var style = document.createElement("style");
+ document.head.appendChild(style);
+ return style.sheet;
+ }
+ function redraw() {
+ if (self.config.noCalendar || self.isMobile)
+ return;
+ buildMonthSwitch();
+ updateNavigationCurrentMonth();
+ buildDays();
+ }
+ function focusAndClose() {
+ self._input.focus();
+ if (window.navigator.userAgent.indexOf("MSIE") !== -1 ||
+ navigator.msMaxTouchPoints !== undefined) {
+ // hack - bugs in the way IE handles focus keeps the calendar open
+ setTimeout(self.close, 0);
+ }
+ else {
+ self.close();
+ }
+ }
+ function selectDate(e) {
+ e.preventDefault();
+ e.stopPropagation();
+ var isSelectable = function (day) {
+ return day.classList &&
+ day.classList.contains("flatpickr-day") &&
+ !day.classList.contains("flatpickr-disabled") &&
+ !day.classList.contains("notAllowed");
+ };
+ var t = findParent(getEventTarget(e), isSelectable);
+ if (t === undefined)
+ return;
+ var target = t;
+ var selectedDate = (self.latestSelectedDateObj = new Date(target.dateObj.getTime()));
+ var shouldChangeMonth = (selectedDate.getMonth() < self.currentMonth ||
+ selectedDate.getMonth() >
+ self.currentMonth + self.config.showMonths - 1) &&
+ self.config.mode !== "range";
+ self.selectedDateElem = target;
+ if (self.config.mode === "single")
+ self.selectedDates = [selectedDate];
+ else if (self.config.mode === "multiple") {
+ var selectedIndex = isDateSelected(selectedDate);
+ if (selectedIndex)
+ self.selectedDates.splice(parseInt(selectedIndex), 1);
+ else
+ self.selectedDates.push(selectedDate);
+ }
+ else if (self.config.mode === "range") {
+ if (self.selectedDates.length === 2) {
+ self.clear(false, false);
+ }
+ self.latestSelectedDateObj = selectedDate;
+ self.selectedDates.push(selectedDate);
+ // unless selecting same date twice, sort ascendingly
+ if (compareDates(selectedDate, self.selectedDates[0], true) !== 0)
+ self.selectedDates.sort(function (a, b) { return a.getTime() - b.getTime(); });
+ }
+ setHoursFromInputs();
+ if (shouldChangeMonth) {
+ var isNewYear = self.currentYear !== selectedDate.getFullYear();
+ self.currentYear = selectedDate.getFullYear();
+ self.currentMonth = selectedDate.getMonth();
+ if (isNewYear) {
+ triggerEvent("onYearChange");
+ buildMonthSwitch();
+ }
+ triggerEvent("onMonthChange");
+ }
+ updateNavigationCurrentMonth();
+ buildDays();
+ updateValue();
+ // maintain focus
+ if (!shouldChangeMonth &&
+ self.config.mode !== "range" &&
+ self.config.showMonths === 1)
+ focusOnDayElem(target);
+ else if (self.selectedDateElem !== undefined &&
+ self.hourElement === undefined) {
+ self.selectedDateElem && self.selectedDateElem.focus();
+ }
+ if (self.hourElement !== undefined)
+ self.hourElement !== undefined && self.hourElement.focus();
+ if (self.config.closeOnSelect) {
+ var single = self.config.mode === "single" && !self.config.enableTime;
+ var range = self.config.mode === "range" &&
+ self.selectedDates.length === 2 &&
+ !self.config.enableTime;
+ if (single || range) {
+ focusAndClose();
+ }
+ }
+ triggerChange();
+ }
+ var CALLBACKS = {
+ locale: [setupLocale, updateWeekdays],
+ showMonths: [buildMonths, setCalendarWidth, buildWeekdays],
+ minDate: [jumpToDate],
+ maxDate: [jumpToDate],
+ positionElement: [updatePositionElement],
+ clickOpens: [
+ function () {
+ if (self.config.clickOpens === true) {
+ bind(self._input, "focus", self.open);
+ bind(self._input, "click", self.open);
+ }
+ else {
+ self._input.removeEventListener("focus", self.open);
+ self._input.removeEventListener("click", self.open);
+ }
+ },
+ ],
+ };
+ function set(option, value) {
+ if (option !== null && typeof option === "object") {
+ Object.assign(self.config, option);
+ for (var key in option) {
+ if (CALLBACKS[key] !== undefined)
+ CALLBACKS[key].forEach(function (x) { return x(); });
+ }
+ }
+ else {
+ self.config[option] = value;
+ if (CALLBACKS[option] !== undefined)
+ CALLBACKS[option].forEach(function (x) { return x(); });
+ else if (HOOKS.indexOf(option) > -1)
+ self.config[option] = arrayify(value);
+ }
+ self.redraw();
+ updateValue(true);
+ }
+ function setSelectedDate(inputDate, format) {
+ var dates = [];
+ if (inputDate instanceof Array)
+ dates = inputDate.map(function (d) { return self.parseDate(d, format); });
+ else if (inputDate instanceof Date || typeof inputDate === "number")
+ dates = [self.parseDate(inputDate, format)];
+ else if (typeof inputDate === "string") {
+ switch (self.config.mode) {
+ case "single":
+ case "time":
+ dates = [self.parseDate(inputDate, format)];
+ break;
+ case "multiple":
+ dates = inputDate
+ .split(self.config.conjunction)
+ .map(function (date) { return self.parseDate(date, format); });
+ break;
+ case "range":
+ dates = inputDate
+ .split(self.l10n.rangeSeparator)
+ .map(function (date) { return self.parseDate(date, format); });
+ break;
+ }
+ }
+ else
+ self.config.errorHandler(new Error("Invalid date supplied: " + JSON.stringify(inputDate)));
+ self.selectedDates = (self.config.allowInvalidPreload
+ ? dates
+ : dates.filter(function (d) { return d instanceof Date && isEnabled(d, false); }));
+ if (self.config.mode === "range")
+ self.selectedDates.sort(function (a, b) { return a.getTime() - b.getTime(); });
+ }
+ function setDate(date, triggerChange, format) {
+ if (triggerChange === void 0) { triggerChange = false; }
+ if (format === void 0) { format = self.config.dateFormat; }
+ if ((date !== 0 && !date) || (date instanceof Array && date.length === 0))
+ return self.clear(triggerChange);
+ setSelectedDate(date, format);
+ self.latestSelectedDateObj =
+ self.selectedDates[self.selectedDates.length - 1];
+ self.redraw();
+ jumpToDate(undefined, triggerChange);
+ setHoursFromDate();
+ if (self.selectedDates.length === 0) {
+ self.clear(false);
+ }
+ updateValue(triggerChange);
+ if (triggerChange)
+ triggerEvent("onChange");
+ }
+ function parseDateRules(arr) {
+ return arr
+ .slice()
+ .map(function (rule) {
+ if (typeof rule === "string" ||
+ typeof rule === "number" ||
+ rule instanceof Date) {
+ return self.parseDate(rule, undefined, true);
+ }
+ else if (rule &&
+ typeof rule === "object" &&
+ rule.from &&
+ rule.to)
+ return {
+ from: self.parseDate(rule.from, undefined),
+ to: self.parseDate(rule.to, undefined),
+ };
+ return rule;
+ })
+ .filter(function (x) { return x; }); // remove falsy values
+ }
+ function setupDates() {
+ self.selectedDates = [];
+ self.now = self.parseDate(self.config.now) || new Date();
+ // Workaround IE11 setting placeholder as the input's value
+ var preloadedDate = self.config.defaultDate ||
+ ((self.input.nodeName === "INPUT" ||
+ self.input.nodeName === "TEXTAREA") &&
+ self.input.placeholder &&
+ self.input.value === self.input.placeholder
+ ? null
+ : self.input.value);
+ if (preloadedDate)
+ setSelectedDate(preloadedDate, self.config.dateFormat);
+ self._initialDate =
+ self.selectedDates.length > 0
+ ? self.selectedDates[0]
+ : self.config.minDate &&
+ self.config.minDate.getTime() > self.now.getTime()
+ ? self.config.minDate
+ : self.config.maxDate &&
+ self.config.maxDate.getTime() < self.now.getTime()
+ ? self.config.maxDate
+ : self.now;
+ self.currentYear = self._initialDate.getFullYear();
+ self.currentMonth = self._initialDate.getMonth();
+ if (self.selectedDates.length > 0)
+ self.latestSelectedDateObj = self.selectedDates[0];
+ if (self.config.minTime !== undefined)
+ self.config.minTime = self.parseDate(self.config.minTime, "H:i");
+ if (self.config.maxTime !== undefined)
+ self.config.maxTime = self.parseDate(self.config.maxTime, "H:i");
+ self.minDateHasTime =
+ !!self.config.minDate &&
+ (self.config.minDate.getHours() > 0 ||
+ self.config.minDate.getMinutes() > 0 ||
+ self.config.minDate.getSeconds() > 0);
+ self.maxDateHasTime =
+ !!self.config.maxDate &&
+ (self.config.maxDate.getHours() > 0 ||
+ self.config.maxDate.getMinutes() > 0 ||
+ self.config.maxDate.getSeconds() > 0);
+ }
+ function setupInputs() {
+ self.input = getInputElem();
+ /* istanbul ignore next */
+ if (!self.input) {
+ self.config.errorHandler(new Error("Invalid input element specified"));
+ return;
+ }
+ // hack: store previous type to restore it after destroy()
+ self.input._type = self.input.type;
+ self.input.type = "text";
+ self.input.classList.add("flatpickr-input");
+ self._input = self.input;
+ if (self.config.altInput) {
+ // replicate self.element
+ self.altInput = createElement(self.input.nodeName, self.config.altInputClass);
+ self._input = self.altInput;
+ self.altInput.placeholder = self.input.placeholder;
+ self.altInput.disabled = self.input.disabled;
+ self.altInput.required = self.input.required;
+ self.altInput.tabIndex = self.input.tabIndex;
+ self.altInput.type = "text";
+ self.input.setAttribute("type", "hidden");
+ if (!self.config.static && self.input.parentNode)
+ self.input.parentNode.insertBefore(self.altInput, self.input.nextSibling);
+ }
+ if (!self.config.allowInput)
+ self._input.setAttribute("readonly", "readonly");
+ updatePositionElement();
+ }
+ function updatePositionElement() {
+ self._positionElement = self.config.positionElement || self._input;
+ }
+ function setupMobile() {
+ var inputType = self.config.enableTime
+ ? self.config.noCalendar
+ ? "time"
+ : "datetime-local"
+ : "date";
+ self.mobileInput = createElement("input", self.input.className + " flatpickr-mobile");
+ self.mobileInput.tabIndex = 1;
+ self.mobileInput.type = inputType;
+ self.mobileInput.disabled = self.input.disabled;
+ self.mobileInput.required = self.input.required;
+ self.mobileInput.placeholder = self.input.placeholder;
+ self.mobileFormatStr =
+ inputType === "datetime-local"
+ ? "Y-m-d\\TH:i:S"
+ : inputType === "date"
+ ? "Y-m-d"
+ : "H:i:S";
+ if (self.selectedDates.length > 0) {
+ self.mobileInput.defaultValue = self.mobileInput.value = self.formatDate(self.selectedDates[0], self.mobileFormatStr);
+ }
+ if (self.config.minDate)
+ self.mobileInput.min = self.formatDate(self.config.minDate, "Y-m-d");
+ if (self.config.maxDate)
+ self.mobileInput.max = self.formatDate(self.config.maxDate, "Y-m-d");
+ if (self.input.getAttribute("step"))
+ self.mobileInput.step = String(self.input.getAttribute("step"));
+ self.input.type = "hidden";
+ if (self.altInput !== undefined)
+ self.altInput.type = "hidden";
+ try {
+ if (self.input.parentNode)
+ self.input.parentNode.insertBefore(self.mobileInput, self.input.nextSibling);
+ }
+ catch (_a) { }
+ bind(self.mobileInput, "change", function (e) {
+ self.setDate(getEventTarget(e).value, false, self.mobileFormatStr);
+ triggerEvent("onChange");
+ triggerEvent("onClose");
+ });
+ }
+ function toggle(e) {
+ if (self.isOpen === true)
+ return self.close();
+ self.open(e);
+ }
+ function triggerEvent(event, data) {
+ // If the instance has been destroyed already, all hooks have been removed
+ if (self.config === undefined)
+ return;
+ var hooks = self.config[event];
+ if (hooks !== undefined && hooks.length > 0) {
+ for (var i = 0; hooks[i] && i < hooks.length; i++)
+ hooks[i](self.selectedDates, self.input.value, self, data);
+ }
+ if (event === "onChange") {
+ self.input.dispatchEvent(createEvent("change"));
+ // many front-end frameworks bind to the input event
+ self.input.dispatchEvent(createEvent("input"));
+ }
+ }
+ function createEvent(name) {
+ var e = document.createEvent("Event");
+ e.initEvent(name, true, true);
+ return e;
+ }
+ function isDateSelected(date) {
+ for (var i = 0; i < self.selectedDates.length; i++) {
+ if (compareDates(self.selectedDates[i], date) === 0)
+ return "" + i;
+ }
+ return false;
+ }
+ function isDateInRange(date) {
+ if (self.config.mode !== "range" || self.selectedDates.length < 2)
+ return false;
+ return (compareDates(date, self.selectedDates[0]) >= 0 &&
+ compareDates(date, self.selectedDates[1]) <= 0);
+ }
+ function updateNavigationCurrentMonth() {
+ if (self.config.noCalendar || self.isMobile || !self.monthNav)
+ return;
+ self.yearElements.forEach(function (yearElement, i) {
+ var d = new Date(self.currentYear, self.currentMonth, 1);
+ d.setMonth(self.currentMonth + i);
+ if (self.config.showMonths > 1 ||
+ self.config.monthSelectorType === "static") {
+ self.monthElements[i].textContent =
+ monthToStr(d.getMonth(), self.config.shorthandCurrentMonth, self.l10n) + " ";
+ }
+ else {
+ self.monthsDropdownContainer.value = d.getMonth().toString();
+ }
+ yearElement.value = d.getFullYear().toString();
+ });
+ self._hidePrevMonthArrow =
+ self.config.minDate !== undefined &&
+ (self.currentYear === self.config.minDate.getFullYear()
+ ? self.currentMonth <= self.config.minDate.getMonth()
+ : self.currentYear < self.config.minDate.getFullYear());
+ self._hideNextMonthArrow =
+ self.config.maxDate !== undefined &&
+ (self.currentYear === self.config.maxDate.getFullYear()
+ ? self.currentMonth + 1 > self.config.maxDate.getMonth()
+ : self.currentYear > self.config.maxDate.getFullYear());
+ }
+ function getDateStr(format) {
+ return self.selectedDates
+ .map(function (dObj) { return self.formatDate(dObj, format); })
+ .filter(function (d, i, arr) {
+ return self.config.mode !== "range" ||
+ self.config.enableTime ||
+ arr.indexOf(d) === i;
+ })
+ .join(self.config.mode !== "range"
+ ? self.config.conjunction
+ : self.l10n.rangeSeparator);
+ }
+ /**
+ * Updates the values of inputs associated with the calendar
+ */
+ function updateValue(triggerChange) {
+ if (triggerChange === void 0) { triggerChange = true; }
+ if (self.mobileInput !== undefined && self.mobileFormatStr) {
+ self.mobileInput.value =
+ self.latestSelectedDateObj !== undefined
+ ? self.formatDate(self.latestSelectedDateObj, self.mobileFormatStr)
+ : "";
+ }
+ self.input.value = getDateStr(self.config.dateFormat);
+ if (self.altInput !== undefined) {
+ self.altInput.value = getDateStr(self.config.altFormat);
+ }
+ if (triggerChange !== false)
+ triggerEvent("onValueUpdate");
+ }
+ function onMonthNavClick(e) {
+ var eventTarget = getEventTarget(e);
+ var isPrevMonth = self.prevMonthNav.contains(eventTarget);
+ var isNextMonth = self.nextMonthNav.contains(eventTarget);
+ if (isPrevMonth || isNextMonth) {
+ changeMonth(isPrevMonth ? -1 : 1);
+ }
+ else if (self.yearElements.indexOf(eventTarget) >= 0) {
+ eventTarget.select();
+ }
+ else if (eventTarget.classList.contains("arrowUp")) {
+ self.changeYear(self.currentYear + 1);
+ }
+ else if (eventTarget.classList.contains("arrowDown")) {
+ self.changeYear(self.currentYear - 1);
+ }
+ }
+ function timeWrapper(e) {
+ e.preventDefault();
+ var isKeyDown = e.type === "keydown", eventTarget = getEventTarget(e), input = eventTarget;
+ if (self.amPM !== undefined && eventTarget === self.amPM) {
+ self.amPM.textContent =
+ self.l10n.amPM[int(self.amPM.textContent === self.l10n.amPM[0])];
+ }
+ var min = parseFloat(input.getAttribute("min")), max = parseFloat(input.getAttribute("max")), step = parseFloat(input.getAttribute("step")), curValue = parseInt(input.value, 10), delta = e.delta ||
+ (isKeyDown ? (e.which === 38 ? 1 : -1) : 0);
+ var newValue = curValue + step * delta;
+ if (typeof input.value !== "undefined" && input.value.length === 2) {
+ var isHourElem = input === self.hourElement, isMinuteElem = input === self.minuteElement;
+ if (newValue < min) {
+ newValue =
+ max +
+ newValue +
+ int(!isHourElem) +
+ (int(isHourElem) && int(!self.amPM));
+ if (isMinuteElem)
+ incrementNumInput(undefined, -1, self.hourElement);
+ }
+ else if (newValue > max) {
+ newValue =
+ input === self.hourElement ? newValue - max - int(!self.amPM) : min;
+ if (isMinuteElem)
+ incrementNumInput(undefined, 1, self.hourElement);
+ }
+ if (self.amPM &&
+ isHourElem &&
+ (step === 1
+ ? newValue + curValue === 23
+ : Math.abs(newValue - curValue) > step)) {
+ self.amPM.textContent =
+ self.l10n.amPM[int(self.amPM.textContent === self.l10n.amPM[0])];
+ }
+ input.value = pad(newValue);
+ }
+ }
+ init();
+ return self;
+ }
+ /* istanbul ignore next */
+ function _flatpickr(nodeList, config) {
+ // static list
+ var nodes = Array.prototype.slice
+ .call(nodeList)
+ .filter(function (x) { return x instanceof HTMLElement; });
+ var instances = [];
+ for (var i = 0; i < nodes.length; i++) {
+ var node = nodes[i];
+ try {
+ if (node.getAttribute("data-fp-omit") !== null)
+ continue;
+ if (node._flatpickr !== undefined) {
+ node._flatpickr.destroy();
+ node._flatpickr = undefined;
+ }
+ node._flatpickr = FlatpickrInstance(node, config || {});
+ instances.push(node._flatpickr);
+ }
+ catch (e) {
+ console.error(e);
+ }
+ }
+ return instances.length === 1 ? instances[0] : instances;
+ }
+ /* istanbul ignore next */
+ if (typeof HTMLElement !== "undefined" &&
+ typeof HTMLCollection !== "undefined" &&
+ typeof NodeList !== "undefined") {
+ // browser env
+ HTMLCollection.prototype.flatpickr = NodeList.prototype.flatpickr = function (config) {
+ return _flatpickr(this, config);
+ };
+ HTMLElement.prototype.flatpickr = function (config) {
+ return _flatpickr([this], config);
+ };
+ }
+ /* istanbul ignore next */
+ var flatpickr = function (selector, config) {
+ if (typeof selector === "string") {
+ return _flatpickr(window.document.querySelectorAll(selector), config);
+ }
+ else if (selector instanceof Node) {
+ return _flatpickr([selector], config);
+ }
+ else {
+ return _flatpickr(selector, config);
+ }
+ };
+ /* istanbul ignore next */
+ flatpickr.defaultConfig = {};
+ flatpickr.l10ns = {
+ en: __assign({}, english),
+ default: __assign({}, english),
+ };
+ flatpickr.localize = function (l10n) {
+ flatpickr.l10ns.default = __assign(__assign({}, flatpickr.l10ns.default), l10n);
+ };
+ flatpickr.setDefaults = function (config) {
+ flatpickr.defaultConfig = __assign(__assign({}, flatpickr.defaultConfig), config);
+ };
+ flatpickr.parseDate = createDateParser({});
+ flatpickr.formatDate = createDateFormatter({});
+ flatpickr.compareDates = compareDates;
+ /* istanbul ignore next */
+ if (typeof jQuery !== "undefined" && typeof jQuery.fn !== "undefined") {
+ jQuery.fn.flatpickr = function (config) {
+ return _flatpickr(this, config);
+ };
+ }
+ Date.prototype.fp_incr = function (days) {
+ return new Date(this.getFullYear(), this.getMonth(), this.getDate() + (typeof days === "string" ? parseInt(days, 10) : days));
+ };
+ if (typeof window !== "undefined") {
+ window.flatpickr = flatpickr;
+ }
+
+ return flatpickr;
+
+})));
diff --git a/asset/js/vendor/flatpickr.min.js b/asset/js/vendor/flatpickr.min.js
new file mode 100644
index 0000000..286f1de
--- /dev/null
+++ b/asset/js/vendor/flatpickr.min.js
@@ -0,0 +1,2 @@
+/* flatpickr v4.6.9,, @license MIT */
+!function(e,n){"object"==typeof exports&&"undefined"!=typeof module?module.exports=n():"function"==typeof define&&define.icinga?define(n):(e="undefined"!=typeof globalThis?globalThis:e||self).flatpickr=n()}(this,(function(){"use strict";var e=function(){return(e=Object.assign||function(e){for(var n,t=1,a=arguments.length;t<a;t++)for(var i in n=arguments[t])Object.prototype.hasOwnProperty.call(n,i)&&(e[i]=n[i]);return e}).apply(this,arguments)};function n(){for(var e=0,n=0,t=arguments.length;n<t;n++)e+=arguments[n].length;var a=Array(e),i=0;for(n=0;n<t;n++)for(var o=arguments[n],r=0,l=o.length;r<l;r++,i++)a[i]=o[r];return a}var t=["onChange","onClose","onDayCreate","onDestroy","onKeyDown","onMonthChange","onOpen","onParseConfig","onReady","onValueUpdate","onYearChange","onPreCalendarPosition"],a={_disable:[],allowInput:!1,allowInvalidPreload:!1,altFormat:"F j, Y",altInput:!1,altInputClass:"form-control input",animate:"object"==typeof window&&-1===window.navigator.userAgent.indexOf("MSIE"),ariaDateFormat:"F j, Y",autoFillDefaultTime:!0,clickOpens:!0,closeOnSelect:!0,conjunction:", ",dateFormat:"Y-m-d",defaultHour:12,defaultMinute:0,defaultSeconds:0,disable:[],disableMobile:!1,enableSeconds:!1,enableTime:!1,errorHandler:function(e){return"undefined"!=typeof console&&console.warn(e)},getWeek:function(e){var n=new Date(e.getTime());n.setHours(0,0,0,0),n.setDate(n.getDate()+3-(n.getDay()+6)%7);var t=new Date(n.getFullYear(),0,4);return 1+Math.round(((n.getTime()-t.getTime())/864e5-3+(t.getDay()+6)%7)/7)},hourIncrement:1,ignoredFocusElements:[],inline:!1,locale:"default",minuteIncrement:5,mode:"single",monthSelectorType:"dropdown",nextArrow:"<svg version='1.1' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink' viewBox='0 0 17 17'><g></g><path d='M13.207 8.472l-7.854 7.854-0.707-0.707 7.146-7.146-7.146-7.148 0.707-0.707 7.854 7.854z' /></svg>",noCalendar:!1,now:new Date,onChange:[],onClose:[],onDayCreate:[],onDestroy:[],onKeyDown:[],onMonthChange:[],onOpen:[],onParseConfig:[],onReady:[],onValueUpdate:[],onYearChange:[],onPreCalendarPosition:[],plugins:[],position:"auto",positionElement:void 0,prevArrow:"<svg version='1.1' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink' viewBox='0 0 17 17'><g></g><path d='M5.207 8.471l7.146 7.147-0.707 0.707-7.853-7.854 7.854-7.853 0.707 0.707-7.147 7.146z' /></svg>",shorthandCurrentMonth:!1,showMonths:1,static:!1,time_24hr:!1,weekNumbers:!1,wrap:!1},i={weekdays:{shorthand:["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],longhand:["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"]},months:{shorthand:["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"],longhand:["January","February","March","April","May","June","July","August","September","October","November","December"]},daysInMonth:[31,28,31,30,31,30,31,31,30,31,30,31],firstDayOfWeek:0,ordinal:function(e){var n=e%100;if(n>3&&n<21)return"th";switch(n%10){case 1:return"st";case 2:return"nd";case 3:return"rd";default:return"th"}},rangeSeparator:" to ",weekAbbreviation:"Wk",scrollTitle:"Scroll to increment",toggleTitle:"Click to toggle",amPM:["AM","PM"],yearAriaLabel:"Year",monthAriaLabel:"Month",hourAriaLabel:"Hour",minuteAriaLabel:"Minute",time_24hr:!1},o=function(e,n){return void 0===n&&(n=2),("000"+e).slice(-1*n)},r=function(e){return!0===e?1:0};function l(e,n){var t;return function(){var a=this,i=arguments;clearTimeout(t),t=setTimeout((function(){return e.apply(a,i)}),n)}}var c=function(e){return e instanceof Array?e:[e]};function s(e,n,t){if(!0===t)return e.classList.add(n);e.classList.remove(n)}function d(e,n,t){var a=window.document.createElement(e);return n=n||"",t=t||"",a.className=n,void 0!==t&&(a.textContent=t),a}function u(e){for(;e.firstChild;)e.removeChild(e.firstChild)}function f(e,n){return n(e)?e:e.parentNode?f(e.parentNode,n):void 0}function m(e,n){var t=d("div","numInputWrapper"),a=d("input","numInput "+e),i=d("span","arrowUp"),o=d("span","arrowDown");if(-1===navigator.userAgent.indexOf("MSIE 9.0")?a.type="number":(a.type="text",a.pattern="\\d*"),void 0!==n)for(var r in n)a.setAttribute(r,n[r]);return t.appendChild(a),t.appendChild(i),t.appendChild(o),t}function g(e){try{return"function"==typeof e.composedPath?e.composedPath()[0]:e.target}catch(n){return e.target}}var p=function(){},h=function(e,n,t){return t.months[n?"shorthand":"longhand"][e]},v={D:p,F:function(e,n,t){e.setMonth(t.months.longhand.indexOf(n))},G:function(e,n){e.setHours(parseFloat(n))},H:function(e,n){e.setHours(parseFloat(n))},J:function(e,n){e.setDate(parseFloat(n))},K:function(e,n,t){e.setHours(e.getHours()%12+12*r(new RegExp(t.amPM[1],"i").test(n)))},M:function(e,n,t){e.setMonth(t.months.shorthand.indexOf(n))},S:function(e,n){e.setSeconds(parseFloat(n))},U:function(e,n){return new Date(1e3*parseFloat(n))},W:function(e,n,t){var a=parseInt(n),i=new Date(e.getFullYear(),0,2+7*(a-1),0,0,0,0);return i.setDate(i.getDate()-i.getDay()+t.firstDayOfWeek),i},Y:function(e,n){e.setFullYear(parseFloat(n))},Z:function(e,n){return new Date(n)},d:function(e,n){e.setDate(parseFloat(n))},h:function(e,n){e.setHours(parseFloat(n))},i:function(e,n){e.setMinutes(parseFloat(n))},j:function(e,n){e.setDate(parseFloat(n))},l:p,m:function(e,n){e.setMonth(parseFloat(n)-1)},n:function(e,n){e.setMonth(parseFloat(n)-1)},s:function(e,n){e.setSeconds(parseFloat(n))},u:function(e,n){return new Date(parseFloat(n))},w:p,y:function(e,n){e.setFullYear(2e3+parseFloat(n))}},D={D:"(\\w+)",F:"(\\w+)",G:"(\\d\\d|\\d)",H:"(\\d\\d|\\d)",J:"(\\d\\d|\\d)\\w+",K:"",M:"(\\w+)",S:"(\\d\\d|\\d)",U:"(.+)",W:"(\\d\\d|\\d)",Y:"(\\d{4})",Z:"(.+)",d:"(\\d\\d|\\d)",h:"(\\d\\d|\\d)",i:"(\\d\\d|\\d)",j:"(\\d\\d|\\d)",l:"(\\w+)",m:"(\\d\\d|\\d)",n:"(\\d\\d|\\d)",s:"(\\d\\d|\\d)",u:"(.+)",w:"(\\d\\d|\\d)",y:"(\\d{2})"},w={Z:function(e){return e.toISOString()},D:function(e,n,t){return n.weekdays.shorthand[w.w(e,n,t)]},F:function(e,n,t){return h(w.n(e,n,t)-1,!1,n)},G:function(e,n,t){return o(w.h(e,n,t))},H:function(e){return o(e.getHours())},J:function(e,n){return void 0!==n.ordinal?e.getDate()+n.ordinal(e.getDate()):e.getDate()},K:function(e,n){return n.amPM[r(e.getHours()>11)]},M:function(e,n){return h(e.getMonth(),!0,n)},S:function(e){return o(e.getSeconds())},U:function(e){return e.getTime()/1e3},W:function(e,n,t){return t.getWeek(e)},Y:function(e){return o(e.getFullYear(),4)},d:function(e){return o(e.getDate())},h:function(e){return e.getHours()%12?e.getHours()%12:12},i:function(e){return o(e.getMinutes())},j:function(e){return e.getDate()},l:function(e,n){return n.weekdays.longhand[e.getDay()]},m:function(e){return o(e.getMonth()+1)},n:function(e){return e.getMonth()+1},s:function(e){return e.getSeconds()},u:function(e){return e.getTime()},w:function(e){return e.getDay()},y:function(e){return String(e.getFullYear()).substring(2)}},b=function(e){var n=e.config,t=void 0===n?a:n,o=e.l10n,r=void 0===o?i:o,l=e.isMobile,c=void 0!==l&&l;return function(e,n,a){var i=a||r;return void 0===t.formatDate||c?n.split("").map((function(n,a,o){return w[n]&&"\\"!==o[a-1]?w[n](e,i,t):"\\"!==n?n:""})).join(""):t.formatDate(e,n,i)}},C=function(e){var n=e.config,t=void 0===n?a:n,o=e.l10n,r=void 0===o?i:o;return function(e,n,i,o){if(0===e||e){var l,c=o||r,s=e;if(e instanceof Date)l=new Date(e.getTime());else if("string"!=typeof e&&void 0!==e.toFixed)l=new Date(e);else if("string"==typeof e){var d=n||(t||a).dateFormat,u=String(e).trim();if("today"===u)l=new Date,i=!0;else if(t&&t.parseDate)l=t.parseDate(e,d);else if(/Z$/.test(u)||/GMT$/.test(u))l=new Date(e);else{for(var f=void 0,m=[],g=0,p=0,h="";g<d.length;g++){var w=d[g],b="\\"===w,C="\\"===d[g-1]||b;if(D[w]&&!C){h+=D[w];var M=new RegExp(h).exec(e);M&&(f=!0)&&m["Y"!==w?"push":"unshift"]({fn:v[w],val:M[++p]})}else b||(h+=".")}l=t&&t.noCalendar?new Date((new Date).setHours(0,0,0,0)):new Date((new Date).getFullYear(),0,1,0,0,0,0),m.forEach((function(e){var n=e.fn,t=e.val;return l=n(l,t,c)||l})),l=f?l:void 0}}if(l instanceof Date&&!isNaN(l.getTime()))return!0===i&&l.setHours(0,0,0,0),l;t.errorHandler(new Error("Invalid date provided: "+s))}}};function M(e,n,t){return void 0===t&&(t=!0),!1!==t?new Date(e.getTime()).setHours(0,0,0,0)-new Date(n.getTime()).setHours(0,0,0,0):e.getTime()-n.getTime()}var y=function(e,n,t){return 3600*e+60*n+t},x=864e5;function E(e){var n=e.defaultHour,t=e.defaultMinute,a=e.defaultSeconds;if(void 0!==e.minDate){var i=e.minDate.getHours(),o=e.minDate.getMinutes(),r=e.minDate.getSeconds();n<i&&(n=i),n===i&&t<o&&(t=o),n===i&&t===o&&a<r&&(a=e.minDate.getSeconds())}if(void 0!==e.maxDate){var l=e.maxDate.getHours(),c=e.maxDate.getMinutes();(n=Math.min(n,l))===l&&(t=Math.min(c,t)),n===l&&t===c&&(a=e.maxDate.getSeconds())}return{hours:n,minutes:t,seconds:a}}"function"!=typeof Object.assign&&(Object.assign=function(e){for(var n=[],t=1;t<arguments.length;t++)n[t-1]=arguments[t];if(!e)throw TypeError("Cannot convert undefined or null to object");for(var a=function(n){n&&Object.keys(n).forEach((function(t){return e[t]=n[t]}))},i=0,o=n;i<o.length;i++){var r=o[i];a(r)}return e});function T(p,v){var w={config:e(e({},a),S.defaultConfig),l10n:i};function T(e){return e.bind(w)}function k(){var e=w.config;!1===e.weekNumbers&&1===e.showMonths||!0!==e.noCalendar&&window.requestAnimationFrame((function(){if(void 0!==w.calendarContainer&&(w.calendarContainer.style.visibility="hidden",w.calendarContainer.style.display="block"),void 0!==w.daysContainer){var n=(w.days.offsetWidth+1)*e.showMonths;w.daysContainer.style.width=n+"px",w.calendarContainer.style.width=n+(void 0!==w.weekWrapper?w.weekWrapper.offsetWidth:0)+"px",w.calendarContainer.style.removeProperty("visibility"),w.calendarContainer.style.removeProperty("display")}}))}function I(e){if(0===w.selectedDates.length){var n=void 0===w.config.minDate||M(new Date,w.config.minDate)>=0?new Date:new Date(w.config.minDate.getTime()),t=E(w.config);n.setHours(t.hours,t.minutes,t.seconds,n.getMilliseconds()),w.selectedDates=[n],w.latestSelectedDateObj=n}void 0!==e&&"blur"!==e.type&&function(e){e.preventDefault();var n="keydown"===e.type,t=g(e),a=t;void 0!==w.amPM&&t===w.amPM&&(w.amPM.textContent=w.l10n.amPM[r(w.amPM.textContent===w.l10n.amPM[0])]);var i=parseFloat(a.getAttribute("min")),l=parseFloat(a.getAttribute("max")),c=parseFloat(a.getAttribute("step")),s=parseInt(a.value,10),d=e.delta||(n?38===e.which?1:-1:0),u=s+c*d;if(void 0!==a.value&&2===a.value.length){var f=a===w.hourElement,m=a===w.minuteElement;u<i?(u=l+u+r(!f)+(r(f)&&r(!w.amPM)),m&&j(void 0,-1,w.hourElement)):u>l&&(u=a===w.hourElement?u-l-r(!w.amPM):i,m&&j(void 0,1,w.hourElement)),w.amPM&&f&&(1===c?u+s===23:Math.abs(u-s)>c)&&(w.amPM.textContent=w.l10n.amPM[r(w.amPM.textContent===w.l10n.amPM[0])]),a.value=o(u)}}(e);var a=w._input.value;_(),Me(),w._input.value!==a&&w._debouncedChange()}function _(){if(void 0!==w.hourElement&&void 0!==w.minuteElement){var e,n,t=(parseInt(w.hourElement.value.slice(-2),10)||0)%24,a=(parseInt(w.minuteElement.value,10)||0)%60,i=void 0!==w.secondElement?(parseInt(w.secondElement.value,10)||0)%60:0;void 0!==w.amPM&&(e=t,n=w.amPM.textContent,t=e%12+12*r(n===w.l10n.amPM[1]));var o=void 0!==w.config.minTime||w.config.minDate&&w.minDateHasTime&&w.latestSelectedDateObj&&0===M(w.latestSelectedDateObj,w.config.minDate,!0),l=void 0!==w.config.maxTime||w.config.maxDate&&w.maxDateHasTime&&w.latestSelectedDateObj&&0===M(w.latestSelectedDateObj,w.config.maxDate,!0);if(void 0!==w.config.maxTime&&void 0!==w.config.minTime&&w.config.minTime>w.config.maxTime){var c=y(w.config.minTime.getHours(),w.config.minTime.getMinutes(),w.config.minTime.getSeconds()),s=y(w.config.maxTime.getHours(),w.config.maxTime.getMinutes(),w.config.maxTime.getSeconds()),d=y(t,a,i);if(d>s&&d<c){var u=function(e){var n=Math.floor(e/3600),t=(e-3600*n)/60;return[n,t,e-3600*n-60*t]}(c);t=u[0],a=u[1],i=u[2]}}else{if(l){var f=void 0!==w.config.maxTime?w.config.maxTime:w.config.maxDate;(t=Math.min(t,f.getHours()))===f.getHours()&&(a=Math.min(a,f.getMinutes())),a===f.getMinutes()&&(i=Math.min(i,f.getSeconds()))}if(o){var m=void 0!==w.config.minTime?w.config.minTime:w.config.minDate;(t=Math.max(t,m.getHours()))===m.getHours()&&a<m.getMinutes()&&(a=m.getMinutes()),a===m.getMinutes()&&(i=Math.max(i,m.getSeconds()))}}F(t,a,i)}}function O(e){var n=e||w.latestSelectedDateObj;n&&F(n.getHours(),n.getMinutes(),n.getSeconds())}function F(e,n,t){void 0!==w.latestSelectedDateObj&&w.latestSelectedDateObj.setHours(e%24,n,t||0,0),w.hourElement&&w.minuteElement&&!w.isMobile&&(w.hourElement.value=o(w.config.time_24hr?e:(12+e)%12+12*r(e%12==0)),w.minuteElement.value=o(n),void 0!==w.amPM&&(w.amPM.textContent=w.l10n.amPM[r(e>=12)]),void 0!==w.secondElement&&(w.secondElement.value=o(t)))}function A(e){var n=g(e),t=parseInt(n.value)+(e.delta||0);(t/1e3>1||"Enter"===e.key&&!/[^\d]/.test(t.toString()))&&X(t)}function N(e,n,t,a){return n instanceof Array?n.forEach((function(n){return N(e,n,t,a)})):e instanceof Array?e.forEach((function(e){return N(e,n,t,a)})):(e.addEventListener(n,t,a),void w._handlers.push({remove:function(){return e.removeEventListener(n,t)}}))}function P(){ve("onChange")}function Y(e,n){var t=void 0!==e?w.parseDate(e):w.latestSelectedDateObj||(w.config.minDate&&w.config.minDate>w.now?w.config.minDate:w.config.maxDate&&w.config.maxDate<w.now?w.config.maxDate:w.now),a=w.currentYear,i=w.currentMonth;try{void 0!==t&&(w.currentYear=t.getFullYear(),w.currentMonth=t.getMonth())}catch(e){e.message="Invalid date supplied: "+t,w.config.errorHandler(e)}n&&w.currentYear!==a&&(ve("onYearChange"),U()),!n||w.currentYear===a&&w.currentMonth===i||ve("onMonthChange"),w.redraw()}function H(e){var n=g(e);~n.className.indexOf("arrow")&&j(e,n.classList.contains("arrowUp")?1:-1)}function j(e,n,t){var a=e&&g(e),i=t||a&&a.parentNode&&a.parentNode.firstChild,o=De("increment");o.delta=n,i&&i.dispatchEvent(o)}function L(e,n,t,a){var i=ee(n,!0),o=d("span","flatpickr-day "+e,n.getDate().toString());return o.dateObj=n,o.$i=a,o.setAttribute("aria-label",w.formatDate(n,w.config.ariaDateFormat)),-1===e.indexOf("hidden")&&0===M(n,w.now)&&(w.todayDateElem=o,o.classList.add("today"),o.setAttribute("aria-current","date")),i?(o.tabIndex=-1,we(n)&&(o.classList.add("selected"),w.selectedDateElem=o,"range"===w.config.mode&&(s(o,"startRange",w.selectedDates[0]&&0===M(n,w.selectedDates[0],!0)),s(o,"endRange",w.selectedDates[1]&&0===M(n,w.selectedDates[1],!0)),"nextMonthDay"===e&&o.classList.add("inRange")))):o.classList.add("flatpickr-disabled"),"range"===w.config.mode&&function(e){return!("range"!==w.config.mode||w.selectedDates.length<2)&&(M(e,w.selectedDates[0])>=0&&M(e,w.selectedDates[1])<=0)}(n)&&!we(n)&&o.classList.add("inRange"),w.weekNumbers&&1===w.config.showMonths&&"prevMonthDay"!==e&&t%7==1&&w.weekNumbers.insertAdjacentHTML("beforeend","<span class='flatpickr-day'>"+w.config.getWeek(n)+"</span>"),ve("onDayCreate",o),o}function W(e){e.focus(),"range"===w.config.mode&&ie(e)}function R(e){for(var n=e>0?0:w.config.showMonths-1,t=e>0?w.config.showMonths:-1,a=n;a!=t;a+=e)for(var i=w.daysContainer.children[a],o=e>0?0:i.children.length-1,r=e>0?i.children.length:-1,l=o;l!=r;l+=e){var c=i.children[l];if(-1===c.className.indexOf("hidden")&&ee(c.dateObj))return c}}function B(e,n){var t=ne(document.activeElement||document.body),a=void 0!==e?e:t?document.activeElement:void 0!==w.selectedDateElem&&ne(w.selectedDateElem)?w.selectedDateElem:void 0!==w.todayDateElem&&ne(w.todayDateElem)?w.todayDateElem:R(n>0?1:-1);void 0===a?w._input.focus():t?function(e,n){for(var t=-1===e.className.indexOf("Month")?e.dateObj.getMonth():w.currentMonth,a=n>0?w.config.showMonths:-1,i=n>0?1:-1,o=t-w.currentMonth;o!=a;o+=i)for(var r=w.daysContainer.children[o],l=t-w.currentMonth===o?e.$i+n:n<0?r.children.length-1:0,c=r.children.length,s=l;s>=0&&s<c&&s!=(n>0?c:-1);s+=i){var d=r.children[s];if(-1===d.className.indexOf("hidden")&&ee(d.dateObj)&&Math.abs(e.$i-s)>=Math.abs(n))return W(d)}w.changeMonth(i),B(R(i),0)}(a,n):W(a)}function J(e,n){for(var t=(new Date(e,n,1).getDay()-w.l10n.firstDayOfWeek+7)%7,a=w.utils.getDaysInMonth((n-1+12)%12,e),i=w.utils.getDaysInMonth(n,e),o=window.document.createDocumentFragment(),r=w.config.showMonths>1,l=r?"prevMonthDay hidden":"prevMonthDay",c=r?"nextMonthDay hidden":"nextMonthDay",s=a+1-t,u=0;s<=a;s++,u++)o.appendChild(L(l,new Date(e,n-1,s),s,u));for(s=1;s<=i;s++,u++)o.appendChild(L("",new Date(e,n,s),s,u));for(var f=i+1;f<=42-t&&(1===w.config.showMonths||u%7!=0);f++,u++)o.appendChild(L(c,new Date(e,n+1,f%i),f,u));var m=d("div","dayContainer");return m.appendChild(o),m}function K(){if(void 0!==w.daysContainer){u(w.daysContainer),w.weekNumbers&&u(w.weekNumbers);for(var e=document.createDocumentFragment(),n=0;n<w.config.showMonths;n++){var t=new Date(w.currentYear,w.currentMonth,1);t.setMonth(w.currentMonth+n),e.appendChild(J(t.getFullYear(),t.getMonth()))}w.daysContainer.appendChild(e),w.days=w.daysContainer.firstChild,"range"===w.config.mode&&1===w.selectedDates.length&&ie()}}function U(){if(!(w.config.showMonths>1||"dropdown"!==w.config.monthSelectorType)){var e=function(e){return!(void 0!==w.config.minDate&&w.currentYear===w.config.minDate.getFullYear()&&e<w.config.minDate.getMonth())&&!(void 0!==w.config.maxDate&&w.currentYear===w.config.maxDate.getFullYear()&&e>w.config.maxDate.getMonth())};w.monthsDropdownContainer.tabIndex=-1,w.monthsDropdownContainer.innerHTML="";for(var n=0;n<12;n++)if(e(n)){var t=d("option","flatpickr-monthDropdown-month");t.value=new Date(w.currentYear,n).getMonth().toString(),t.textContent=h(n,w.config.shorthandCurrentMonth,w.l10n),t.tabIndex=-1,w.currentMonth===n&&(t.selected=!0),w.monthsDropdownContainer.appendChild(t)}}}function q(){var e,n=d("div","flatpickr-month"),t=window.document.createDocumentFragment();w.config.showMonths>1||"static"===w.config.monthSelectorType?e=d("span","cur-month"):(w.monthsDropdownContainer=d("select","flatpickr-monthDropdown-months"),w.monthsDropdownContainer.setAttribute("aria-label",w.l10n.monthAriaLabel),N(w.monthsDropdownContainer,"change",(function(e){var n=g(e),t=parseInt(n.value,10);w.changeMonth(t-w.currentMonth),ve("onMonthChange")})),U(),e=w.monthsDropdownContainer);var a=m("cur-year",{tabindex:"-1"}),i=a.getElementsByTagName("input")[0];i.setAttribute("aria-label",w.l10n.yearAriaLabel),w.config.minDate&&i.setAttribute("min",w.config.minDate.getFullYear().toString()),w.config.maxDate&&(i.setAttribute("max",w.config.maxDate.getFullYear().toString()),i.disabled=!!w.config.minDate&&w.config.minDate.getFullYear()===w.config.maxDate.getFullYear());var o=d("div","flatpickr-current-month");return o.appendChild(e),o.appendChild(a),t.appendChild(o),n.appendChild(t),{container:n,yearElement:i,monthElement:e}}function $(){u(w.monthNav),w.monthNav.appendChild(w.prevMonthNav),w.config.showMonths&&(w.yearElements=[],w.monthElements=[]);for(var e=w.config.showMonths;e--;){var n=q();w.yearElements.push(n.yearElement),w.monthElements.push(n.monthElement),w.monthNav.appendChild(n.container)}w.monthNav.appendChild(w.nextMonthNav)}function z(){w.weekdayContainer?u(w.weekdayContainer):w.weekdayContainer=d("div","flatpickr-weekdays");for(var e=w.config.showMonths;e--;){var n=d("div","flatpickr-weekdaycontainer");w.weekdayContainer.appendChild(n)}return G(),w.weekdayContainer}function G(){if(w.weekdayContainer){var e=w.l10n.firstDayOfWeek,t=n(w.l10n.weekdays.shorthand);e>0&&e<t.length&&(t=n(t.splice(e,t.length),t.splice(0,e)));for(var a=w.config.showMonths;a--;)w.weekdayContainer.children[a].innerHTML="\n <span class='flatpickr-weekday'>\n "+t.join("</span><span class='flatpickr-weekday'>")+"\n </span>\n "}}function V(e,n){void 0===n&&(n=!0);var t=n?e:e-w.currentMonth;t<0&&!0===w._hidePrevMonthArrow||t>0&&!0===w._hideNextMonthArrow||(w.currentMonth+=t,(w.currentMonth<0||w.currentMonth>11)&&(w.currentYear+=w.currentMonth>11?1:-1,w.currentMonth=(w.currentMonth+12)%12,ve("onYearChange"),U()),K(),ve("onMonthChange"),be())}function Z(e){return!(!w.config.appendTo||!w.config.appendTo.contains(e))||w.calendarContainer.contains(e)}function Q(e){if(w.isOpen&&!w.config.inline){var n=g(e),t=Z(n),a=n===w.input||n===w.altInput||w.element.contains(n)||e.path&&e.path.indexOf&&(~e.path.indexOf(w.input)||~e.path.indexOf(w.altInput)),i="blur"===e.type?a&&e.relatedTarget&&!Z(e.relatedTarget):!a&&!t&&!Z(e.relatedTarget),o=!w.config.ignoredFocusElements.some((function(e){return e.contains(n)}));i&&o&&(void 0!==w.timeContainer&&void 0!==w.minuteElement&&void 0!==w.hourElement&&""!==w.input.value&&void 0!==w.input.value&&I(),w.close(),w.config&&"range"===w.config.mode&&1===w.selectedDates.length&&(w.clear(!1),w.redraw()))}}function X(e){if(!(!e||w.config.minDate&&e<w.config.minDate.getFullYear()||w.config.maxDate&&e>w.config.maxDate.getFullYear())){var n=e,t=w.currentYear!==n;w.currentYear=n||w.currentYear,w.config.maxDate&&w.currentYear===w.config.maxDate.getFullYear()?w.currentMonth=Math.min(w.config.maxDate.getMonth(),w.currentMonth):w.config.minDate&&w.currentYear===w.config.minDate.getFullYear()&&(w.currentMonth=Math.max(w.config.minDate.getMonth(),w.currentMonth)),t&&(w.redraw(),ve("onYearChange"),U())}}function ee(e,n){var t;void 0===n&&(n=!0);var a=w.parseDate(e,void 0,n);if(w.config.minDate&&a&&M(a,w.config.minDate,void 0!==n?n:!w.minDateHasTime)<0||w.config.maxDate&&a&&M(a,w.config.maxDate,void 0!==n?n:!w.maxDateHasTime)>0)return!1;if(!w.config.enable&&0===w.config.disable.length)return!0;if(void 0===a)return!1;for(var i=!!w.config.enable,o=null!==(t=w.config.enable)&&void 0!==t?t:w.config.disable,r=0,l=void 0;r<o.length;r++){if("function"==typeof(l=o[r])&&l(a))return i;if(l instanceof Date&&void 0!==a&&l.getTime()===a.getTime())return i;if("string"==typeof l){var c=w.parseDate(l,void 0,!0);return c&&c.getTime()===a.getTime()?i:!i}if("object"==typeof l&&void 0!==a&&l.from&&l.to&&a.getTime()>=l.from.getTime()&&a.getTime()<=l.to.getTime())return i}return!i}function ne(e){return void 0!==w.daysContainer&&(-1===e.className.indexOf("hidden")&&-1===e.className.indexOf("flatpickr-disabled")&&w.daysContainer.contains(e))}function te(e){!(e.target===w._input)||!(w.selectedDates.length>0||w._input.value.length>0)||e.relatedTarget&&Z(e.relatedTarget)||w.setDate(w._input.value,!0,e.target===w.altInput?w.config.altFormat:w.config.dateFormat)}function ae(e){var n=g(e),t=w.config.wrap?p.contains(n):n===w._input,a=w.config.allowInput,i=w.isOpen&&(!a||!t),o=w.config.inline&&t&&!a;if(13===e.keyCode&&t){if(a)return w.setDate(w._input.value,!0,n===w.altInput?w.config.altFormat:w.config.dateFormat),n.blur();w.open()}else if(Z(n)||i||o){var r=!!w.timeContainer&&w.timeContainer.contains(n);switch(e.keyCode){case 13:r?(e.preventDefault(),I(),ue()):fe(e);break;case 27:e.preventDefault(),ue();break;case 8:case 46:t&&!w.config.allowInput&&(e.preventDefault(),w.clear());break;case 37:case 39:if(r||t)w.hourElement&&w.hourElement.focus();else if(e.preventDefault(),void 0!==w.daysContainer&&(!1===a||document.activeElement&&ne(document.activeElement))){var l=39===e.keyCode?1:-1;e.ctrlKey?(e.stopPropagation(),V(l),B(R(1),0)):B(void 0,l)}break;case 38:case 40:e.preventDefault();var c=40===e.keyCode?1:-1;w.daysContainer&&void 0!==n.$i||n===w.input||n===w.altInput?e.ctrlKey?(e.stopPropagation(),X(w.currentYear-c),B(R(1),0)):r||B(void 0,7*c):n===w.currentYearElement?X(w.currentYear-c):w.config.enableTime&&(!r&&w.hourElement&&w.hourElement.focus(),I(e),w._debouncedChange());break;case 9:if(r){var s=[w.hourElement,w.minuteElement,w.secondElement,w.amPM].concat(w.pluginElements).filter((function(e){return e})),d=s.indexOf(n);if(-1!==d){var u=s[d+(e.shiftKey?-1:1)];e.preventDefault(),(u||w._input).focus()}}else!w.config.noCalendar&&w.daysContainer&&w.daysContainer.contains(n)&&e.shiftKey&&(e.preventDefault(),w._input.focus())}}if(void 0!==w.amPM&&n===w.amPM)switch(e.key){case w.l10n.amPM[0].charAt(0):case w.l10n.amPM[0].charAt(0).toLowerCase():w.amPM.textContent=w.l10n.amPM[0],_(),Me();break;case w.l10n.amPM[1].charAt(0):case w.l10n.amPM[1].charAt(0).toLowerCase():w.amPM.textContent=w.l10n.amPM[1],_(),Me()}(t||Z(n))&&ve("onKeyDown",e)}function ie(e){if(1===w.selectedDates.length&&(!e||e.classList.contains("flatpickr-day")&&!e.classList.contains("flatpickr-disabled"))){for(var n=e?e.dateObj.getTime():w.days.firstElementChild.dateObj.getTime(),t=w.parseDate(w.selectedDates[0],void 0,!0).getTime(),a=Math.min(n,w.selectedDates[0].getTime()),i=Math.max(n,w.selectedDates[0].getTime()),o=!1,r=0,l=0,c=a;c<i;c+=x)ee(new Date(c),!0)||(o=o||c>a&&c<i,c<t&&(!r||c>r)?r=c:c>t&&(!l||c<l)&&(l=c));for(var s=0;s<w.config.showMonths;s++)for(var d=w.daysContainer.children[s],u=function(a,i){var c,s,u,f=d.children[a],m=f.dateObj.getTime(),g=r>0&&m<r||l>0&&m>l;return g?(f.classList.add("notAllowed"),["inRange","startRange","endRange"].forEach((function(e){f.classList.remove(e)})),"continue"):o&&!g?"continue":(["startRange","inRange","endRange","notAllowed"].forEach((function(e){f.classList.remove(e)})),void(void 0!==e&&(e.classList.add(n<=w.selectedDates[0].getTime()?"startRange":"endRange"),t<n&&m===t?f.classList.add("startRange"):t>n&&m===t&&f.classList.add("endRange"),m>=r&&(0===l||m<=l)&&(s=t,u=n,(c=m)>Math.min(s,u)&&c<Math.max(s,u))&&f.classList.add("inRange"))))},f=0,m=d.children.length;f<m;f++)u(f)}}function oe(){!w.isOpen||w.config.static||w.config.inline||se()}function re(e){return function(n){var t=w.config["_"+e+"Date"]=w.parseDate(n,w.config.dateFormat),a=w.config["_"+("min"===e?"max":"min")+"Date"];void 0!==t&&(w["min"===e?"minDateHasTime":"maxDateHasTime"]=t.getHours()>0||t.getMinutes()>0||t.getSeconds()>0),w.selectedDates&&(w.selectedDates=w.selectedDates.filter((function(e){return ee(e)})),w.selectedDates.length||"min"!==e||O(t),Me()),w.daysContainer&&(de(),void 0!==t?w.currentYearElement[e]=t.getFullYear().toString():w.currentYearElement.removeAttribute(e),w.currentYearElement.disabled=!!a&&void 0!==t&&a.getFullYear()===t.getFullYear())}}function le(){return w.config.wrap?p.querySelector("[data-input]"):p}function ce(){"object"!=typeof w.config.locale&&void 0===S.l10ns[w.config.locale]&&w.config.errorHandler(new Error("flatpickr: invalid locale "+w.config.locale)),w.l10n=e(e({},S.l10ns.default),"object"==typeof w.config.locale?w.config.locale:"default"!==w.config.locale?S.l10ns[w.config.locale]:void 0),D.K="("+w.l10n.amPM[0]+"|"+w.l10n.amPM[1]+"|"+w.l10n.amPM[0].toLowerCase()+"|"+w.l10n.amPM[1].toLowerCase()+")",void 0===e(e({},v),JSON.parse(JSON.stringify(p.dataset||{}))).time_24hr&&void 0===S.defaultConfig.time_24hr&&(w.config.time_24hr=w.l10n.time_24hr),w.formatDate=b(w),w.parseDate=C({config:w.config,l10n:w.l10n})}function se(e){if("function"!=typeof w.config.position){if(void 0!==w.calendarContainer){ve("onPreCalendarPosition");var n=e||w._positionElement,t=Array.prototype.reduce.call(w.calendarContainer.children,(function(e,n){return e+n.offsetHeight}),0),a=w.calendarContainer.offsetWidth,i=w.config.position.split(" "),o=i[0],r=i.length>1?i[1]:null,l=n.getBoundingClientRect(),c=window.innerHeight-l.bottom,d="above"===o||"below"!==o&&c<t&&l.top>t,u=window.pageYOffset+l.top+(d?-t-2:n.offsetHeight+2);if(s(w.calendarContainer,"arrowTop",!d),s(w.calendarContainer,"arrowBottom",d),!w.config.inline){var f=window.pageXOffset+l.left,m=!1,g=!1;"center"===r?(f-=(a-l.width)/2,m=!0):"right"===r&&(f-=a-l.width,g=!0),s(w.calendarContainer,"arrowLeft",!m&&!g),s(w.calendarContainer,"arrowCenter",m),s(w.calendarContainer,"arrowRight",g);var p=window.document.body.offsetWidth-(window.pageXOffset+l.right),h=f+a>window.document.body.offsetWidth,v=p+a>window.document.body.offsetWidth;if(s(w.calendarContainer,"rightMost",h),!w.config.static)if(w.calendarContainer.style.top=u+"px",h)if(v){var D=function(){for(var e=null,n=0;n<document.styleSheets.length;n++){var t=document.styleSheets[n];try{t.cssRules}catch(e){continue}e=t;break}return null!=e?e:(a=document.createElement("style"),document.head.appendChild(a),a.sheet);var a}();if(void 0===D)return;var b=window.document.body.offsetWidth,C=Math.max(0,b/2-a/2),M=D.cssRules.length,y="{left:"+l.left+"px;right:auto;}";s(w.calendarContainer,"rightMost",!1),s(w.calendarContainer,"centerMost",!0),D.insertRule(".flatpickr-calendar.centerMost:before,.flatpickr-calendar.centerMost:after"+y,M),w.calendarContainer.style.left=C+"px",w.calendarContainer.style.right="auto"}else w.calendarContainer.style.left="auto",w.calendarContainer.style.right=p+"px";else w.calendarContainer.style.left=f+"px",w.calendarContainer.style.right="auto"}}}else w.config.position(w,e)}function de(){w.config.noCalendar||w.isMobile||(U(),be(),K())}function ue(){w._input.focus(),-1!==window.navigator.userAgent.indexOf("MSIE")||void 0!==navigator.msMaxTouchPoints?setTimeout(w.close,0):w.close()}function fe(e){e.preventDefault(),e.stopPropagation();var n=f(g(e),(function(e){return e.classList&&e.classList.contains("flatpickr-day")&&!e.classList.contains("flatpickr-disabled")&&!e.classList.contains("notAllowed")}));if(void 0!==n){var t=n,a=w.latestSelectedDateObj=new Date(t.dateObj.getTime()),i=(a.getMonth()<w.currentMonth||a.getMonth()>w.currentMonth+w.config.showMonths-1)&&"range"!==w.config.mode;if(w.selectedDateElem=t,"single"===w.config.mode)w.selectedDates=[a];else if("multiple"===w.config.mode){var o=we(a);o?w.selectedDates.splice(parseInt(o),1):w.selectedDates.push(a)}else"range"===w.config.mode&&(2===w.selectedDates.length&&w.clear(!1,!1),w.latestSelectedDateObj=a,w.selectedDates.push(a),0!==M(a,w.selectedDates[0],!0)&&w.selectedDates.sort((function(e,n){return e.getTime()-n.getTime()})));if(_(),i){var r=w.currentYear!==a.getFullYear();w.currentYear=a.getFullYear(),w.currentMonth=a.getMonth(),r&&(ve("onYearChange"),U()),ve("onMonthChange")}if(be(),K(),Me(),i||"range"===w.config.mode||1!==w.config.showMonths?void 0!==w.selectedDateElem&&void 0===w.hourElement&&w.selectedDateElem&&w.selectedDateElem.focus():W(t),void 0!==w.hourElement&&void 0!==w.hourElement&&w.hourElement.focus(),w.config.closeOnSelect){var l="single"===w.config.mode&&!w.config.enableTime,c="range"===w.config.mode&&2===w.selectedDates.length&&!w.config.enableTime;(l||c)&&ue()}P()}}w.parseDate=C({config:w.config,l10n:w.l10n}),w._handlers=[],w.pluginElements=[],w.loadedPlugins=[],w._bind=N,w._setHoursFromDate=O,w._positionCalendar=se,w.changeMonth=V,w.changeYear=X,w.clear=function(e,n){void 0===e&&(e=!0);void 0===n&&(n=!0);w.input.value="",void 0!==w.altInput&&(w.altInput.value="");void 0!==w.mobileInput&&(w.mobileInput.value="");w.selectedDates=[],w.latestSelectedDateObj=void 0,!0===n&&(w.currentYear=w._initialDate.getFullYear(),w.currentMonth=w._initialDate.getMonth());if(!0===w.config.enableTime){var t=E(w.config),a=t.hours,i=t.minutes,o=t.seconds;F(a,i,o)}w.redraw(),e&&ve("onChange")},w.close=function(){w.isOpen=!1,w.isMobile||(void 0!==w.calendarContainer&&w.calendarContainer.classList.remove("open"),void 0!==w._input&&w._input.classList.remove("active"));ve("onClose")},w._createElement=d,w.destroy=function(){void 0!==w.config&&ve("onDestroy");for(var e=w._handlers.length;e--;)w._handlers[e].remove();if(w._handlers=[],w.mobileInput)w.mobileInput.parentNode&&w.mobileInput.parentNode.removeChild(w.mobileInput),w.mobileInput=void 0;else if(w.calendarContainer&&w.calendarContainer.parentNode)if(w.config.static&&w.calendarContainer.parentNode){var n=w.calendarContainer.parentNode;if(n.lastChild&&n.removeChild(n.lastChild),n.parentNode){for(;n.firstChild;)n.parentNode.insertBefore(n.firstChild,n);n.parentNode.removeChild(n)}}else w.calendarContainer.parentNode.removeChild(w.calendarContainer);w.altInput&&(w.input.type="text",w.altInput.parentNode&&w.altInput.parentNode.removeChild(w.altInput),delete w.altInput);w.input&&(w.input.type=w.input._type,w.input.classList.remove("flatpickr-input"),w.input.removeAttribute("readonly"));["_showTimeInput","latestSelectedDateObj","_hideNextMonthArrow","_hidePrevMonthArrow","__hideNextMonthArrow","__hidePrevMonthArrow","isMobile","isOpen","selectedDateElem","minDateHasTime","maxDateHasTime","days","daysContainer","_input","_positionElement","innerContainer","rContainer","monthNav","todayDateElem","calendarContainer","weekdayContainer","prevMonthNav","nextMonthNav","monthsDropdownContainer","currentMonthElement","currentYearElement","navigationCurrentMonth","selectedDateElem","config"].forEach((function(e){try{delete w[e]}catch(e){}}))},w.isEnabled=ee,w.jumpToDate=Y,w.open=function(e,n){void 0===n&&(n=w._positionElement);if(!0===w.isMobile){if(e){e.preventDefault();var t=g(e);t&&t.blur()}return void 0!==w.mobileInput&&(w.mobileInput.focus(),w.mobileInput.click()),void ve("onOpen")}if(w._input.disabled||w.config.inline)return;var a=w.isOpen;w.isOpen=!0,a||(w.calendarContainer.classList.add("open"),w._input.classList.add("active"),ve("onOpen"),se(n));!0===w.config.enableTime&&!0===w.config.noCalendar&&(!1!==w.config.allowInput||void 0!==e&&w.timeContainer.contains(e.relatedTarget)||setTimeout((function(){return w.hourElement.select()}),50))},w.redraw=de,w.set=function(e,n){if(null!==e&&"object"==typeof e)for(var a in Object.assign(w.config,e),e)void 0!==me[a]&&me[a].forEach((function(e){return e()}));else w.config[e]=n,void 0!==me[e]?me[e].forEach((function(e){return e()})):t.indexOf(e)>-1&&(w.config[e]=c(n));w.redraw(),Me(!0)},w.setDate=function(e,n,t){void 0===n&&(n=!1);void 0===t&&(t=w.config.dateFormat);if(0!==e&&!e||e instanceof Array&&0===e.length)return w.clear(n);ge(e,t),w.latestSelectedDateObj=w.selectedDates[w.selectedDates.length-1],w.redraw(),Y(void 0,n),O(),0===w.selectedDates.length&&w.clear(!1);Me(n),n&&ve("onChange")},w.toggle=function(e){if(!0===w.isOpen)return w.close();w.open(e)};var me={locale:[ce,G],showMonths:[$,k,z],minDate:[Y],maxDate:[Y],positionElement:[he],clickOpens:[function(){!0===w.config.clickOpens?(N(w._input,"focus",w.open),N(w._input,"click",w.open)):(w._input.removeEventListener("focus",w.open),w._input.removeEventListener("click",w.open))}]};function ge(e,n){var t=[];if(e instanceof Array)t=e.map((function(e){return w.parseDate(e,n)}));else if(e instanceof Date||"number"==typeof e)t=[w.parseDate(e,n)];else if("string"==typeof e)switch(w.config.mode){case"single":case"time":t=[w.parseDate(e,n)];break;case"multiple":t=e.split(w.config.conjunction).map((function(e){return w.parseDate(e,n)}));break;case"range":t=e.split(w.l10n.rangeSeparator).map((function(e){return w.parseDate(e,n)}))}else w.config.errorHandler(new Error("Invalid date supplied: "+JSON.stringify(e)));w.selectedDates=w.config.allowInvalidPreload?t:t.filter((function(e){return e instanceof Date&&ee(e,!1)})),"range"===w.config.mode&&w.selectedDates.sort((function(e,n){return e.getTime()-n.getTime()}))}function pe(e){return e.slice().map((function(e){return"string"==typeof e||"number"==typeof e||e instanceof Date?w.parseDate(e,void 0,!0):e&&"object"==typeof e&&e.from&&e.to?{from:w.parseDate(e.from,void 0),to:w.parseDate(e.to,void 0)}:e})).filter((function(e){return e}))}function he(){w._positionElement=w.config.positionElement||w._input}function ve(e,n){if(void 0!==w.config){var t=w.config[e];if(void 0!==t&&t.length>0)for(var a=0;t[a]&&a<t.length;a++)t[a](w.selectedDates,w.input.value,w,n);"onChange"===e&&(w.input.dispatchEvent(De("change")),w.input.dispatchEvent(De("input")))}}function De(e){var n=document.createEvent("Event");return n.initEvent(e,!0,!0),n}function we(e){for(var n=0;n<w.selectedDates.length;n++)if(0===M(w.selectedDates[n],e))return""+n;return!1}function be(){w.config.noCalendar||w.isMobile||!w.monthNav||(w.yearElements.forEach((function(e,n){var t=new Date(w.currentYear,w.currentMonth,1);t.setMonth(w.currentMonth+n),w.config.showMonths>1||"static"===w.config.monthSelectorType?w.monthElements[n].textContent=h(t.getMonth(),w.config.shorthandCurrentMonth,w.l10n)+" ":w.monthsDropdownContainer.value=t.getMonth().toString(),e.value=t.getFullYear().toString()})),w._hidePrevMonthArrow=void 0!==w.config.minDate&&(w.currentYear===w.config.minDate.getFullYear()?w.currentMonth<=w.config.minDate.getMonth():w.currentYear<w.config.minDate.getFullYear()),w._hideNextMonthArrow=void 0!==w.config.maxDate&&(w.currentYear===w.config.maxDate.getFullYear()?w.currentMonth+1>w.config.maxDate.getMonth():w.currentYear>w.config.maxDate.getFullYear()))}function Ce(e){return w.selectedDates.map((function(n){return w.formatDate(n,e)})).filter((function(e,n,t){return"range"!==w.config.mode||w.config.enableTime||t.indexOf(e)===n})).join("range"!==w.config.mode?w.config.conjunction:w.l10n.rangeSeparator)}function Me(e){void 0===e&&(e=!0),void 0!==w.mobileInput&&w.mobileFormatStr&&(w.mobileInput.value=void 0!==w.latestSelectedDateObj?w.formatDate(w.latestSelectedDateObj,w.mobileFormatStr):""),w.input.value=Ce(w.config.dateFormat),void 0!==w.altInput&&(w.altInput.value=Ce(w.config.altFormat)),!1!==e&&ve("onValueUpdate")}function ye(e){var n=g(e),t=w.prevMonthNav.contains(n),a=w.nextMonthNav.contains(n);t||a?V(t?-1:1):w.yearElements.indexOf(n)>=0?n.select():n.classList.contains("arrowUp")?w.changeYear(w.currentYear+1):n.classList.contains("arrowDown")&&w.changeYear(w.currentYear-1)}return function(){w.element=w.input=p,w.isOpen=!1,function(){var n=["wrap","weekNumbers","allowInput","allowInvalidPreload","clickOpens","time_24hr","enableTime","noCalendar","altInput","shorthandCurrentMonth","inline","static","enableSeconds","disableMobile"],i=e(e({},JSON.parse(JSON.stringify(p.dataset||{}))),v),o={};w.config.parseDate=i.parseDate,w.config.formatDate=i.formatDate,Object.defineProperty(w.config,"enable",{get:function(){return w.config._enable},set:function(e){w.config._enable=pe(e)}}),Object.defineProperty(w.config,"disable",{get:function(){return w.config._disable},set:function(e){w.config._disable=pe(e)}});var r="time"===i.mode;if(!i.dateFormat&&(i.enableTime||r)){var l=S.defaultConfig.dateFormat||a.dateFormat;o.dateFormat=i.noCalendar||r?"H:i"+(i.enableSeconds?":S":""):l+" H:i"+(i.enableSeconds?":S":"")}if(i.altInput&&(i.enableTime||r)&&!i.altFormat){var s=S.defaultConfig.altFormat||a.altFormat;o.altFormat=i.noCalendar||r?"h:i"+(i.enableSeconds?":S K":" K"):s+" h:i"+(i.enableSeconds?":S":"")+" K"}Object.defineProperty(w.config,"minDate",{get:function(){return w.config._minDate},set:re("min")}),Object.defineProperty(w.config,"maxDate",{get:function(){return w.config._maxDate},set:re("max")});var d=function(e){return function(n){w.config["min"===e?"_minTime":"_maxTime"]=w.parseDate(n,"H:i:S")}};Object.defineProperty(w.config,"minTime",{get:function(){return w.config._minTime},set:d("min")}),Object.defineProperty(w.config,"maxTime",{get:function(){return w.config._maxTime},set:d("max")}),"time"===i.mode&&(w.config.noCalendar=!0,w.config.enableTime=!0);Object.assign(w.config,o,i);for(var u=0;u<n.length;u++)w.config[n[u]]=!0===w.config[n[u]]||"true"===w.config[n[u]];t.filter((function(e){return void 0!==w.config[e]})).forEach((function(e){w.config[e]=c(w.config[e]||[]).map(T)})),w.isMobile=!w.config.disableMobile&&!w.config.inline&&"single"===w.config.mode&&!w.config.disable.length&&!w.config.enable&&!w.config.weekNumbers&&/Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent);for(u=0;u<w.config.plugins.length;u++){var f=w.config.plugins[u](w)||{};for(var m in f)t.indexOf(m)>-1?w.config[m]=c(f[m]).map(T).concat(w.config[m]):void 0===i[m]&&(w.config[m]=f[m])}i.altInputClass||(w.config.altInputClass=le().className+" "+w.config.altInputClass);ve("onParseConfig")}(),ce(),function(){if(w.input=le(),!w.input)return void w.config.errorHandler(new Error("Invalid input element specified"));w.input._type=w.input.type,w.input.type="text",w.input.classList.add("flatpickr-input"),w._input=w.input,w.config.altInput&&(w.altInput=d(w.input.nodeName,w.config.altInputClass),w._input=w.altInput,w.altInput.placeholder=w.input.placeholder,w.altInput.disabled=w.input.disabled,w.altInput.required=w.input.required,w.altInput.tabIndex=w.input.tabIndex,w.altInput.type="text",w.input.setAttribute("type","hidden"),!w.config.static&&w.input.parentNode&&w.input.parentNode.insertBefore(w.altInput,w.input.nextSibling));w.config.allowInput||w._input.setAttribute("readonly","readonly");he()}(),function(){w.selectedDates=[],w.now=w.parseDate(w.config.now)||new Date;var e=w.config.defaultDate||("INPUT"!==w.input.nodeName&&"TEXTAREA"!==w.input.nodeName||!w.input.placeholder||w.input.value!==w.input.placeholder?w.input.value:null);e&&ge(e,w.config.dateFormat);w._initialDate=w.selectedDates.length>0?w.selectedDates[0]:w.config.minDate&&w.config.minDate.getTime()>w.now.getTime()?w.config.minDate:w.config.maxDate&&w.config.maxDate.getTime()<w.now.getTime()?w.config.maxDate:w.now,w.currentYear=w._initialDate.getFullYear(),w.currentMonth=w._initialDate.getMonth(),w.selectedDates.length>0&&(w.latestSelectedDateObj=w.selectedDates[0]);void 0!==w.config.minTime&&(w.config.minTime=w.parseDate(w.config.minTime,"H:i"));void 0!==w.config.maxTime&&(w.config.maxTime=w.parseDate(w.config.maxTime,"H:i"));w.minDateHasTime=!!w.config.minDate&&(w.config.minDate.getHours()>0||w.config.minDate.getMinutes()>0||w.config.minDate.getSeconds()>0),w.maxDateHasTime=!!w.config.maxDate&&(w.config.maxDate.getHours()>0||w.config.maxDate.getMinutes()>0||w.config.maxDate.getSeconds()>0)}(),w.utils={getDaysInMonth:function(e,n){return void 0===e&&(e=w.currentMonth),void 0===n&&(n=w.currentYear),1===e&&(n%4==0&&n%100!=0||n%400==0)?29:w.l10n.daysInMonth[e]}},w.isMobile||function(){var e=window.document.createDocumentFragment();if(w.calendarContainer=d("div","flatpickr-calendar"),w.calendarContainer.tabIndex=-1,!w.config.noCalendar){if(e.appendChild((w.monthNav=d("div","flatpickr-months"),w.yearElements=[],w.monthElements=[],w.prevMonthNav=d("span","flatpickr-prev-month"),w.prevMonthNav.innerHTML=w.config.prevArrow,w.nextMonthNav=d("span","flatpickr-next-month"),w.nextMonthNav.innerHTML=w.config.nextArrow,$(),Object.defineProperty(w,"_hidePrevMonthArrow",{get:function(){return w.__hidePrevMonthArrow},set:function(e){w.__hidePrevMonthArrow!==e&&(s(w.prevMonthNav,"flatpickr-disabled",e),w.__hidePrevMonthArrow=e)}}),Object.defineProperty(w,"_hideNextMonthArrow",{get:function(){return w.__hideNextMonthArrow},set:function(e){w.__hideNextMonthArrow!==e&&(s(w.nextMonthNav,"flatpickr-disabled",e),w.__hideNextMonthArrow=e)}}),w.currentYearElement=w.yearElements[0],be(),w.monthNav)),w.innerContainer=d("div","flatpickr-innerContainer"),w.config.weekNumbers){var n=function(){w.calendarContainer.classList.add("hasWeeks");var e=d("div","flatpickr-weekwrapper");e.appendChild(d("span","flatpickr-weekday",w.l10n.weekAbbreviation));var n=d("div","flatpickr-weeks");return e.appendChild(n),{weekWrapper:e,weekNumbers:n}}(),t=n.weekWrapper,a=n.weekNumbers;w.innerContainer.appendChild(t),w.weekNumbers=a,w.weekWrapper=t}w.rContainer=d("div","flatpickr-rContainer"),w.rContainer.appendChild(z()),w.daysContainer||(w.daysContainer=d("div","flatpickr-days"),w.daysContainer.tabIndex=-1),K(),w.rContainer.appendChild(w.daysContainer),w.innerContainer.appendChild(w.rContainer),e.appendChild(w.innerContainer)}w.config.enableTime&&e.appendChild(function(){w.calendarContainer.classList.add("hasTime"),w.config.noCalendar&&w.calendarContainer.classList.add("noCalendar");var e=E(w.config);w.timeContainer=d("div","flatpickr-time"),w.timeContainer.tabIndex=-1;var n=d("span","flatpickr-time-separator",":"),t=m("flatpickr-hour",{"aria-label":w.l10n.hourAriaLabel});w.hourElement=t.getElementsByTagName("input")[0];var a=m("flatpickr-minute",{"aria-label":w.l10n.minuteAriaLabel});w.minuteElement=a.getElementsByTagName("input")[0],w.hourElement.tabIndex=w.minuteElement.tabIndex=-1,w.hourElement.value=o(w.latestSelectedDateObj?w.latestSelectedDateObj.getHours():w.config.time_24hr?e.hours:function(e){switch(e%24){case 0:case 12:return 12;default:return e%12}}(e.hours)),w.minuteElement.value=o(w.latestSelectedDateObj?w.latestSelectedDateObj.getMinutes():e.minutes),w.hourElement.setAttribute("step",w.config.hourIncrement.toString()),w.minuteElement.setAttribute("step",w.config.minuteIncrement.toString()),w.hourElement.setAttribute("min",w.config.time_24hr?"0":"1"),w.hourElement.setAttribute("max",w.config.time_24hr?"23":"12"),w.hourElement.setAttribute("maxlength","2"),w.minuteElement.setAttribute("min","0"),w.minuteElement.setAttribute("max","59"),w.minuteElement.setAttribute("maxlength","2"),w.timeContainer.appendChild(t),w.timeContainer.appendChild(n),w.timeContainer.appendChild(a),w.config.time_24hr&&w.timeContainer.classList.add("time24hr");if(w.config.enableSeconds){w.timeContainer.classList.add("hasSeconds");var i=m("flatpickr-second");w.secondElement=i.getElementsByTagName("input")[0],w.secondElement.value=o(w.latestSelectedDateObj?w.latestSelectedDateObj.getSeconds():e.seconds),w.secondElement.setAttribute("step",w.minuteElement.getAttribute("step")),w.secondElement.setAttribute("min","0"),w.secondElement.setAttribute("max","59"),w.secondElement.setAttribute("maxlength","2"),w.timeContainer.appendChild(d("span","flatpickr-time-separator",":")),w.timeContainer.appendChild(i)}w.config.time_24hr||(w.amPM=d("span","flatpickr-am-pm",w.l10n.amPM[r((w.latestSelectedDateObj?w.hourElement.value:w.config.defaultHour)>11)]),w.amPM.title=w.l10n.toggleTitle,w.amPM.tabIndex=-1,w.timeContainer.appendChild(w.amPM));return w.timeContainer}());s(w.calendarContainer,"rangeMode","range"===w.config.mode),s(w.calendarContainer,"animate",!0===w.config.animate),s(w.calendarContainer,"multiMonth",w.config.showMonths>1),w.calendarContainer.appendChild(e);var i=void 0!==w.config.appendTo&&void 0!==w.config.appendTo.nodeType;if((w.config.inline||w.config.static)&&(w.calendarContainer.classList.add(w.config.inline?"inline":"static"),w.config.inline&&(!i&&w.element.parentNode?w.element.parentNode.insertBefore(w.calendarContainer,w._input.nextSibling):void 0!==w.config.appendTo&&w.config.appendTo.appendChild(w.calendarContainer)),w.config.static)){var l=d("div","flatpickr-wrapper");w.element.parentNode&&w.element.parentNode.insertBefore(l,w.element),l.appendChild(w.element),w.altInput&&l.appendChild(w.altInput),l.appendChild(w.calendarContainer)}w.config.static||w.config.inline||(void 0!==w.config.appendTo?w.config.appendTo:window.document.body).appendChild(w.calendarContainer)}(),function(){w.config.wrap&&["open","close","toggle","clear"].forEach((function(e){Array.prototype.forEach.call(w.element.querySelectorAll("[data-"+e+"]"),(function(n){return N(n,"click",w[e])}))}));if(w.isMobile)return void function(){var e=w.config.enableTime?w.config.noCalendar?"time":"datetime-local":"date";w.mobileInput=d("input",w.input.className+" flatpickr-mobile"),w.mobileInput.tabIndex=1,w.mobileInput.type=e,w.mobileInput.disabled=w.input.disabled,w.mobileInput.required=w.input.required,w.mobileInput.placeholder=w.input.placeholder,w.mobileFormatStr="datetime-local"===e?"Y-m-d\\TH:i:S":"date"===e?"Y-m-d":"H:i:S",w.selectedDates.length>0&&(w.mobileInput.defaultValue=w.mobileInput.value=w.formatDate(w.selectedDates[0],w.mobileFormatStr));w.config.minDate&&(w.mobileInput.min=w.formatDate(w.config.minDate,"Y-m-d"));w.config.maxDate&&(w.mobileInput.max=w.formatDate(w.config.maxDate,"Y-m-d"));w.input.getAttribute("step")&&(w.mobileInput.step=String(w.input.getAttribute("step")));w.input.type="hidden",void 0!==w.altInput&&(w.altInput.type="hidden");try{w.input.parentNode&&w.input.parentNode.insertBefore(w.mobileInput,w.input.nextSibling)}catch(e){}N(w.mobileInput,"change",(function(e){w.setDate(g(e).value,!1,w.mobileFormatStr),ve("onChange"),ve("onClose")}))}();var e=l(oe,50);w._debouncedChange=l(P,300),w.daysContainer&&!/iPhone|iPad|iPod/i.test(navigator.userAgent)&&N(w.daysContainer,"mouseover",(function(e){"range"===w.config.mode&&ie(g(e))}));N(w._input,"keydown",ae),void 0!==w.calendarContainer&&N(w.calendarContainer,"keydown",ae);w.config.inline||w.config.static||N(window,"resize",e);void 0!==window.ontouchstart?N(window.document,"touchstart",Q):N(window.document,"mousedown",Q);N(window.document,"focus",Q,{capture:!0}),!0===w.config.clickOpens&&(N(w._input,"focus",w.open),N(w._input,"click",w.open));void 0!==w.daysContainer&&(N(w.monthNav,"click",ye),N(w.monthNav,["keyup","increment"],A),N(w.daysContainer,"click",fe));if(void 0!==w.timeContainer&&void 0!==w.minuteElement&&void 0!==w.hourElement){var n=function(e){return g(e).select()};N(w.timeContainer,["increment"],I),N(w.timeContainer,"blur",I,{capture:!0}),N(w.timeContainer,"click",H),N([w.hourElement,w.minuteElement],["focus","click"],n),void 0!==w.secondElement&&N(w.secondElement,"focus",(function(){return w.secondElement&&w.secondElement.select()})),void 0!==w.amPM&&N(w.amPM,"click",(function(e){I(e),P()}))}w.config.allowInput&&N(w._input,"blur",te)}(),(w.selectedDates.length||w.config.noCalendar)&&(w.config.enableTime&&O(w.config.noCalendar?w.latestSelectedDateObj:void 0),Me(!1)),k();var n=/^((?!chrome|android).)*safari/i.test(navigator.userAgent);!w.isMobile&&n&&se(),ve("onReady")}(),w}function k(e,n){for(var t=Array.prototype.slice.call(e).filter((function(e){return e instanceof HTMLElement})),a=[],i=0;i<t.length;i++){var o=t[i];try{if(null!==o.getAttribute("data-fp-omit"))continue;void 0!==o._flatpickr&&(o._flatpickr.destroy(),o._flatpickr=void 0),o._flatpickr=T(o,n||{}),a.push(o._flatpickr)}catch(e){console.error(e)}}return 1===a.length?a[0]:a}"undefined"!=typeof HTMLElement&&"undefined"!=typeof HTMLCollection&&"undefined"!=typeof NodeList&&(HTMLCollection.prototype.flatpickr=NodeList.prototype.flatpickr=function(e){return k(this,e)},HTMLElement.prototype.flatpickr=function(e){return k([this],e)});var S=function(e,n){return"string"==typeof e?k(window.document.querySelectorAll(e),n):e instanceof Node?k([e],n):k(e,n)};return S.defaultConfig={},S.l10ns={en:e({},i),default:e({},i)},S.localize=function(n){S.l10ns.default=e(e({},S.l10ns.default),n)},S.setDefaults=function(n){S.defaultConfig=e(e({},S.defaultConfig),n)},S.parseDate=C({}),S.formatDate=b({}),S.compareDates=M,"undefined"!=typeof jQuery&&void 0!==jQuery.fn&&(jQuery.fn.flatpickr=function(e){return k(this,e)}),Date.prototype.fp_incr=function(e){return new Date(this.getFullYear(),this.getMonth(),this.getDate()+("string"==typeof e?parseInt(e,10):e))},"undefined"!=typeof window&&(window.flatpickr=S),S}));
diff --git a/asset/js/vendor/flatpickr/l10n/ar.js b/asset/js/vendor/flatpickr/l10n/ar.js
new file mode 100644
index 0000000..221dc0f
--- /dev/null
+++ b/asset/js/vendor/flatpickr/l10n/ar.js
@@ -0,0 +1,62 @@
+(function (global, factory) {
+ typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) :
+ typeof define === 'function' && define.icinga ? define(["exports"], factory) :
+ (global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.ar = {}));
+}(this, (function (exports) { 'use strict';
+
+ var fp = typeof window !== "undefined" && window.flatpickr !== undefined
+ ? window.flatpickr
+ : {
+ l10ns: {},
+ };
+ var Arabic = {
+ weekdays: {
+ shorthand: ["أحد", "اثنين", "ثلاثاء", "أربعاء", "خميس", "جمعة", "سبت"],
+ longhand: [
+ "الأحد",
+ "الاثنين",
+ "الثلاثاء",
+ "الأربعاء",
+ "الخميس",
+ "الجمعة",
+ "السبت",
+ ],
+ },
+ months: {
+ shorthand: ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12"],
+ longhand: [
+ "يناير",
+ "فبراير",
+ "مارس",
+ "أبريل",
+ "مايو",
+ "يونيو",
+ "يوليو",
+ "أغسطس",
+ "سبتمبر",
+ "أكتوبر",
+ "نوفمبر",
+ "ديسمبر",
+ ],
+ },
+ firstDayOfWeek: 6,
+ rangeSeparator: " إلى ",
+ weekAbbreviation: "Wk",
+ scrollTitle: "قم بالتمرير للزيادة",
+ toggleTitle: "اضغط للتبديل",
+ amPM: ["ص", "م"],
+ yearAriaLabel: "سنة",
+ monthAriaLabel: "شهر",
+ hourAriaLabel: "ساعة",
+ minuteAriaLabel: "دقيقة",
+ time_24hr: false,
+ };
+ fp.l10ns.ar = Arabic;
+ var ar = fp.l10ns;
+
+ exports.Arabic = Arabic;
+ exports.default = ar;
+
+ Object.defineProperty(exports, '__esModule', { value: true });
+
+})));
diff --git a/asset/js/vendor/flatpickr/l10n/de.js b/asset/js/vendor/flatpickr/l10n/de.js
new file mode 100644
index 0000000..b86f784
--- /dev/null
+++ b/asset/js/vendor/flatpickr/l10n/de.js
@@ -0,0 +1,70 @@
+(function (global, factory) {
+ typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) :
+ typeof define === 'function' && define.icinga ? define(["exports"], factory) :
+ (global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.de = {}));
+}(this, (function (exports) { 'use strict';
+
+ var fp = typeof window !== "undefined" && window.flatpickr !== undefined
+ ? window.flatpickr
+ : {
+ l10ns: {},
+ };
+ var German = {
+ weekdays: {
+ shorthand: ["So", "Mo", "Di", "Mi", "Do", "Fr", "Sa"],
+ longhand: [
+ "Sonntag",
+ "Montag",
+ "Dienstag",
+ "Mittwoch",
+ "Donnerstag",
+ "Freitag",
+ "Samstag",
+ ],
+ },
+ months: {
+ shorthand: [
+ "Jan",
+ "Feb",
+ "Mär",
+ "Apr",
+ "Mai",
+ "Jun",
+ "Jul",
+ "Aug",
+ "Sep",
+ "Okt",
+ "Nov",
+ "Dez",
+ ],
+ longhand: [
+ "Januar",
+ "Februar",
+ "März",
+ "April",
+ "Mai",
+ "Juni",
+ "Juli",
+ "August",
+ "September",
+ "Oktober",
+ "November",
+ "Dezember",
+ ],
+ },
+ firstDayOfWeek: 1,
+ weekAbbreviation: "KW",
+ rangeSeparator: " bis ",
+ scrollTitle: "Zum Ändern scrollen",
+ toggleTitle: "Zum Umschalten klicken",
+ time_24hr: true,
+ };
+ fp.l10ns.de = German;
+ var de = fp.l10ns;
+
+ exports.German = German;
+ exports.default = de;
+
+ Object.defineProperty(exports, '__esModule', { value: true });
+
+})));
diff --git a/asset/js/vendor/flatpickr/l10n/es.js b/asset/js/vendor/flatpickr/l10n/es.js
new file mode 100644
index 0000000..4da4635
--- /dev/null
+++ b/asset/js/vendor/flatpickr/l10n/es.js
@@ -0,0 +1,70 @@
+(function (global, factory) {
+ typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) :
+ typeof define === 'function' && define.icinga ? define(["exports"], factory) :
+ (global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.es = {}));
+}(this, (function (exports) { 'use strict';
+
+ var fp = typeof window !== "undefined" && window.flatpickr !== undefined
+ ? window.flatpickr
+ : {
+ l10ns: {},
+ };
+ var Spanish = {
+ weekdays: {
+ shorthand: ["Dom", "Lun", "Mar", "Mié", "Jue", "Vie", "Sáb"],
+ longhand: [
+ "Domingo",
+ "Lunes",
+ "Martes",
+ "Miércoles",
+ "Jueves",
+ "Viernes",
+ "Sábado",
+ ],
+ },
+ months: {
+ shorthand: [
+ "Ene",
+ "Feb",
+ "Mar",
+ "Abr",
+ "May",
+ "Jun",
+ "Jul",
+ "Ago",
+ "Sep",
+ "Oct",
+ "Nov",
+ "Dic",
+ ],
+ longhand: [
+ "Enero",
+ "Febrero",
+ "Marzo",
+ "Abril",
+ "Mayo",
+ "Junio",
+ "Julio",
+ "Agosto",
+ "Septiembre",
+ "Octubre",
+ "Noviembre",
+ "Diciembre",
+ ],
+ },
+ ordinal: function () {
+ return "º";
+ },
+ firstDayOfWeek: 1,
+ rangeSeparator: " a ",
+ time_24hr: true,
+ };
+ fp.l10ns.es = Spanish;
+ var es = fp.l10ns;
+
+ exports.Spanish = Spanish;
+ exports.default = es;
+
+ Object.defineProperty(exports, '__esModule', { value: true });
+
+})));
diff --git a/asset/js/vendor/flatpickr/l10n/fi.js b/asset/js/vendor/flatpickr/l10n/fi.js
new file mode 100644
index 0000000..3510078
--- /dev/null
+++ b/asset/js/vendor/flatpickr/l10n/fi.js
@@ -0,0 +1,69 @@
+(function (global, factory) {
+ typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) :
+ typeof define === 'function' && define.icinga ? define(["exports"], factory) :
+ (global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.fi = {}));
+}(this, (function (exports) { 'use strict';
+
+ var fp = typeof window !== "undefined" && window.flatpickr !== undefined
+ ? window.flatpickr
+ : {
+ l10ns: {},
+ };
+ var Finnish = {
+ firstDayOfWeek: 1,
+ weekdays: {
+ shorthand: ["su", "ma", "ti", "ke", "to", "pe", "la"],
+ longhand: [
+ "sunnuntai",
+ "maanantai",
+ "tiistai",
+ "keskiviikko",
+ "torstai",
+ "perjantai",
+ "lauantai",
+ ],
+ },
+ months: {
+ shorthand: [
+ "tammi",
+ "helmi",
+ "maalis",
+ "huhti",
+ "touko",
+ "kesä",
+ "heinä",
+ "elo",
+ "syys",
+ "loka",
+ "marras",
+ "joulu",
+ ],
+ longhand: [
+ "tammikuu",
+ "helmikuu",
+ "maaliskuu",
+ "huhtikuu",
+ "toukokuu",
+ "kesäkuu",
+ "heinäkuu",
+ "elokuu",
+ "syyskuu",
+ "lokakuu",
+ "marraskuu",
+ "joulukuu",
+ ],
+ },
+ ordinal: function () {
+ return ".";
+ },
+ time_24hr: true,
+ };
+ fp.l10ns.fi = Finnish;
+ var fi = fp.l10ns;
+
+ exports.Finnish = Finnish;
+ exports.default = fi;
+
+ Object.defineProperty(exports, '__esModule', { value: true });
+
+})));
diff --git a/asset/js/vendor/flatpickr/l10n/fr.js b/asset/js/vendor/flatpickr/l10n/fr.js
new file mode 100644
index 0000000..4d5edf3
--- /dev/null
+++ b/asset/js/vendor/flatpickr/l10n/fr.js
@@ -0,0 +1,75 @@
+(function (global, factory) {
+ typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) :
+ typeof define === 'function' && define.icinga ? define(["exports"], factory) :
+ (global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.fr = {}));
+}(this, (function (exports) { 'use strict';
+
+ var fp = typeof window !== "undefined" && window.flatpickr !== undefined
+ ? window.flatpickr
+ : {
+ l10ns: {},
+ };
+ var French = {
+ firstDayOfWeek: 1,
+ weekdays: {
+ shorthand: ["dim", "lun", "mar", "mer", "jeu", "ven", "sam"],
+ longhand: [
+ "dimanche",
+ "lundi",
+ "mardi",
+ "mercredi",
+ "jeudi",
+ "vendredi",
+ "samedi",
+ ],
+ },
+ months: {
+ shorthand: [
+ "janv",
+ "févr",
+ "mars",
+ "avr",
+ "mai",
+ "juin",
+ "juil",
+ "août",
+ "sept",
+ "oct",
+ "nov",
+ "déc",
+ ],
+ longhand: [
+ "janvier",
+ "février",
+ "mars",
+ "avril",
+ "mai",
+ "juin",
+ "juillet",
+ "août",
+ "septembre",
+ "octobre",
+ "novembre",
+ "décembre",
+ ],
+ },
+ ordinal: function (nth) {
+ if (nth > 1)
+ return "";
+ return "er";
+ },
+ rangeSeparator: " au ",
+ weekAbbreviation: "Sem",
+ scrollTitle: "Défiler pour augmenter la valeur",
+ toggleTitle: "Cliquer pour basculer",
+ time_24hr: true,
+ };
+ fp.l10ns.fr = French;
+ var fr = fp.l10ns;
+
+ exports.French = French;
+ exports.default = fr;
+
+ Object.defineProperty(exports, '__esModule', { value: true });
+
+})));
diff --git a/asset/js/vendor/flatpickr/l10n/it.js b/asset/js/vendor/flatpickr/l10n/it.js
new file mode 100644
index 0000000..674f172
--- /dev/null
+++ b/asset/js/vendor/flatpickr/l10n/it.js
@@ -0,0 +1,71 @@
+(function (global, factory) {
+ typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) :
+ typeof define === 'function' && define.icinga ? define(["exports"], factory) :
+ (global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.it = {}));
+}(this, (function (exports) { 'use strict';
+
+ var fp = typeof window !== "undefined" && window.flatpickr !== undefined
+ ? window.flatpickr
+ : {
+ l10ns: {},
+ };
+ var Italian = {
+ weekdays: {
+ shorthand: ["Dom", "Lun", "Mar", "Mer", "Gio", "Ven", "Sab"],
+ longhand: [
+ "Domenica",
+ "Lunedì",
+ "Martedì",
+ "Mercoledì",
+ "Giovedì",
+ "Venerdì",
+ "Sabato",
+ ],
+ },
+ months: {
+ shorthand: [
+ "Gen",
+ "Feb",
+ "Mar",
+ "Apr",
+ "Mag",
+ "Giu",
+ "Lug",
+ "Ago",
+ "Set",
+ "Ott",
+ "Nov",
+ "Dic",
+ ],
+ longhand: [
+ "Gennaio",
+ "Febbraio",
+ "Marzo",
+ "Aprile",
+ "Maggio",
+ "Giugno",
+ "Luglio",
+ "Agosto",
+ "Settembre",
+ "Ottobre",
+ "Novembre",
+ "Dicembre",
+ ],
+ },
+ firstDayOfWeek: 1,
+ ordinal: function () { return "°"; },
+ rangeSeparator: " al ",
+ weekAbbreviation: "Se",
+ scrollTitle: "Scrolla per aumentare",
+ toggleTitle: "Clicca per cambiare",
+ time_24hr: true,
+ };
+ fp.l10ns.it = Italian;
+ var it = fp.l10ns;
+
+ exports.Italian = Italian;
+ exports.default = it;
+
+ Object.defineProperty(exports, '__esModule', { value: true });
+
+})));
diff --git a/asset/js/vendor/flatpickr/l10n/ja.js b/asset/js/vendor/flatpickr/l10n/ja.js
new file mode 100644
index 0000000..fd15e34
--- /dev/null
+++ b/asset/js/vendor/flatpickr/l10n/ja.js
@@ -0,0 +1,71 @@
+(function (global, factory) {
+ typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) :
+ typeof define === 'function' && define.icinga ? define(["exports"], factory) :
+ (global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.ja = {}));
+}(this, (function (exports) { 'use strict';
+
+ var fp = typeof window !== "undefined" && window.flatpickr !== undefined
+ ? window.flatpickr
+ : {
+ l10ns: {},
+ };
+ var Japanese = {
+ weekdays: {
+ shorthand: ["日", "月", "火", "水", "木", "金", "土"],
+ longhand: [
+ "日曜日",
+ "月曜日",
+ "火曜日",
+ "水曜日",
+ "木曜日",
+ "金曜日",
+ "土曜日",
+ ],
+ },
+ months: {
+ shorthand: [
+ "1月",
+ "2月",
+ "3月",
+ "4月",
+ "5月",
+ "6月",
+ "7月",
+ "8月",
+ "9月",
+ "10月",
+ "11月",
+ "12月",
+ ],
+ longhand: [
+ "1月",
+ "2月",
+ "3月",
+ "4月",
+ "5月",
+ "6月",
+ "7月",
+ "8月",
+ "9月",
+ "10月",
+ "11月",
+ "12月",
+ ],
+ },
+ time_24hr: true,
+ rangeSeparator: " から ",
+ monthAriaLabel: "月",
+ amPM: ["午前", "午後"],
+ yearAriaLabel: "年",
+ hourAriaLabel: "時間",
+ minuteAriaLabel: "分",
+ };
+ fp.l10ns.ja = Japanese;
+ var ja = fp.l10ns;
+
+ exports.Japanese = Japanese;
+ exports.default = ja;
+
+ Object.defineProperty(exports, '__esModule', { value: true });
+
+})));
diff --git a/asset/js/vendor/flatpickr/l10n/pt.js b/asset/js/vendor/flatpickr/l10n/pt.js
new file mode 100644
index 0000000..7d6c605
--- /dev/null
+++ b/asset/js/vendor/flatpickr/l10n/pt.js
@@ -0,0 +1,66 @@
+(function (global, factory) {
+ typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) :
+ typeof define === 'function' && define.icinga ? define(["exports"], factory) :
+ (global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.pt = {}));
+}(this, (function (exports) { 'use strict';
+
+ var fp = typeof window !== "undefined" && window.flatpickr !== undefined
+ ? window.flatpickr
+ : {
+ l10ns: {},
+ };
+ var Portuguese = {
+ weekdays: {
+ shorthand: ["Dom", "Seg", "Ter", "Qua", "Qui", "Sex", "Sáb"],
+ longhand: [
+ "Domingo",
+ "Segunda-feira",
+ "Terça-feira",
+ "Quarta-feira",
+ "Quinta-feira",
+ "Sexta-feira",
+ "Sábado",
+ ],
+ },
+ months: {
+ shorthand: [
+ "Jan",
+ "Fev",
+ "Mar",
+ "Abr",
+ "Mai",
+ "Jun",
+ "Jul",
+ "Ago",
+ "Set",
+ "Out",
+ "Nov",
+ "Dez",
+ ],
+ longhand: [
+ "Janeiro",
+ "Fevereiro",
+ "Março",
+ "Abril",
+ "Maio",
+ "Junho",
+ "Julho",
+ "Agosto",
+ "Setembro",
+ "Outubro",
+ "Novembro",
+ "Dezembro",
+ ],
+ },
+ rangeSeparator: " até ",
+ time_24hr: true,
+ };
+ fp.l10ns.pt = Portuguese;
+ var pt = fp.l10ns;
+
+ exports.Portuguese = Portuguese;
+ exports.default = pt;
+
+ Object.defineProperty(exports, '__esModule', { value: true });
+
+})));
diff --git a/asset/js/vendor/flatpickr/l10n/ru.js b/asset/js/vendor/flatpickr/l10n/ru.js
new file mode 100644
index 0000000..5065f0b
--- /dev/null
+++ b/asset/js/vendor/flatpickr/l10n/ru.js
@@ -0,0 +1,75 @@
+(function (global, factory) {
+ typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) :
+ typeof define === 'function' && define.icinga ? define(["exports"], factory) :
+ (global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.ru = {}));
+}(this, (function (exports) { 'use strict';
+
+ var fp = typeof window !== "undefined" && window.flatpickr !== undefined
+ ? window.flatpickr
+ : {
+ l10ns: {},
+ };
+ var Russian = {
+ weekdays: {
+ shorthand: ["Вс", "Пн", "Вт", "Ср", "Чт", "Пт", "Сб"],
+ longhand: [
+ "Воскресенье",
+ "Понедельник",
+ "Вторник",
+ "Среда",
+ "Четверг",
+ "Пятница",
+ "Суббота",
+ ],
+ },
+ months: {
+ shorthand: [
+ "Янв",
+ "Фев",
+ "Март",
+ "Апр",
+ "Май",
+ "Июнь",
+ "Июль",
+ "Авг",
+ "Сен",
+ "Окт",
+ "Ноя",
+ "Дек",
+ ],
+ longhand: [
+ "Январь",
+ "Февраль",
+ "Март",
+ "Апрель",
+ "Май",
+ "Июнь",
+ "Июль",
+ "Август",
+ "Сентябрь",
+ "Октябрь",
+ "Ноябрь",
+ "Декабрь",
+ ],
+ },
+ firstDayOfWeek: 1,
+ ordinal: function () {
+ return "";
+ },
+ rangeSeparator: " — ",
+ weekAbbreviation: "Нед.",
+ scrollTitle: "Прокрутите для увеличения",
+ toggleTitle: "Нажмите для переключения",
+ amPM: ["ДП", "ПП"],
+ yearAriaLabel: "Год",
+ time_24hr: true,
+ };
+ fp.l10ns.ru = Russian;
+ var ru = fp.l10ns;
+
+ exports.Russian = Russian;
+ exports.default = ru;
+
+ Object.defineProperty(exports, '__esModule', { value: true });
+
+})));
diff --git a/asset/js/vendor/flatpickr/l10n/uk.js b/asset/js/vendor/flatpickr/l10n/uk.js
new file mode 100644
index 0000000..a2eaa71
--- /dev/null
+++ b/asset/js/vendor/flatpickr/l10n/uk.js
@@ -0,0 +1,66 @@
+(function (global, factory) {
+ typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) :
+ typeof define === 'function' && define.icinga ? define(["exports"], factory) :
+ (global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.uk = {}));
+}(this, (function (exports) { 'use strict';
+
+ var fp = typeof window !== "undefined" && window.flatpickr !== undefined
+ ? window.flatpickr
+ : {
+ l10ns: {},
+ };
+ var Ukrainian = {
+ firstDayOfWeek: 1,
+ weekdays: {
+ shorthand: ["Нд", "Пн", "Вт", "Ср", "Чт", "Пт", "Сб"],
+ longhand: [
+ "Неділя",
+ "Понеділок",
+ "Вівторок",
+ "Середа",
+ "Четвер",
+ "П'ятниця",
+ "Субота",
+ ],
+ },
+ months: {
+ shorthand: [
+ "Січ",
+ "Лют",
+ "Бер",
+ "Кві",
+ "Тра",
+ "Чер",
+ "Лип",
+ "Сер",
+ "Вер",
+ "Жов",
+ "Лис",
+ "Гру",
+ ],
+ longhand: [
+ "Січень",
+ "Лютий",
+ "Березень",
+ "Квітень",
+ "Травень",
+ "Червень",
+ "Липень",
+ "Серпень",
+ "Вересень",
+ "Жовтень",
+ "Листопад",
+ "Грудень",
+ ],
+ },
+ time_24hr: true,
+ };
+ fp.l10ns.uk = Ukrainian;
+ var uk = fp.l10ns;
+
+ exports.Ukrainian = Ukrainian;
+ exports.default = uk;
+
+ Object.defineProperty(exports, '__esModule', { value: true });
+
+})));
diff --git a/asset/js/widget/BaseInput.js b/asset/js/widget/BaseInput.js
new file mode 100644
index 0000000..269d6f7
--- /dev/null
+++ b/asset/js/widget/BaseInput.js
@@ -0,0 +1,1049 @@
+define(["../notjQuery", "Completer"], function ($, Completer) {
+
+ "use strict";
+
+ class BaseInput {
+ constructor(input) {
+ this.input = input;
+ this.disabled = false;
+ this.separator = '';
+ this.usedTerms = [];
+ this.completer = null;
+ this.lastCompletedTerm = null;
+ this.manageRequired = input.required;
+ this._dataInput = null;
+ this._termInput = null;
+ this._termContainer = null;
+ }
+
+ get dataInput() {
+ if (this._dataInput === null) {
+ this._dataInput = document.querySelector(this.input.dataset.dataInput);
+ }
+
+ return this._dataInput;
+ }
+
+ get termInput() {
+ if (this._termInput === null) {
+ this._termInput = document.querySelector(this.input.dataset.termInput);
+ }
+
+ return this._termInput;
+ }
+
+ get termContainer() {
+ if (this._termContainer === null) {
+ this._termContainer = document.querySelector(this.input.dataset.termContainer);
+ }
+
+ return this._termContainer;
+ }
+
+ bind() {
+ // Form submissions
+ $(this.input.form).on('submit', this.onSubmit, this);
+ $(this.input.form).on(
+ 'click', 'button:not([type]), button[type="submit"], input[type="submit"]', this.onButtonClick, this);
+
+ // User interactions
+ $(this.input).on('input', this.onInput, this);
+ $(this.input).on('keydown', this.onKeyDown, this);
+ $(this.input).on('keyup', this.onKeyUp, this);
+ $(this.input).on('blur', this.onInputBlur, this);
+ $(this.input).on('focusin', this.onTermFocus, this);
+ $(this.termContainer).on('input', '[data-label]', this.onInput, this);
+ $(this.termContainer).on('keydown', '[data-label]', this.onKeyDown, this);
+ $(this.termContainer).on('keyup', '[data-label]', this.onKeyUp, this);
+ $(this.termContainer).on('focusout', '[data-index]', this.onTermFocusOut, this);
+ $(this.termContainer).on('focusin', '[data-index]', this.onTermFocus, this);
+
+ // Copy/Paste
+ $(this.input).on('paste', this.onPaste, this);
+ $(this.input).on('copy', this.onCopyAndCut, this);
+ $(this.input).on('cut', this.onCopyAndCut, this);
+
+ // Should terms be completed?
+ if (this.input.dataset.suggestUrl) {
+ if (this.completer === null) {
+ this.completer = new Completer(this.input, true);
+ this.completer.bind(this.termContainer);
+ }
+
+ $(this.input).on('suggestion', this.onSuggestion, this);
+ $(this.input).on('completion', this.onCompletion, this);
+ $(this.termContainer).on('suggestion', '[data-label]', this.onSuggestion, this);
+ $(this.termContainer).on('completion', '[data-label]', this.onCompletion, this);
+ }
+
+ return this;
+ }
+
+ refresh(input) {
+ if (input === this.input) {
+ // If the DOM node is still the same, nothing has changed
+ return;
+ }
+
+ this._termInput = null;
+ this._termContainer = null;
+
+ this.input = input;
+ this.bind();
+
+ if (this.completer !== null) {
+ this.completer.refresh(input, this.termContainer);
+ }
+
+ if (! this.restoreTerms()) {
+ this.reset();
+ }
+ }
+
+ reset() {
+ this.usedTerms = [];
+ this.lastCompletedTerm = null;
+
+ this.togglePlaceholder();
+ this.termInput.value = '';
+ this.termContainer.innerHTML = '';
+ }
+
+ destroy() {
+ this._termContainer = null;
+ this._termInput = null;
+ this.input = null;
+
+ if (this.completer !== null) {
+ this.completer.destroy();
+ this.completer = null;
+ }
+ }
+
+ disable() {
+ this.disabled = true;
+ this.input.disabled = true;
+ this.input.form.classList.add('disabled');
+ this.termContainer.querySelectorAll('[data-index]').forEach(el => el.firstChild.disabled = true);
+
+ if (this.completer !== null) {
+ this.completer.reset();
+ }
+ }
+
+ enable() {
+ this.input.disabled = false;
+ this.input.form.classList.remove('disabled');
+ this.termContainer.querySelectorAll('[data-index]').forEach(el => el.firstChild.disabled = false);
+ this.disabled = false;
+ }
+
+ restoreTerms() {
+ if (this.hasTerms()) {
+ this.usedTerms.forEach((termData, termIndex) => this.addTerm(termData, termIndex));
+ this.togglePlaceholder();
+ this.clearPartialTerm(this.input);
+ } else {
+ this.registerTerms();
+ this.togglePlaceholder();
+ }
+
+ if (this.hasTerms()) {
+ if (this.manageRequired) {
+ this.input.required = false;
+ }
+
+ return true;
+ }
+
+ return false;
+ }
+
+ registerTerms() {
+ this.termContainer.querySelectorAll('[data-index]').forEach((label) => {
+ let termData = { ...label.dataset };
+ delete termData.index;
+
+ if (label.className) {
+ termData['class'] = label.className;
+ }
+
+ if (label.title) {
+ termData['title'] = label.title;
+ }
+
+ this.registerTerm(this.decodeTerm(termData), label.dataset.index);
+ });
+ }
+
+ registerTerm(termData, termIndex = null) {
+ if (termIndex !== null) {
+ this.usedTerms.splice(termIndex, 0, termData);
+ return termIndex;
+ } else {
+ return this.usedTerms.push(termData) - 1;
+ }
+ }
+
+ updateTerms(changedTerms) {
+ // Reset the data input, otherwise the value remains and is sent continuously with subsequent requests
+ this.dataInput.value = '';
+
+ if (changedTerms === 'bogus') {
+ return;
+ }
+
+ let changedIndices = Object.keys(changedTerms);
+ if (! changedIndices.length) {
+ // Perform a partial reset. this.reset() empties the termContainer, which isn't desired here
+ this.usedTerms = [];
+ this.lastCompletedTerm = null;
+
+ this.registerTerms();
+ this.togglePlaceholder();
+ this.termInput.value = '';
+ }
+
+ for (const termIndex of changedIndices) {
+ let label = this.termContainer.querySelector(`[data-index="${ termIndex }"]`);
+ if (! label) {
+ continue;
+ }
+
+ let input = label.firstChild;
+ let termData = changedTerms[termIndex];
+
+ if (termData.label) {
+ this.writePartialTerm(termData.label, input);
+ }
+
+ this.updateTermData(termData, input);
+ this.usedTerms[termIndex] = termData;
+ }
+ }
+
+ clearPartialTerm(input) {
+ if (this.completer !== null) {
+ this.completer.reset();
+ }
+
+ this.writePartialTerm('', input);
+ }
+
+ writePartialTerm(value, input) {
+ input.value = value;
+ this.updateTermData({ label: value }, input);
+ }
+
+ readPartialTerm(input) {
+ return input.value.trim();
+ }
+
+ readFullTerm(input, termIndex = null) {
+ let value = this.readPartialTerm(input);
+ if (! value && this.lastCompletedTerm === null) {
+ return false;
+ }
+
+ let termData = {};
+
+ if (termIndex !== null) {
+ termData = { ...this.usedTerms[termIndex] };
+ }
+
+ if (value) {
+ termData.label = value;
+ termData.search = value;
+ }
+
+ if (this.lastCompletedTerm !== null) {
+ if ('type' in this.lastCompletedTerm && this.lastCompletedTerm.type === 'terms') {
+ if (typeof this.lastCompletedTerm.terms === 'string') {
+ termData = JSON.parse(this.lastCompletedTerm.terms);
+ } else {
+ termData = this.lastCompletedTerm.terms;
+ }
+ } else if (termData.label === this.lastCompletedTerm.label) {
+ Object.assign(termData, this.lastCompletedTerm);
+ }
+
+ this.lastCompletedTerm = null;
+ }
+
+ return termData;
+ }
+
+ exchangeTerm() {
+ if (this.completer !== null) {
+ this.completer.reset();
+ }
+
+ let termData = this.readFullTerm(this.input);
+ if (! termData) {
+ return {};
+ }
+
+ let addedTerms = {};
+ if (Array.isArray(termData)) {
+ for (let data of termData) {
+ this.addTerm(data);
+ addedTerms[this.usedTerms.length - 1] = data;
+ }
+ } else {
+ this.addTerm(termData);
+ addedTerms[this.usedTerms.length - 1] = termData;
+ }
+
+ this.clearPartialTerm(this.input);
+
+ return addedTerms;
+ }
+
+ insertTerm(termData, termIndex) {
+ this.reIndexTerms(termIndex, 1, true);
+ this.registerTerm(termData, termIndex);
+ return this.insertRenderedTerm(this.renderTerm(termData, termIndex));
+ }
+
+ insertRenderedTerm(label) {
+ let next = this.termContainer.querySelector(`[data-index="${ label.dataset.index + 1 }"]`);
+ this.termContainer.insertBefore(label, next);
+ return label;
+ }
+
+ addTerm(termData, termIndex = null) {
+ if (termIndex === null) {
+ termIndex = this.registerTerm(termData);
+ }
+
+ this.addRenderedTerm(this.renderTerm(termData, termIndex));
+ }
+
+ addRenderedTerm(label) {
+ this.termContainer.appendChild(label);
+ }
+
+ hasTerms() {
+ return this.usedTerms.length > 0;
+ }
+
+ hasSyntaxError(input) {
+ if (typeof input === 'undefined') {
+ input = this.input;
+ }
+
+ return 'hasSyntaxError' in input.dataset;
+ }
+
+ clearSyntaxError(input) {
+ if (typeof input === 'undefined') {
+ input = this.input;
+ }
+
+ delete input.dataset.hasSyntaxError;
+ input.removeAttribute('pattern');
+ input.removeAttribute('title');
+ }
+
+ getQueryString() {
+ return this.termsToQueryString(this.usedTerms);
+ }
+
+ checkValidity(input) {
+ if (input.pattern && ! input.checkValidity()) {
+ if (! input.value.match(input.pattern)) {
+ if (input.dataset.invalidMsg) {
+ input.setCustomValidity(input.dataset.invalidMsg);
+ }
+
+ return false;
+ }
+
+ // If the pattern matches, reset the custom validity, otherwise the value is still invalid.
+ input.setCustomValidity('');
+ }
+
+ // The pattern isn't set or it matches. Any other custom validity must not be accounted for here.
+ return true;
+ }
+
+ reportValidity(element) {
+ setTimeout(() => element.reportValidity(), 0);
+ }
+
+ validate(element) {
+ if (! this.checkValidity(element)) {
+ this.reportValidity(element);
+
+ return false;
+ }
+
+ return true;
+ }
+
+ saveTerm(input, updateDOM = true, force = false) {
+ if (! this.checkValidity(input)) {
+ return false;
+ }
+
+ let termIndex = input.parentNode.dataset.index;
+ let termData = this.readFullTerm(input, termIndex);
+
+ // Only save if something has changed, unless forced
+ if (termData === false) {
+ console.warn('[BaseInput] Input is empty, cannot save');
+ } else if (force || this.usedTerms[termIndex].label !== termData.label) {
+ let oldTermData = this.usedTerms[termIndex];
+ this.usedTerms[termIndex] = termData;
+ this.updateTermData(termData, input);
+
+ return oldTermData;
+ }
+
+ return false;
+ }
+
+ updateTermData(termData, input) {
+ let label = input.parentNode;
+ label.dataset.label = termData.label;
+
+ if (!! termData.search || termData.search === '') {
+ label.dataset.search = termData.search;
+ }
+
+ if (!! termData.title) {
+ label.title = termData.title;
+ } else {
+ label.title = '';
+ }
+
+ if (termData.pattern) {
+ input.pattern = termData.pattern;
+ delete termData.pattern;
+
+ if (termData.invalidMsg) {
+ input.dataset.invalidMsg = termData.invalidMsg;
+ delete termData.invalidMsg;
+ }
+
+ this.validate(input);
+ }
+ }
+
+ termsToQueryString(terms) {
+ return terms.map(e => this.encodeTerm(e).search).join(this.separator).trim();
+ }
+
+ lastTerm() {
+ if (! this.hasTerms()) {
+ return null;
+ }
+
+ return this.usedTerms[this.usedTerms.length - 1];
+ }
+
+ popTerm() {
+ let lastTermIndex = this.usedTerms.length - 1;
+ return this.removeTerm(this.termContainer.querySelector(`[data-index="${ lastTermIndex }"]`));
+ }
+
+ removeTerm(label, updateDOM = true) {
+ if (this.completer !== null) {
+ this.completer.reset();
+ }
+
+ let termIndex = Number(label.dataset.index);
+
+ // Re-index following remaining terms
+ this.reIndexTerms(termIndex);
+
+ // Cut the term's data
+ let [termData] = this.usedTerms.splice(termIndex, 1);
+
+ // Avoid saving the term, it's removed after all
+ label.firstChild.skipSaveOnBlur = true;
+
+ if (updateDOM) {
+ // Remove it from the DOM
+ this.removeRenderedTerm(label);
+ }
+
+ return termData;
+ }
+
+ removeRenderedTerm(label) {
+ label.remove();
+ }
+
+ removeRange(labels) {
+ let from = Number(labels[0].dataset.index);
+ let to = Number(labels[labels.length - 1].dataset.index);
+ let deleteCount = to - from + 1;
+
+ if (to < this.usedTerms.length - 1) {
+ // Only re-index if there's something left
+ this.reIndexTerms(to, deleteCount);
+ }
+
+ let removedData = this.usedTerms.splice(from, deleteCount);
+
+ this.removeRenderedRange(labels);
+
+ let removedTerms = {};
+ for (let i = from; removedData.length; i++) {
+ removedTerms[i] = removedData.shift();
+ }
+
+ return removedTerms;
+ }
+
+ removeRenderedRange(labels) {
+ labels.forEach(label => this.removeRenderedTerm(label));
+ }
+
+ reIndexTerms(from, howMuch = 1, forward = false) {
+ if (forward) {
+ for (let i = this.usedTerms.length - 1; i >= from; i--) {
+ let label = this.termContainer.querySelector(`[data-index="${ i }"]`);
+ label.dataset.index = `${ i + howMuch }`;
+ }
+ } else {
+ for (let i = ++from; i < this.usedTerms.length; i++) {
+ let label = this.termContainer.querySelector(`[data-index="${ i }"]`);
+ label.dataset.index = `${ i - howMuch }`;
+ }
+ }
+ }
+
+ complete(input, data) {
+ if (this.completer !== null) {
+ $(input).trigger('complete', data);
+ }
+ }
+
+ selectTerms() {
+ this.termContainer.querySelectorAll('[data-index]').forEach(el => el.classList.add('selected'));
+ }
+
+ deselectTerms() {
+ this.termContainer.querySelectorAll('.selected').forEach(el => el.classList.remove('selected'));
+ }
+
+ clearSelectedTerms() {
+ if (this.hasTerms()) {
+ let labels = this.termContainer.querySelectorAll('.selected');
+ if (labels.length) {
+ return this.removeRange(Array.from(labels));
+ }
+ }
+
+ return {};
+ }
+
+ togglePlaceholder() {
+ if (this.isTermDirectionVertical()) {
+ return;
+ }
+
+ let placeholder = '';
+
+ if (! this.hasTerms()) {
+ if (this.input.dataset.placeholder) {
+ placeholder = this.input.dataset.placeholder;
+ } else {
+ return;
+ }
+ } else if (this.input.placeholder) {
+ if (! this.input.dataset.placeholder) {
+ this.input.dataset.placeholder = this.input.placeholder;
+ }
+ }
+
+ this.input.placeholder = placeholder;
+ }
+
+ renderTerm(termData, termIndex) {
+ let label = $.render('<label><input type="text"></label>');
+
+ if (termData.class) {
+ label.classList.add(termData.class);
+ }
+
+ if (termData.title) {
+ label.title = termData.title;
+ }
+
+ label.dataset.label = termData.label;
+ label.dataset.search = termData.search;
+ label.dataset.index = termIndex;
+
+ label.firstChild.value = termData.label;
+
+ return label;
+ }
+
+ encodeTerm(termData) {
+ termData = { ...termData };
+ termData.search = encodeURIComponent(termData.search);
+
+ return termData;
+ }
+
+ decodeTerm(termData) {
+ termData.search = decodeURIComponent(termData.search);
+
+ return termData;
+ }
+
+ shouldNotAutoSubmit() {
+ return 'noAutoSubmit' in this.input.dataset;
+ }
+
+ shouldNotAutoSubmitOnRemove() {
+ return 'noAutoSubmitOnRemove' in this.input.dataset;
+ }
+
+ autoSubmit(input, changeType, data) {
+ if (this.shouldNotAutoSubmit() || (changeType === 'remove' && this.shouldNotAutoSubmitOnRemove())) {
+ return;
+ }
+
+ if (changeType === 'save' && 'terms' in data) {
+ // Replace old term data with the new one, as required by the backend
+ for (const termIndex of Object.keys(data['terms'])) {
+ data['terms'][termIndex] = this.usedTerms[termIndex];
+ }
+ }
+
+ if (changeType === 'remove' && ! Object.keys(data['terms']).length) {
+ return;
+ }
+
+ this.dataInput.value = JSON.stringify({
+ type: changeType,
+ ...data
+ });
+
+ let eventData = { submittedBy: input };
+ if (changeType === 'paste') {
+ // Ensure that what's pasted is also transmitted as value
+ eventData['terms'] = this.termsToQueryString(data['terms']) + this.separator + data['input'];
+ }
+
+ $(this.input.form).trigger('submit', eventData);
+ }
+
+ submitTerms(terms) {
+ $(this.input.form).trigger(
+ 'submit',
+ { terms: terms }
+ );
+ }
+
+ isTermDirectionVertical() {
+ return this.input.dataset.termDirection === 'vertical';
+ }
+
+ moveFocusForward(from = null) {
+ let toFocus;
+
+ let inputs = Array.from(this.termContainer.querySelectorAll('input'));
+ if (from === null) {
+ let focused = this.termContainer.querySelector('input:focus');
+ from = inputs.indexOf(focused);
+ }
+
+ if (from === -1) {
+ toFocus = inputs.shift();
+ if (typeof toFocus === 'undefined') {
+ toFocus = this.input;
+ }
+ } else if (from + 1 < inputs.length) {
+ toFocus = inputs[from + 1];
+ } else {
+ toFocus = this.input;
+ }
+
+ toFocus.selectionStart = toFocus.selectionEnd = 0;
+ $(toFocus).focus();
+
+ return toFocus;
+ }
+
+ moveFocusBackward(from = null) {
+ let toFocus;
+
+ let inputs = Array.from(this.termContainer.querySelectorAll('input'));
+ if (from === null) {
+ let focused = this.termContainer.querySelector('input:focus');
+ from = inputs.indexOf(focused);
+ }
+
+ if (from === -1) {
+ toFocus = inputs.pop();
+ } else if (from > 0 && from - 1 < inputs.length) {
+ toFocus = inputs[from - 1];
+ } else {
+ toFocus = this.input;
+ }
+
+ toFocus.selectionStart = toFocus.selectionEnd = toFocus.value.length;
+ $(toFocus).focus();
+
+ return toFocus;
+ }
+
+ /**
+ * Event listeners
+ */
+
+ onSubmit(event) {
+ // Unset the input's name, to prevent its submission (It may actually have a name, as no-js fallback)
+ this.input.name = '';
+
+ // Set the hidden input's value, it's what's sent
+ if (event.detail && 'terms' in event.detail) {
+ this.termInput.value = event.detail.terms;
+ } else {
+ let renderedTerms = this.termsToQueryString(this.usedTerms);
+ if (this.hasSyntaxError()) {
+ renderedTerms += this.input.value;
+ }
+
+ this.termInput.value = renderedTerms;
+ }
+
+ // Enable the hidden input, otherwise it's not submitted
+ this.termInput.disabled = false;
+ }
+
+ onSuggestion(event) {
+ let data = event.detail;
+ let input = event.target;
+
+ let termData;
+ if (typeof data === 'object') {
+ termData = data;
+ } else {
+ termData = { label: data, search: data };
+ }
+
+ this.lastCompletedTerm = termData;
+ this.writePartialTerm(termData.label, input);
+ }
+
+ onCompletion(event) {
+ let input = event.target;
+ let termData = event.detail;
+ let termIndex = Number(input.parentNode.dataset.index);
+
+ this.lastCompletedTerm = termData;
+
+ if ('label' in termData) {
+ this.writePartialTerm(termData.label, input);
+ this.checkValidity(input);
+ }
+
+ if (termIndex >= 0) {
+ this.autoSubmit(input, 'save', { terms: { [termIndex]: this.saveTerm(input, false, true) } });
+ } else {
+ this.autoSubmit(input, 'exchange', { terms: this.exchangeTerm() });
+ this.togglePlaceholder();
+ }
+ }
+
+ onInput(event) {
+ let input = event.target;
+ let isTerm = input.parentNode.dataset.index >= 0;
+
+ let termData = { label: this.readPartialTerm(input) };
+ this.updateTermData(termData, input);
+
+ if (! input.value && this.hasSyntaxError(input)) {
+ this.clearSyntaxError(input);
+ }
+
+ if (! this.hasSyntaxError(input)) {
+ if (isTerm && ! this.validate(input)) {
+ return;
+ }
+
+ this.complete(input, { term: termData });
+ }
+
+ if (! isTerm) {
+ this.autoSubmit(this.input, 'remove', { terms: this.clearSelectedTerms() });
+ this.togglePlaceholder();
+ }
+ }
+
+ onKeyDown(event) {
+ let input = event.target;
+ let termIndex = Number(input.parentNode.dataset.index);
+
+ if (this.hasSyntaxError(input) && ! (/[A-Z]/.test(event.key.charAt(0)) || event.ctrlKey || event.metaKey)) {
+ // Clear syntax error flag if the user types entirely new input after having selected the entire input
+ // (This way the input isn't empty but switches from input to input immediately, causing the clearing
+ // in onInput to not work)
+ if (input.selectionEnd - input.selectionStart === input.value.length) {
+ this.clearSyntaxError(input);
+ }
+ }
+
+ let removedTerms;
+ switch (event.key) {
+ case ' ':
+ if (! this.readPartialTerm(input)) {
+ this.complete(input, { term: { label: '' } });
+ event.preventDefault();
+ }
+ break;
+ case 'Backspace':
+ removedTerms = this.clearSelectedTerms();
+
+ if (this.isTermDirectionVertical()) {
+ // pass
+ } else if (termIndex >= 0 && ! input.value) {
+ let removedTerm = this.removeTerm(input.parentNode);
+ if (removedTerm !== false) {
+ input = this.moveFocusBackward(termIndex);
+ if (event.ctrlKey || event.metaKey) {
+ this.clearPartialTerm(input);
+ } else {
+ this.writePartialTerm(input.value.slice(0, -1), input);
+ }
+
+ removedTerms[termIndex] = removedTerm;
+ event.preventDefault();
+ }
+ } else if (isNaN(termIndex)) {
+ if (! input.value && this.hasTerms()) {
+ let termData = this.popTerm();
+ if (! event.ctrlKey && ! event.metaKey) {
+ // Removing the last char programmatically is not
+ // necessary since the browser default is not prevented
+ this.writePartialTerm(termData.label, input);
+ }
+
+ removedTerms[this.usedTerms.length] = termData;
+ }
+ }
+
+ this.togglePlaceholder();
+ this.autoSubmit(input, 'remove', { terms: removedTerms });
+ break;
+ case 'Delete':
+ removedTerms = this.clearSelectedTerms();
+
+ if (! this.isTermDirectionVertical() && termIndex >= 0 && ! input.value) {
+ let removedTerm = this.removeTerm(input.parentNode);
+ if (removedTerm !== false) {
+ input = this.moveFocusForward(termIndex - 1);
+ if (event.ctrlKey || event.metaKey) {
+ this.clearPartialTerm(input);
+ } else {
+ this.writePartialTerm(input.value.slice(1), input);
+ }
+
+ removedTerms[termIndex] = removedTerm;
+ event.preventDefault();
+ }
+ }
+
+ this.togglePlaceholder();
+ this.autoSubmit(input, 'remove', { terms: removedTerms });
+ break;
+ case 'Enter':
+ if (termIndex >= 0) {
+ if (this.readPartialTerm(input)) {
+ this.saveTerm(input, false);
+ } else {
+ this.removeTerm(input.parentNode, false);
+ }
+ }
+ break;
+ case 'ArrowLeft':
+ if (input.selectionStart === 0 && this.hasTerms()) {
+ event.preventDefault();
+ this.moveFocusBackward();
+ }
+ break;
+ case 'ArrowRight':
+ if (input.selectionStart === input.value.length && this.hasTerms()) {
+ event.preventDefault();
+ this.moveFocusForward();
+ }
+ break;
+ case 'ArrowUp':
+ if (this.isTermDirectionVertical()
+ && input.selectionStart === 0
+ && this.hasTerms()
+ && (this.completer === null || ! this.completer.isBeingCompleted(input))
+ ) {
+ event.preventDefault();
+ this.moveFocusBackward();
+ }
+ break;
+ case 'ArrowDown':
+ if (this.isTermDirectionVertical()
+ && input.selectionStart === input.value.length
+ && this.hasTerms()
+ && (this.completer === null || ! this.completer.isBeingCompleted(input))
+ ) {
+ event.preventDefault();
+ this.moveFocusForward();
+ }
+ break;
+ case 'a':
+ if ((event.ctrlKey || event.metaKey) && ! this.readPartialTerm(input)) {
+ this.selectTerms();
+ }
+ }
+ }
+
+ onKeyUp(event) {
+ if (event.target.parentNode.dataset.index >= 0) {
+ return;
+ }
+
+ switch (event.key) {
+ case 'End':
+ case 'ArrowLeft':
+ case 'ArrowRight':
+ this.deselectTerms();
+ break;
+ case 'Home':
+ if (this.input.selectionStart === 0 && this.input.selectionEnd === 0) {
+ if (event.shiftKey) {
+ this.selectTerms();
+ } else {
+ this.deselectTerms();
+ }
+ }
+
+ break;
+ case 'Delete':
+ this.autoSubmit(event.target, 'remove', { terms: this.clearSelectedTerms() });
+ this.togglePlaceholder();
+ break;
+ }
+ }
+
+ onInputBlur() {
+ this.deselectTerms();
+ }
+
+ onTermFocusOut(event) {
+ let input = event.target;
+ if (this.hasSyntaxError(input)) {
+ return;
+ }
+
+ // skipSaveOnBlur is set if the input is about to be removed anyway.
+ // If we remove the input as well, the other removal will fail without
+ // any chance to handle it. (Element.remove() blurs the input)
+ if (typeof input.skipSaveOnBlur === 'undefined' || ! input.skipSaveOnBlur) {
+ setTimeout(() => {
+ if (this.completer === null || ! this.completer.isBeingCompleted(input)) {
+ let termIndex = Number(input.parentNode.dataset.index);
+ if (this.readPartialTerm(input)) {
+ let previousTerm = this.saveTerm(input);
+ if (previousTerm !== false) {
+ this.autoSubmit(input, 'save', { terms: { [termIndex]: previousTerm } });
+ }
+ } else {
+ this.autoSubmit(
+ input, 'remove', { terms: { [termIndex]: this.removeTerm(input.parentNode) } });
+ }
+ }
+ }, 0);
+ }
+ }
+
+ onTermFocus(event) {
+ let input = event.target;
+
+ if (input.parentNode.dataset.index >= 0) {
+ this.validate(input);
+ }
+
+ if (event.detail.scripted) {
+ // Only request suggestions if the user manually focuses the term
+ return;
+ }
+
+ this.deselectTerms();
+
+ if (! this.hasSyntaxError(input) && (
+ this.completer === null || ! this.completer.isBeingCompleted(input, false)
+ )) {
+ // Only request suggestions if the input is valid and not already being completed
+ let value = this.readPartialTerm(input);
+ this.complete(input, { trigger: 'script', term: { label: value } });
+ }
+ }
+
+ onButtonClick(event) {
+ if (! this.hasSyntaxError()) {
+ // Register current input value, otherwise it's not included
+ this.exchangeTerm();
+ }
+
+ if (this.hasTerms()) {
+ if (this.manageRequired) {
+ this.input.required = false;
+ }
+
+ // This is not part of `onSubmit()` because otherwise it would override what `autoSubmit()` does
+ this.dataInput.value = JSON.stringify({ type: 'submit', terms: this.usedTerms });
+
+ return;
+ } else if (this.manageRequired && ! this.hasTerms()) {
+ this.input.required = true;
+ }
+
+ this.dataInput.value = '';
+ }
+
+ onPaste(event) {
+ if (this.shouldNotAutoSubmit() || this.input.value) {
+ return;
+ }
+
+ this.autoSubmit(this.input, 'paste', {
+ input: event.clipboardData.getData('text/plain'),
+ terms: this.usedTerms
+ });
+
+ event.preventDefault();
+ }
+
+ onCopyAndCut(event) {
+ if (! this.hasTerms()) {
+ return;
+ }
+
+ let data = '';
+
+ let selectedTerms = this.termContainer.querySelectorAll('.selected');
+ if (selectedTerms.length) {
+ data = Array.from(selectedTerms).map(label => label.dataset.search).join(this.separator);
+ }
+
+ if (this.input.selectionStart < this.input.selectionEnd) {
+ data += this.separator + this.input.value.slice(this.input.selectionStart, this.input.selectionEnd);
+ }
+
+ event.clipboardData.setData('text/plain', data);
+ event.preventDefault();
+
+ if (event.type === 'cut') {
+ this.clearPartialTerm(this.input);
+ this.autoSubmit(this.input, 'remove', { terms: this.clearSelectedTerms() });
+ this.togglePlaceholder();
+ }
+ }
+ }
+
+ return BaseInput;
+});
diff --git a/asset/js/widget/Completer.js b/asset/js/widget/Completer.js
new file mode 100644
index 0000000..6d60380
--- /dev/null
+++ b/asset/js/widget/Completer.js
@@ -0,0 +1,750 @@
+define(["../notjQuery"], function ($) {
+
+ "use strict";
+
+ class Completer {
+ constructor(input, instrumented = false) {
+ this.input = input;
+ this.instrumented = instrumented;
+ this.selectionStartInput = null;
+ this.selectionActive = false;
+ this.mouseSelectionActive = false;
+ this.nextSuggestion = null;
+ this.activeSuggestion = null;
+ this.suggestionKiller = null;
+ this.completedInput = null;
+ this.completedValue = null;
+ this.completedData = null;
+ this._termSuggestions = null;
+ }
+
+ get termSuggestions() {
+ if (this._termSuggestions === null) {
+ this._termSuggestions = document.querySelector(this.input.dataset.termSuggestions);
+ }
+
+ return this._termSuggestions;
+ }
+
+ bind(to = null) {
+ // Form submissions
+ $(this.input.form).on('submit', this.onSubmit, this);
+
+ // User interactions
+ $(this.termSuggestions).on('focusout', '[type="button"]', this.onFocusOut, this);
+ $(this.termSuggestions).on('click', '[type="button"]', this.onSuggestionClick, this);
+ $(this.termSuggestions).on('keydown', '[type="button"]', this.onSuggestionKeyDown, this);
+
+ if (this.selectionEnabled()) {
+ $(this.termSuggestions).on('keyup', '[type="button"]', this.onSuggestionKeyUp, this);
+ $(this.termSuggestions).on('mouseover', '[type="button"]', this.onSuggestionMouseOver, this);
+ $(this.termSuggestions).on('mousedown', '[type="button"]', this.onSuggestionMouseDown, this);
+ $(this.termSuggestions).on('mouseup', '[type="button"]', this.onSuggestionsMouseUp, this);
+ $(this.termSuggestions).on('mouseleave', this.onSuggestionsMouseLeave, this);
+ }
+
+ if (this.instrumented) {
+ if (to !== null) {
+ $(to).on('focusout', 'input[type="text"]', this.onFocusOut, this);
+ $(to).on('keydown', 'input[type="text"]', this.onKeyDown, this);
+ $(to).on('complete', 'input[type="text"]', this.onComplete, this);
+ }
+
+ $(this.input).on('complete', this.onComplete, this);
+ } else {
+ $(this.input).on('input', this.onInput, this);
+ }
+
+ $(this.input).on('focusout', this.onFocusOut, this);
+ $(this.input).on('keydown', this.onKeyDown, this);
+
+ return this;
+ }
+
+ refresh(input, bindTo = null) {
+ if (input === this.input) {
+ // If the DOM node is still the same, nothing has changed
+ return;
+ }
+
+ this._termSuggestions = null;
+ this.abort();
+
+ this.input = input;
+ this.bind(bindTo);
+ }
+
+ reset() {
+ this.abort();
+ this.hideSuggestions();
+ }
+
+ destroy() {
+ this._termSuggestions = null;
+ this.input = null;
+ }
+
+ renderSuggestions(html) {
+ let template = document.createElement('template');
+ template.innerHTML = html;
+
+ return template.content;
+ }
+
+ showSuggestions(suggestions, input) {
+ this.termSuggestions.innerHTML = '';
+ this.termSuggestions.appendChild(suggestions);
+ this.termSuggestions.style.display = '';
+
+ let containingBlock = this.termSuggestions.offsetParent || document.body;
+ let containingBlockRect = containingBlock.getBoundingClientRect();
+ let inputRect = input.getBoundingClientRect();
+ let inputPosX = inputRect.left - containingBlockRect.left;
+ let inputPosY = inputRect.bottom - containingBlockRect.top;
+ let suggestionWidth = this.termSuggestions.offsetWidth;
+
+ let maxAvailableHeight = document.body.clientHeight - inputRect.bottom;
+ let localMarginBottom = window.getComputedStyle(this.termSuggestions).marginBottom;
+
+ this.termSuggestions.style.top = `${ inputPosY }px`;
+ this.termSuggestions.style.maxHeight = `calc(${maxAvailableHeight}px - ${localMarginBottom})`;
+ if (inputPosX + suggestionWidth > containingBlockRect.right - containingBlockRect.left) {
+ this.termSuggestions.style.left =
+ `${ containingBlockRect.right - containingBlockRect.left - suggestionWidth }px`;
+ } else {
+ this.termSuggestions.style.left = `${ inputPosX }px`;
+ }
+ }
+
+ hasSuggestions() {
+ return this.termSuggestions.childNodes.length > 0;
+ }
+
+ hideSuggestions() {
+ if (this.nextSuggestion !== null || this.activeSuggestion !== null) {
+ return;
+ }
+
+ if (this.suggestionKiller !== null) {
+ // onFocusOut initiates this timer in order to hide the suggestions if the user
+ // doesn't navigate them. Since it does this by checking after a short interval
+ // if the focus is inside the suggestions, the interval has to be long enough to
+ // have a chance to detect the focus. `focusout` runs before `blur` and `focus`,
+ // so this may lead to a race condition which is addressed by the timeout. Though,
+ // to not close the newly opened suggestions of the next input the timer has to
+ // be cancelled here since it's purpose is already fulfilled.
+ clearTimeout(this.suggestionKiller);
+ this.suggestionKiller = null;
+ }
+
+ this.termSuggestions.style.display = 'none';
+ this.termSuggestions.innerHTML = '';
+
+ this.completedInput = null;
+ this.completedValue = null;
+ this.completedData = null;
+
+ this.endSelection();
+ }
+
+ prepareCompletionData(input, data = null) {
+ if (data === null) {
+ data = { term: { ...input.dataset } };
+ data.term.label = input.value;
+ }
+
+ let value = data.term.label;
+ data.term.search = value;
+ data.term.label = this.addWildcards(value);
+
+ if (input.parentElement instanceof HTMLFieldSetElement) {
+ for (let element of input.parentElement.elements) {
+ if (element !== input
+ && element.name !== input.name + '-search'
+ && (element.name.substr(-7) === '-search'
+ || typeof input.form[element.name + '-search'] === 'undefined')
+ ) {
+ // Make sure we'll use a key that the server can understand..
+ let dataName = element.name;
+ if (dataName.substr(-7) === '-search') {
+ dataName = dataName.substr(0, dataName.length - 7);
+ }
+ if (dataName.substr(0, input.parentElement.name.length) === input.parentElement.name) {
+ dataName = dataName.substr(input.parentElement.name.length);
+ }
+
+ if (! dataName in data || element.value) {
+ data[dataName] = element.value;
+ }
+ }
+ }
+ }
+
+ return [value, data];
+ }
+
+ addWildcards(value) {
+ if (! value) {
+ return '*';
+ }
+
+ if (value.slice(0, 1) !== '*' && value.slice(-1) !== '*') {
+ return '*' + value + '*';
+ }
+
+ return value;
+ }
+
+ abort() {
+ if (this.activeSuggestion !== null) {
+ this.activeSuggestion.abort();
+ this.activeSuggestion = null;
+ }
+
+ if (this.nextSuggestion !== null) {
+ clearTimeout(this.nextSuggestion);
+ this.nextSuggestion = null;
+ }
+ }
+
+ requestCompletion(input, data, trigger = 'user') {
+ this.abort();
+
+ this.nextSuggestion = setTimeout(() => {
+ let req = new XMLHttpRequest();
+ req.open('POST', this.input.dataset.suggestUrl, true);
+ req.setRequestHeader('X-Requested-With', 'XMLHttpRequest');
+ req.setRequestHeader('Content-Type', 'application/json');
+
+ if (typeof icinga !== 'undefined') {
+ let windowId = icinga.ui.getWindowId();
+ let containerId = icinga.ui.getUniqueContainerId(this.termSuggestions);
+ if (containerId) {
+ req.setRequestHeader('X-Icinga-WindowId', windowId + '_' + containerId);
+ } else {
+ req.setRequestHeader('X-Icinga-WindowId', windowId);
+ }
+ }
+
+ req.addEventListener('loadend', () => {
+ if (req.readyState > 0) {
+ if (req.responseText) {
+ let suggestions = this.renderSuggestions(req.responseText);
+ if (trigger === 'script') {
+ // If the suggestions are to be displayed due to a scripted event,
+ // show them only if the completed input is still focused..
+ if (document.activeElement === input) {
+ this.showSuggestions(suggestions, input);
+ }
+ } else {
+ this.showSuggestions(suggestions, input);
+ }
+ } else {
+ this.hideSuggestions();
+ }
+ }
+
+ this.activeSuggestion = null;
+ this.nextSuggestion = null;
+ });
+
+ req.send(JSON.stringify(data));
+
+ this.activeSuggestion = req;
+ }, 200);
+ }
+
+ suggest(input, value, data = {}) {
+ if (this.instrumented) {
+ if (! Object.keys(data).length) {
+ data = value;
+ }
+
+ $(input).trigger('suggestion', data);
+ } else {
+ input.value = value;
+ }
+ }
+
+ complete(input, value, data) {
+ $(input).focus({ scripted: true });
+
+ if (this.instrumented) {
+ if (! Object.keys(data).length) {
+ data = value;
+ }
+
+ $(input).trigger('completion', data);
+ } else {
+ input.value = value;
+
+ for (let name in data) {
+ let dataElement = input.form[input.name + '-' + name];
+ if (typeof dataElement !== 'undefined') {
+ if (dataElement instanceof RadioNodeList) {
+ dataElement = dataElement[dataElement.length - 1];
+ }
+
+ dataElement.value = data[name];
+ } else if (name === 'title') {
+ input.title = data[name];
+ }
+ }
+ }
+
+ this.hideSuggestions();
+ }
+
+ moveToSuggestion(backwards = false, stopAtEdge = false) {
+ let focused = this.termSuggestions.querySelector('[type="button"]:focus');
+ let inputs = Array.from(this.termSuggestions.querySelectorAll('[type="button"]'));
+
+ let input;
+ if (focused !== null) {
+ let sibling = inputs[backwards ? inputs.indexOf(focused) - 1 : inputs.indexOf(focused) + 1];
+ if (sibling) {
+ input = sibling;
+ } else if (stopAtEdge) {
+ return null;
+ } else {
+ input = this.completedInput;
+ }
+ } else {
+ input = inputs[backwards ? inputs.length - 1 : 0];
+ }
+
+ $(input).focus();
+
+ if (! stopAtEdge && this.completedValue !== null) {
+ if (input === this.completedInput) {
+ this.suggest(this.completedInput, this.completedValue);
+ } else {
+ this.suggest(this.completedInput, input.value, { ...input.dataset });
+ }
+ }
+
+ return input;
+ }
+
+ isBeingCompleted(input, activeElement = null) {
+ if (activeElement === null) {
+ activeElement = document.activeElement;
+ }
+
+ return input === this.completedInput && this.hasSuggestions()
+ && (! activeElement || input === activeElement || this.termSuggestions.contains(activeElement));
+ }
+
+ selectionEnabled() {
+ return this.instrumented && 'withMultiCompletion' in this.input.dataset;
+ }
+
+ selectionAllowed() {
+ return this.completedInput === this.input && this.selectionEnabled();
+ }
+
+ startSelection(input) {
+ this.selectionActive = true;
+ this.selectionStartInput = input;
+ }
+
+ isSelectionActive() {
+ return this.selectionActive;
+ }
+
+ endSelection() {
+ this.selectionStartInput = null;
+ this.selectionActive = false;
+ this.mouseSelectionActive = false;
+ }
+
+ selectSuggestion(input) {
+ input.classList.add('selected');
+ }
+
+ deselectSuggestion(input) {
+ input.classList.remove('selected');
+ }
+
+ toggleSelection(input) {
+ input.classList.toggle('selected');
+ let selected = input.classList.contains('selected');
+ if (selected && ! this.isSelectionActive()) {
+ this.startSelection(input);
+ $(input).focus();
+ }
+
+ if (! selected && input === this.selectionStartInput) {
+ this.selectionStartInput = this.termSuggestions.querySelector('[type="button"].selected');
+ if (! this.selectionStartInput) {
+ this.endSelection();
+ $(this.input).focus();
+ } else {
+ $(this.selectionStartInput).focus();
+ }
+ }
+
+ return selected;
+ }
+
+ isSelectedSuggestion(input) {
+ return input.classList.contains('selected');
+ }
+
+ getSelectedSuggestions() {
+ return this.termSuggestions.querySelectorAll('[type="button"].selected');
+ }
+
+ clearSelection() {
+ if (! this.isSelectionActive()) {
+ return;
+ }
+
+ for (const selectedInput of this.getSelectedSuggestions()) {
+ this.deselectSuggestion(selectedInput);
+ }
+
+ this.endSelection();
+ }
+
+ handleKeySelection(input, newInput) {
+ if (! this.isSelectionActive()) {
+ this.startSelection(input);
+ this.selectSuggestion(input);
+ this.selectSuggestion(newInput);
+ this.suggest(this.completedInput, '');
+ } else if (this.isSelectedSuggestion(newInput)) {
+ this.deselectSuggestion(input);
+ } else {
+ this.selectSuggestion(newInput);
+ }
+ }
+
+ startMouseSelection(input) {
+ this.startSelection(input);
+ this.mouseSelectionActive = true;
+ }
+
+ isMouseSelectionActive() {
+ return this.mouseSelectionActive;
+ }
+
+ finishMouseSelection() {
+ if (! this.mouseSelectionActive) {
+ return;
+ }
+
+ this.mouseSelectionActive = false;
+ this.selectSuggestion(this.selectionStartInput);
+
+ let selectionFound = false;
+ let selectionCandidates = [];
+ for (const input of this.termSuggestions.querySelectorAll('[type="button"]')) {
+ if (input.classList.contains('selected')) {
+ if (selectionFound) {
+ for (const candidate of selectionCandidates) {
+ this.selectSuggestion(candidate);
+ }
+
+ selectionCandidates = [];
+ } else {
+ selectionFound = true;
+ }
+ } else if (selectionFound) {
+ selectionCandidates.push(input);
+ }
+ }
+ }
+
+ /**
+ * Event listeners
+ */
+
+ onSubmit(event) {
+ if (! event.detail || ! event.detail.submittedBy) {
+ // Reset all states, the user is about to navigate away
+ this.reset();
+ }
+ }
+
+ onFocusOut(event) {
+ if (this.completedInput === null) {
+ // If there are multiple instances of Completer bound to the same suggestion container
+ // all of them try to handle the event. Though, only one of them is responsible and
+ // that's the one which has a completed input set.
+ return;
+ }
+
+ let input = event.target;
+ let completedInput = this.completedInput;
+ this.suggestionKiller = setTimeout(() => {
+ if (completedInput !== this.completedInput) {
+ // Don't hide another input's suggestions
+ } else if (document.activeElement !== completedInput
+ && ! this.termSuggestions.contains(document.activeElement)
+ ) {
+ // Hide the suggestions if the user doesn't navigate them
+ if (input !== completedInput) {
+ // Restore input if a suggestion lost focus
+ this.suggest(completedInput, this.completedValue);
+ }
+
+ this.hideSuggestions();
+ }
+ }, 250);
+ }
+
+ onSuggestionMouseDown(event) {
+ if (! this.selectionAllowed()) {
+ return;
+ }
+
+ if (event.ctrlKey || event.metaKey) {
+ // onSuggestionClick only toggles the suggestion's selection and should
+ // be the only one who decides which other suggestion should be focused
+ event.preventDefault();
+ } else {
+ this.clearSelection();
+ this.startMouseSelection(event.target);
+ }
+ }
+
+ onSuggestionsMouseUp(event) {
+ if (! event.ctrlKey && ! event.metaKey) {
+ this.finishMouseSelection();
+ }
+ }
+
+ onSuggestionsMouseLeave(_) {
+ this.finishMouseSelection();
+ }
+
+ onSuggestionMouseOver(event) {
+ if (this.isMouseSelectionActive()) {
+ this.selectSuggestion(event.target);
+ }
+ }
+
+ onSuggestionKeyUp(event) {
+ if (this.completedInput === null) {
+ return;
+ }
+
+ let input = event.target;
+
+ switch (event.key) {
+ case 'Shift':
+ if (this.isSelectionActive()) {
+ event.preventDefault();
+
+ if (input === this.selectionStartInput && this.getSelectedSuggestions().length === 1) {
+ this.deselectSuggestion(input);
+ this.endSelection();
+ }
+ }
+
+ break;
+ }
+ }
+
+ onSuggestionKeyDown(event) {
+ if (this.completedInput === null) {
+ return;
+ }
+
+ let newInput;
+ let input = event.target;
+ let allowSelection = event.shiftKey && this.selectionAllowed();
+
+ switch (event.key) {
+ case 'Escape':
+ $(this.completedInput).focus({ scripted: true });
+ this.suggest(this.completedInput, this.completedValue);
+ this.clearSelection();
+ break;
+ case 'Tab':
+ event.preventDefault();
+ this.moveToSuggestion(event.shiftKey);
+ break;
+ case 'ArrowLeft':
+ case 'ArrowUp':
+ event.preventDefault();
+
+ newInput = this.moveToSuggestion(true, allowSelection);
+ if (allowSelection) {
+ if (newInput !== null) {
+ this.handleKeySelection(input, newInput);
+ }
+ } else {
+ this.clearSelection();
+ }
+
+ break;
+ case 'ArrowRight':
+ case 'ArrowDown':
+ event.preventDefault();
+
+ newInput = this.moveToSuggestion(false, allowSelection);
+ if (allowSelection) {
+ if (newInput !== null) {
+ this.handleKeySelection(input, newInput);
+ }
+ } else {
+ this.clearSelection();
+ }
+
+ break;
+ }
+ }
+
+ onSuggestionClick(event) {
+ if (this.completedInput === null) {
+ return;
+ }
+
+ if (event.ctrlKey || event.metaKey) {
+ if (this.selectionAllowed()) {
+ this.toggleSelection(event.target);
+ event.preventDefault();
+ }
+ } else if (this.isSelectionActive() && this.isSelectedSuggestion(event.target)) {
+ let terms = [];
+ for (const suggestion of this.getSelectedSuggestions()) {
+ terms.push({ ...suggestion.dataset });
+ }
+
+ this.complete(this.completedInput, null, { type: 'terms', terms: terms });
+ } else {
+ let input = event.currentTarget;
+
+ this.complete(this.completedInput, input.value, { ...input.dataset });
+ }
+ }
+
+ onKeyDown(event) {
+ let suggestions;
+
+ switch (event.key) {
+ case ' ':
+ if (this.instrumented) {
+ break;
+ }
+
+ let input = event.target;
+
+ if (! input.value) {
+ if (input.minLength <= 0) {
+ let [value, data] = this.prepareCompletionData(input);
+ this.completedInput = input;
+ this.completedValue = value;
+ this.completedData = data;
+ this.requestCompletion(input, data);
+ }
+
+ event.preventDefault();
+ }
+
+ break;
+ case 'Tab':
+ suggestions = this.termSuggestions.querySelectorAll('[type="button"]');
+ if (suggestions.length === 1) {
+ event.preventDefault();
+ let input = event.target;
+ let suggestion = suggestions[0];
+
+ this.complete(input, suggestion.value, { ...suggestion.dataset });
+ }
+
+ break;
+ case 'Enter':
+ let defaultSuggestion = this.termSuggestions.querySelector('.default > [type="button"]');
+ if (defaultSuggestion !== null) {
+ event.preventDefault();
+ let input = event.target;
+
+ this.complete(input, defaultSuggestion.value, { ...defaultSuggestion.dataset });
+ }
+
+ break;
+ case 'Escape':
+ if (this.hasSuggestions()) {
+ this.hideSuggestions()
+ event.preventDefault();
+ }
+
+ break;
+ case 'ArrowUp':
+ suggestions = this.termSuggestions.querySelectorAll('[type="button"]');
+ if (suggestions.length) {
+ event.preventDefault();
+ this.moveToSuggestion(true);
+ }
+
+ break;
+ case 'ArrowDown':
+ suggestions = this.termSuggestions.querySelectorAll('[type="button"]');
+ if (suggestions.length) {
+ event.preventDefault();
+ this.moveToSuggestion();
+ }
+
+ break;
+ default:
+ if (/[A-Z]/.test(event.key.charAt(0)) || event.key === '"') {
+ // Ignore control keys not resulting in new input data
+ break;
+ }
+
+ let typedSuggestion = this.termSuggestions.querySelector(`[value="${ event.key }"]`);
+ if (typedSuggestion !== null) {
+ this.hideSuggestions();
+ }
+ }
+ }
+
+ onInput(event) {
+ let input = event.target;
+
+ if (input.minLength > 0 && input.value.length < input.minLength) {
+ return;
+ }
+
+ // Set the input's value as search value. This ensures that if the user doesn't
+ // choose a suggestion, an up2date contextual value will be transmitted with
+ // completion requests and the server can properly identify a new value upon submit
+ input.dataset.search = input.value;
+ if (typeof input.form[input.name + '-search'] !== 'undefined') {
+ let dataElement = input.form[input.name + '-search'];
+ if (dataElement instanceof RadioNodeList) {
+ dataElement = dataElement[dataElement.length - 1];
+ }
+
+ dataElement.value = input.value;
+ }
+
+ let [value, data] = this.prepareCompletionData(input);
+ this.completedInput = input;
+ this.completedValue = value;
+ this.completedData = data;
+ this.requestCompletion(input, data);
+ }
+
+ onComplete(event) {
+ let input = event.target;
+ let { trigger = 'user' , ...detail } = event.detail;
+
+ let [value, data] = this.prepareCompletionData(input, detail);
+ this.completedInput = input;
+ this.completedValue = value;
+ this.completedData = data;
+
+ if (typeof data.suggestions !== 'undefined') {
+ this.showSuggestions(data.suggestions, input);
+ } else {
+ this.requestCompletion(input, data, trigger);
+ }
+ }
+ }
+
+ return Completer;
+});
diff --git a/asset/js/widget/CopyToClipboard.js b/asset/js/widget/CopyToClipboard.js
new file mode 100644
index 0000000..e3b348c
--- /dev/null
+++ b/asset/js/widget/CopyToClipboard.js
@@ -0,0 +1,49 @@
+define(["../notjQuery"], function ($) {
+
+ "use strict";
+
+ class CopyToClipboard {
+ constructor(button)
+ {
+ button.classList.add('active');
+ button.removeAttribute('tabindex');
+ $(button).on('click', null, this.onClick, this);
+ }
+
+ onClick(event)
+ {
+ let button = event.currentTarget;
+ let clipboardSource = button.parentElement.querySelector("[data-clipboard-source]");
+ let copyText;
+
+ if (clipboardSource) {
+ copyText = clipboardSource.innerText;
+ } else {
+ throw new Error('Clipboard source is required but not provided');
+ }
+
+ if (navigator.clipboard) {
+ navigator.clipboard.writeText(copyText).then(() => {
+ let previousHtml = button.innerHTML;
+ button.innerText = button.dataset.copiedLabel;
+ button.classList.add('copied');
+
+ setTimeout(() => {
+ // after 4 second, reset it.
+ button.classList.remove('copied');
+ button.innerHTML = previousHtml;
+ }, 4000);
+ }).catch((err) => {
+ console.error('Failed to copy: ', err);
+ });
+ } else {
+ throw new Error('Copy to clipboard requires HTTPS connection');
+ }
+
+ event.stopPropagation();
+ event.preventDefault();
+ }
+ }
+
+ return CopyToClipboard;
+});
diff --git a/asset/js/widget/FilterInput.js b/asset/js/widget/FilterInput.js
new file mode 100644
index 0000000..fad3da0
--- /dev/null
+++ b/asset/js/widget/FilterInput.js
@@ -0,0 +1,1521 @@
+define(["../notjQuery", "BaseInput"], function ($, BaseInput) {
+
+ "use strict";
+
+ class FilterInput extends BaseInput {
+ constructor(input) {
+ super(input);
+
+ this.termType = 'column';
+
+ /**
+ * The negation operator
+ *
+ * @type {{}}
+ */
+ this.negationOperator = { label: '!', search: '!', class: 'logical_operator', type: 'negation_operator' };
+
+ /**
+ * Supported grouping operators
+ *
+ * @type {{close: {}, open: {}}}
+ */
+ this.grouping_operators = {
+ open: { label: '(', search: '(', class: 'grouping_operator_open', type: 'grouping_operator' },
+ close: { label: ')', search: ')', class: 'grouping_operator_close', type: 'grouping_operator' }
+ };
+
+ /**
+ * Supported logical operators
+ *
+ * The first is also the default.
+ *
+ * @type {{}[]}
+ */
+ this.logical_operators = [
+ { label: '&', search: '&', class: 'logical_operator', type: 'logical_operator', default: true },
+ { label: '|', search: '|', class: 'logical_operator', type: 'logical_operator' },
+ ];
+
+ /**
+ * Supported relational operators
+ *
+ * The first is also the default.
+ *
+ * @type {{}[]}
+ */
+ this.relational_operators = [
+ { label: '~', search: '~', class: 'operator', type: 'operator', default: true },
+ { label: '!~', search: '!~', class: 'operator', type: 'operator' },
+ { label: '=', search: '=', class: 'operator', type: 'operator' },
+ { label: '!=', search: '!=', class: 'operator', type: 'operator' },
+ { label: '>', search: '>', class: 'operator', type: 'operator' },
+ { label: '<', search: '<', class: 'operator', type: 'operator' },
+ { label: '>=', search: '>=', class: 'operator', type: 'operator' },
+ { label: '<=', search: '<=', class: 'operator', type: 'operator' }
+ ];
+ }
+
+ bind() {
+ $(this.termContainer).on('click', '[data-group-type="condition"] > button', this.onRemoveCondition, this);
+ $(this.termContainer).on('click', '[data-index]', this.onTermClick, this);
+ $(this.termContainer).on('mouseover', '[data-index]', this.onTermHover, this);
+ $(this.termContainer).on('mouseout', '[data-index]', this.onTermLeave, this);
+ return super.bind();
+ }
+
+ reset() {
+ super.reset();
+
+ this.termType = 'column';
+ }
+
+ restoreTerms() {
+ if (super.restoreTerms()) {
+ this.reportValidity(this.input.form);
+ return true;
+ }
+
+ return false;
+ }
+
+ registerTerms() {
+ super.registerTerms();
+
+ if (this.hasTerms()) {
+ this.termType = this.nextTermType(this.lastTerm());
+ }
+ }
+
+ registerTerm(termData, termIndex = null) {
+ termIndex = super.registerTerm(termData, termIndex);
+
+ if (termData.type === 'grouping_operator' && typeof termData.counterpart === 'undefined') {
+ let counterpart;
+ if (this.isGroupOpen(termData)) {
+ counterpart = this.nextPendingGroupClose(termIndex);
+ } else {
+ counterpart = this.lastPendingGroupOpen(termIndex);
+ }
+
+ if (counterpart !== null) {
+ termData.counterpart = counterpart;
+ this.usedTerms[counterpart].counterpart = termIndex;
+ }
+ }
+
+ return termIndex;
+ }
+
+ readFullTerm(input, termIndex = null) {
+ let termData = super.readFullTerm(input, termIndex);
+ if (termData === false) {
+ return false;
+ }
+
+ if (! Array.isArray(termData) && ! termData.type) {
+ termData.type = this.termType;
+ }
+
+ return termData;
+ }
+
+ insertTerm(termData, termIndex) {
+ let label = super.insertTerm(termData, termIndex);
+
+ if (termIndex === this.usedTerms.length - 1) {
+ this.termType = this.nextTermType(termData);
+ } else {
+ let next = this.termContainer.querySelector(`[data-index="${ termIndex + 1 }"]`);
+ this.checkValidity(next.firstChild, next.dataset.type, termIndex + 1);
+ }
+
+ return label;
+ }
+
+ insertRenderedTerm(label) {
+ let termIndex = Number(label.dataset.index);
+ if (label.dataset.counterpart >= 0) {
+ let otherLabel = this.termContainer.querySelector(`[data-index="${ label.dataset.counterpart }"]`);
+ if (otherLabel !== null) {
+ otherLabel.dataset.counterpart = termIndex;
+ this.checkValidity(otherLabel.firstChild);
+ }
+ }
+
+ let previous = this.termContainer.querySelector(`[data-index="${ termIndex - 1 }"]`);
+ switch (label.dataset.type) {
+ case 'column':
+ let newCondition = this.renderCondition();
+ newCondition.appendChild(label);
+
+ if (previous) {
+ previous.parentNode.insertBefore(newCondition, previous.nextSibling);
+ } else {
+ this.termContainer.insertBefore(newCondition, this.termContainer.firstChild);
+ }
+
+ break;
+ case 'operator':
+ case 'value':
+ previous.parentNode.appendChild(label);
+ break;
+ case 'logical_operator':
+ if (previous) {
+ if (previous.parentNode.dataset.groupType === 'condition') {
+ previous.parentNode.parentNode.insertBefore(label, previous.parentNode.nextSibling);
+ } else {
+ previous.parentNode.insertBefore(label, previous.nextSibling);
+ }
+ } else {
+ this.termContainer.insertBefore(label, this.termContainer.firstChild);
+ }
+
+ break;
+ case 'negation_operator':
+ if (previous) {
+ previous.parentNode.insertBefore(label, previous.nextSibling);
+ } else {
+ this.termContainer.insertBefore(label, this.termContainer.firstChild);
+ }
+
+ break;
+ case 'grouping_operator':
+ if (this.isGroupOpen(label.dataset)) {
+ if (label.dataset.counterpart >= 0) {
+ let counterpart = this.termContainer.querySelector(
+ `[data-index="${ label.dataset.counterpart }"]`
+ );
+ counterpart.parentNode.insertBefore(label, counterpart.parentNode.firstChild);
+ } else {
+ let newGroup = this.renderChain();
+ newGroup.appendChild(label);
+
+ let sibling = previous ? previous.nextSibling : this.termContainer.firstChild;
+ while (sibling !== null && sibling.dataset.type !== 'grouping_operator') {
+ let nextSibling = sibling.nextSibling;
+ newGroup.appendChild(sibling);
+ sibling = nextSibling;
+ }
+
+ if (previous) {
+ previous.parentNode.insertBefore(newGroup, previous.nextSibling);
+ } else {
+ // newGroup should be now the only child then
+ this.termContainer.appendChild(newGroup);
+ }
+ }
+ } else {
+ let chain = this.termContainer.querySelector(
+ `[data-index="${ label.dataset.counterpart }"]`
+ ).parentNode;
+ if (previous.parentNode.dataset.groupType && previous.parentNode !== chain) {
+ previous = previous.parentNode;
+ }
+
+ if (previous.parentNode !== chain) {
+ // The op is being moved by the user again, after it was already moved
+ let sibling = previous;
+ let lastSibling = null;
+ while (sibling !== null && sibling !== chain) {
+ let previousSibling = sibling.previousSibling;
+ chain.insertBefore(sibling, lastSibling);
+ lastSibling = sibling;
+ sibling = previousSibling;
+ }
+ }
+
+ // There may be terms following in the same level which now should be a level above
+ let sibling = previous.nextSibling;
+ let refNode = chain.nextSibling;
+ while (sibling !== null) {
+ let nextSibling = sibling.nextSibling;
+ chain.parentNode.insertBefore(sibling, refNode);
+ sibling = nextSibling;
+ }
+
+ chain.appendChild(label);
+ }
+ }
+
+ if (termIndex === this.usedTerms.length - 1) {
+ this.identifyLastRenderedTerm();
+ }
+
+ return label;
+ }
+
+ addTerm(termData, termIndex = null) {
+ super.addTerm(termData, termIndex);
+
+ if (termData.counterpart >= 0) {
+ let otherLabel = this.termContainer.querySelector(`[data-index="${ termData.counterpart }"]`);
+ if (otherLabel !== null) {
+ otherLabel.dataset.counterpart = termIndex || this.usedTerms[termData.counterpart].counterpart;
+ this.checkValidity(otherLabel.firstChild);
+ }
+ }
+
+ this.termType = this.nextTermType(termData);
+ }
+
+ addRenderedTerm(label) {
+ let newGroup = null;
+ let leaveGroup = false;
+ let currentGroup = null;
+
+ switch (label.dataset.type) {
+ case 'column':
+ newGroup = this.renderCondition();
+ break;
+ case 'grouping_operator':
+ if (this.isGroupOpen(label.dataset)) {
+ newGroup = this.renderChain();
+ } else {
+ let termIndex = Number(label.dataset.index);
+ let previous = this.termContainer.querySelector(`[data-index="${ termIndex - 1 }"]`);
+
+ currentGroup = this.termContainer.querySelector(
+ `[data-index="${ label.dataset.counterpart }"]`
+ ).parentNode;
+ if (previous.parentNode.dataset.groupType && previous.parentNode !== currentGroup) {
+ previous = previous.parentNode;
+ }
+
+ if (previous.parentNode !== currentGroup) {
+ // The op is being moved by the user again, after it was already moved
+ let sibling = previous;
+ let lastSibling = null;
+ while (sibling !== null && sibling !== currentGroup) {
+ let previousSibling = sibling.previousSibling;
+ currentGroup.insertBefore(sibling, lastSibling);
+ lastSibling = sibling;
+ sibling = previousSibling;
+ }
+ }
+ }
+
+ break;
+ case 'logical_operator':
+ currentGroup = this.currentGroup;
+ leaveGroup = currentGroup.dataset.groupType === 'condition';
+ }
+
+ if (currentGroup === null) {
+ currentGroup = this.currentGroup;
+ }
+
+ if (newGroup !== null) {
+ newGroup.appendChild(label);
+ currentGroup.appendChild(newGroup);
+ } else if (leaveGroup) {
+ currentGroup.parentNode.appendChild(label);
+ } else {
+ currentGroup.appendChild(label);
+ }
+
+ this.identifyLastRenderedTerm();
+ }
+
+ identifyLastRenderedTerm() {
+ let lastTerm = Array.from(this.termContainer.querySelectorAll('[data-index]')).pop();
+ if (! lastTerm) {
+ return;
+ }
+
+ let lastLabel = this.termContainer.querySelector('.last-term');
+ if (lastLabel !== null) {
+ if (lastLabel === lastTerm) {
+ return;
+ }
+
+ lastLabel.classList.remove('last-term');
+ }
+
+ lastTerm.classList.add('last-term');
+ }
+
+ termsToQueryString(terms) {
+ if (! this.input.form.checkValidity()) {
+ let filtered = [];
+ for (let i = 0; i < terms.length; i++) {
+ const input = this.termContainer.querySelector(`[data-index="${ i }"] > input`);
+ if (input === null || this.isGroupOpen(terms[i]) || input.checkValidity()) {
+ filtered.push(terms[i]);
+ } else if (input) {
+ // Ignore all terms after an invalid one
+ break;
+ }
+ }
+
+ terms = filtered;
+ }
+
+ return super.termsToQueryString(terms);
+ }
+
+ removeTerm(label, updateDOM = true) {
+ let termIndex = Number(label.dataset.index);
+ if (termIndex < this.usedTerms.length - 1) {
+ // It's not the last term
+ if (! this.validate(label.firstChild)) {
+ return false;
+ }
+ }
+
+ let termData = super.removeTerm(label, updateDOM);
+
+ if (this.hasTerms()) {
+ if (termIndex === this.usedTerms.length) {
+ // It's been the last term
+ this.termType = this.nextTermType(this.lastTerm());
+ }
+
+ if (termData.counterpart >= 0) {
+ let otherLabel = this.termContainer.querySelector(`[data-index="${ termData.counterpart }"]`);
+ delete this.usedTerms[otherLabel.dataset.index].counterpart;
+ delete otherLabel.dataset.counterpart;
+ this.checkValidity(otherLabel.firstChild);
+ }
+ } else {
+ this.termType = 'column';
+ }
+
+ return termData;
+ }
+
+ removeRange(labels) {
+ let removedTerms = super.removeRange(labels);
+
+ if (this.hasTerms()) {
+ this.termType = this.nextTermType(this.lastTerm());
+
+ labels.forEach((label) => {
+ if (label.dataset.counterpart >= 0) {
+ let otherLabel = this.termContainer.querySelector(
+ `[data-counterpart="${ label.dataset.index }"]`
+ );
+ if (otherLabel !== null) {
+ delete this.usedTerms[otherLabel.dataset.index].counterpart;
+ delete otherLabel.dataset.counterpart;
+ this.checkValidity(otherLabel.firstChild);
+ }
+ }
+ });
+ } else {
+ this.termType = 'column';
+ }
+
+ return removedTerms;
+ }
+
+ removeRenderedTerm(label) {
+ let parent = label.parentNode;
+ let children = parent.querySelectorAll(':scope > [data-index], :scope > [data-group-type]');
+ if (parent.dataset.groupType && children.length === 1) {
+ // If the parent is a group and the label is the only child, we can remove the entire group
+ parent.remove();
+ } else {
+ super.removeRenderedTerm(label);
+
+ if (parent.dataset.groupType === 'chain') {
+ // Get a new nodes list first, otherwise the removed label is still part of it
+ children = parent.querySelectorAll(':scope > [data-index], :scope > [data-group-type]');
+ let hasNoGroupOperators = children[0].dataset.type !== 'grouping_operator'
+ && children[children.length - 1].dataset.type !== 'grouping_operator';
+ if (hasNoGroupOperators) {
+ // Unwrap remaining terms, remove the resulting empty group
+ Array.from(children).forEach(child => parent.parentNode.insertBefore(child, parent));
+ parent.remove();
+ }
+ }
+ }
+
+ if (Number(label.dataset.index) >= this.usedTerms.length - 1) {
+ this.identifyLastRenderedTerm();
+ }
+ }
+
+ removeRenderedRange(labels) {
+ let to = Number(labels[labels.length - 1].dataset.index);
+
+ while (labels.length) {
+ let label = labels.shift();
+ let parent = label.parentNode;
+ if (parent.dataset.groupType && label === parent.firstChild) {
+ let counterpartIndex = Number(label.dataset.counterpart);
+ if (isNaN(counterpartIndex)) {
+ counterpartIndex = Number(
+ Array.from(parent.querySelectorAll(':scope > [data-index]')).pop().dataset.index
+ );
+ }
+
+ if (counterpartIndex <= to) {
+ // If the parent's terms are all to be removed, we'll remove the
+ // entire parent to keep the DOM operations as efficient as possible
+ parent.remove();
+
+ labels.splice(0, counterpartIndex - Number(label.dataset.index));
+ continue;
+ }
+ }
+
+ this.removeRenderedTerm(label);
+ }
+ }
+
+ reIndexTerms(from, howMuch = 1, forward = false) {
+ let fromLabel = this.termContainer.querySelector(`[data-index="${ from }"]`);
+
+ super.reIndexTerms(from, howMuch, forward);
+
+ let _this = this;
+ this.termContainer.querySelectorAll('[data-counterpart]').forEach(label => {
+ let counterpartIndex = Number(label.dataset.counterpart);
+ if ((forward && counterpartIndex >= from) || (! forward && counterpartIndex > from)) {
+ counterpartIndex += forward ? howMuch : -howMuch;
+
+ let termIndex = Number(label.dataset.index);
+ if (
+ (! forward && termIndex > from - howMuch && label !== fromLabel)
+ || (forward && termIndex >= from)
+ ) {
+ // Make sure to use the previous index to access usedTerms, it's not adjusted yet
+ termIndex += forward ? -howMuch : howMuch;
+ }
+
+ label.dataset.counterpart = `${ counterpartIndex }`;
+ _this.usedTerms[termIndex].counterpart = `${ counterpartIndex }`;
+ }
+ });
+ }
+
+ complete(input, data) {
+ let termIndex = Number(input.parentNode.dataset.index);
+ if (termIndex >= 0) {
+ data.term.type = this.usedTerms[termIndex].type;
+ } else {
+ termIndex = this.usedTerms.length;
+ data.term.type = this.termType;
+ }
+
+ // Special cases
+ switch (data.term.type) {
+ case 'grouping_operator':
+ case 'negation_operator':
+ return;
+ case 'column':
+ data.showQuickSearch = termIndex === this.usedTerms.length;
+ break;
+ case 'value':
+ let terms = [ ...this.usedTerms ];
+ terms.splice(termIndex - 2, 3, { type: 'column', search: '' },
+ { type: 'operator', search: '' }, { type: 'value', search: '' });
+
+ data.searchFilter = this.termsToQueryString(terms);
+ break;
+ case 'operator':
+ case 'logical_operator':
+ let suggestions = this.validOperator(
+ data.trigger === 'script' ? '' : data.term.label, data.term.type, termIndex);
+ if (suggestions.exactMatch && ! suggestions.partialMatches) {
+ // User typed a suggestion manually, don't show the same suggestion again
+ return;
+ }
+
+ data.suggestions = this.renderSuggestions(suggestions);
+ }
+
+ // Additional metadata
+ switch (data.term.type) {
+ case 'value':
+ data.operator = this.usedTerms[--termIndex].search;
+ case 'operator':
+ data.column = this.usedTerms[--termIndex].search;
+ }
+
+ super.complete(input, data);
+ }
+
+ nextTermType(termData) {
+ switch (termData.type) {
+ case 'column':
+ return 'operator';
+ case 'operator':
+ return 'value';
+ case 'value':
+ return 'logical_operator';
+ case 'logical_operator':
+ case 'negation_operator':
+ return 'column';
+ case 'grouping_operator':
+ return this.isGroupOpen(termData) ? 'column' : 'logical_operator';
+ }
+ }
+
+ get currentGroup() {
+ let label = Array.from(this.termContainer.querySelectorAll('[data-index]')).pop();
+ if (! label) {
+ return this.termContainer;
+ }
+
+ let termData = this.usedTerms[label.dataset.index];
+ switch (termData.type) {
+ case 'grouping_operator':
+ if (this.isGroupOpen(termData)) {
+ break;
+ }
+ case 'value':
+ return label.parentNode.parentNode;
+ }
+
+ return label.parentNode;
+ }
+
+ lastPendingGroupOpen(before) {
+ let level = 0;
+ for (let i = before - 1; i >= 0 && i < this.usedTerms.length; i--) {
+ let termData = this.usedTerms[i];
+
+ if (termData.type === 'grouping_operator') {
+ if (this.isGroupOpen(termData)) {
+ if (level === 0) {
+ return typeof termData.counterpart === 'undefined' ? i : null;
+ }
+
+ level++;
+ } else {
+ if (termData.counterpart >= 0) {
+ i = termData.counterpart;
+ } else {
+ level--;
+ }
+ }
+ }
+ }
+
+ return null;
+ }
+
+ nextPendingGroupClose(after) {
+ let level = 0;
+ for (let i = after + 1; i < this.usedTerms.length; i++) {
+ let termData = this.usedTerms[i];
+
+ if (termData.type === 'grouping_operator') {
+ if (this.isGroupClose(termData)) {
+ if (level === 0) {
+ return typeof termData.counterpart === 'undefined' ? i : null;
+ }
+
+ level--;
+ } else {
+ if (termData.counterpart >= 0) {
+ i = termData.counterpart;
+ } else {
+ level++;
+ }
+ }
+ }
+ }
+
+ return null;
+ }
+
+ isGroupOpen(termData) {
+ return termData.type === 'grouping_operator' && termData.search === this.grouping_operators.open.search;
+ }
+
+ isGroupClose(termData) {
+ return termData.type === 'grouping_operator' && termData.search === this.grouping_operators.close.search;
+ }
+
+ getOperator(value, termType = null) {
+ if (termType === null) {
+ termType = this.termType;
+ }
+
+ let operators;
+ switch (termType) {
+ case 'operator':
+ operators = this.relational_operators;
+ break;
+ case 'logical_operator':
+ operators = this.logical_operators;
+ break;
+ }
+
+ value = value.toLowerCase();
+ return operators.find((term) => {
+ return value === term.label.toLowerCase() || value === term.search.toLowerCase();
+ }) || null;
+ }
+
+ matchOperators(operators, value) {
+ value = value.toLowerCase();
+
+ let exactMatch = false;
+ let partialMatch = false;
+ let filtered = operators.filter((op) => {
+ let label = op.label.toLowerCase();
+ let search = op.search.toLowerCase();
+
+ if (
+ (value.length < label.length && value === label.slice(0, value.length))
+ || (value.length < search.length && value === search.slice(0, value.length))
+ ) {
+ partialMatch = true;
+ return true;
+ }
+
+ if (value === label || value === search) {
+ exactMatch = true;
+ return true;
+ }
+
+ return false;
+ });
+
+ if (exactMatch || partialMatch) {
+ operators = filtered;
+ }
+
+ operators.exactMatch = exactMatch;
+ operators.partialMatches = partialMatch;
+
+ return operators;
+ }
+
+ nextOperator(value, currentValue, termType = null, termIndex = null) {
+ let operators = [];
+
+ if (termType === null) {
+ termType = this.termType;
+ }
+
+ if (termIndex === null && termType === 'column' && ! currentValue) {
+ switch (true) {
+ case ! this.hasTerms():
+ case this.lastTerm().type === 'logical_operator':
+ case this.isGroupOpen(this.lastTerm()):
+ operators.push(this.grouping_operators.open);
+ operators.push(this.negationOperator);
+ }
+ } else if (termIndex === -1) {
+ // This is more of a `previousOperator` thing here
+ switch (termType) {
+ case 'column':
+ operators = operators.concat(this.logical_operators);
+ case 'logical_operator':
+ operators.push(this.grouping_operators.open);
+ operators.push(this.negationOperator);
+ break;
+ case 'negation_operator':
+ operators = operators.concat(this.logical_operators);
+ operators.push(this.grouping_operators.open);
+ break;
+ case 'grouping_operator':
+ if (this.isGroupOpen(this.usedTerms[0])) {
+ operators.push(this.grouping_operators.open);
+ operators.push(this.negationOperator);
+ }
+ }
+ } else {
+ let nextIndex = termIndex === null ? this.usedTerms.length : termIndex + 1;
+ switch (termType) {
+ case 'column':
+ operators = operators.concat(this.relational_operators);
+
+ if (! currentValue || (termIndex !== null && termIndex < this.usedTerms.length)) {
+ operators.push(this.grouping_operators.open);
+ operators.push(this.negationOperator);
+ }
+ case 'operator':
+ case 'value':
+ operators = operators.concat(this.logical_operators);
+
+ if (this.lastPendingGroupOpen(nextIndex) !== null) {
+ operators.push(this.grouping_operators.close);
+ }
+
+ break;
+ case 'logical_operator':
+ if (this.lastPendingGroupOpen(nextIndex) !== null) {
+ operators.push(this.grouping_operators.close);
+ }
+
+ if (termIndex !== null && termIndex < this.usedTerms.length) {
+ operators.push(this.grouping_operators.open);
+ operators.push(this.negationOperator);
+ }
+
+ break;
+ case 'negation_operator':
+ operators.push(this.grouping_operators.open);
+
+ break;
+ case 'grouping_operator':
+ let termData = this.usedTerms[termIndex];
+ if (this.isGroupOpen(termData)) {
+ operators.push(this.grouping_operators.open);
+ operators.push(this.negationOperator);
+ } else {
+ operators = operators.concat(this.logical_operators);
+
+ if (this.lastPendingGroupOpen(nextIndex)) {
+ operators.push(this.grouping_operators.close);
+ }
+ }
+ }
+ }
+
+ return value ? this.matchOperators(operators, value) : operators;
+ }
+
+ validOperator(value, termType = null, termIndex = null) {
+ let operators = [];
+
+ if (termType === null) {
+ termType = this.termType;
+ }
+
+ switch (termType) {
+ case 'operator':
+ operators = operators.concat(this.relational_operators);
+ break;
+ case 'logical_operator':
+ operators = operators.concat(this.logical_operators);
+ break;
+ case 'negation_operator':
+ operators.push(this.negationOperator);
+ break;
+ case 'grouping_operator':
+ let termData = this.usedTerms[termIndex];
+ if (termData.counterpart >= 0) {
+ let counterpart = this.usedTerms[termData.counterpart];
+ if (this.isGroupOpen(counterpart)) {
+ operators.push(this.grouping_operators.close);
+ } else {
+ operators.push(this.grouping_operators.open);
+ }
+ }
+ }
+
+ return value ? this.matchOperators(operators, value) : operators;
+ }
+
+ checkValidity(input, type = null, termIndex = null) {
+ if (! super.checkValidity(input)) {
+ return false;
+ }
+
+ if (type === null) {
+ type = input.parentNode.dataset.type;
+ }
+
+ if (! type || type === 'value') {
+ // type is undefined for the main input, values have no special validity rules
+ return true;
+ }
+
+ if (termIndex === null && input.parentNode.dataset.index >= 0) {
+ termIndex = Number(input.parentNode.dataset.index);
+ }
+
+ let value = this.readPartialTerm(input);
+
+ let options;
+ switch (type) {
+ case 'operator':
+ case 'logical_operator':
+ case 'negation_operator':
+ case 'grouping_operator':
+ options = this.validOperator(value, type, termIndex);
+ }
+
+ let message = '';
+ if (type === 'column') {
+ let nextTermAt = termIndex + 1;
+ if (! value && nextTermAt < this.usedTerms.length && this.usedTerms[nextTermAt].type === 'operator') {
+ message = this.input.dataset.chooseColumn;
+ }
+ } else {
+ let isRequired = ! options.exactMatch;
+ if (type === 'negation_operator' && ! value) {
+ isRequired = false;
+ } else if (type === 'operator' && ! value) {
+ let nextTermAt = termIndex + 1;
+ isRequired = nextTermAt < this.usedTerms.length && this.usedTerms[nextTermAt].type === 'value';
+ } else if (type === 'logical_operator' && ! value) {
+ if (termIndex === 0 || termIndex === this.usedTerms.length - 1) {
+ isRequired = false;
+ } else {
+ isRequired = ! this.isGroupOpen(this.usedTerms[termIndex - 1])
+ && ! this.isGroupClose(this.usedTerms[termIndex + 1])
+ && this.usedTerms[termIndex - 1].type !== 'logical_operator'
+ && this.usedTerms[termIndex + 1].type !== 'logical_operator';
+ }
+ } else if (type === 'grouping_operator') {
+ if (typeof this.usedTerms[termIndex].counterpart === 'undefined') {
+ if (value) {
+ message = this.input.dataset.incompleteGroup;
+ }
+
+ isRequired = false;
+ } else if (! value) {
+ isRequired = false;
+ }
+ }
+
+ if (isRequired) {
+ message = this.input.dataset.chooseTemplate.replace(
+ '%s',
+ options.map(e => e.label).join(', ')
+ );
+ }
+ }
+
+ if (! message && termIndex > 0 && type !== 'logical_operator') {
+ let previousTerm = this.usedTerms[termIndex - 1];
+
+ let missingLogicalOp = true;
+ switch (type) {
+ case 'column':
+ missingLogicalOp = ! ['logical_operator', 'negation_operator'].includes(previousTerm.type)
+ && ! this.isGroupOpen(previousTerm);
+ break;
+ case 'operator':
+ missingLogicalOp = previousTerm.type !== 'column';
+ break;
+ case 'value':
+ missingLogicalOp = previousTerm.type !== 'operator';
+ break;
+ case 'negation_operator':
+ missingLogicalOp = previousTerm.type !== 'logical_operator'
+ && ! this.isGroupOpen(previousTerm);
+ break;
+ case 'grouping_operator':
+ if (value === this.grouping_operators.open.label) {
+ missingLogicalOp = ! ['logical_operator', 'negation_operator'].includes(previousTerm.type)
+ && ! this.isGroupOpen(previousTerm);
+ } else {
+ missingLogicalOp = false;
+ }
+ }
+
+ if (missingLogicalOp) {
+ message = this.input.dataset.missingLogOp;
+ }
+ }
+
+ input.setCustomValidity(message);
+ return input.checkValidity();
+ }
+
+ renderSuggestions(suggestions) {
+ let itemTemplate = $.render('<li><input type="button" tabindex="-1"></li>');
+
+ let list = document.createElement('ul');
+
+ suggestions.forEach((term) => {
+ let item = itemTemplate.cloneNode(true);
+ item.firstChild.value = term.label;
+
+ for (let name in term) {
+ if (name === 'default') {
+ if (term[name]) {
+ item.classList.add('default');
+ }
+ } else {
+ item.firstChild.dataset[name] = term[name];
+ }
+ }
+
+ list.appendChild(item);
+ });
+
+ return list;
+ }
+
+ renderPreview(content) {
+ return $.render('<span>' + content + '</span>');
+ }
+
+ renderCondition() {
+ return $.render(
+ '<div class="filter-condition" data-group-type="condition">'
+ + '<button type="button"><i class="icon fa fa-trash"></i></button>'
+ + '</div>'
+ );
+ }
+
+ renderChain() {
+ return $.render('<div class="filter-chain" data-group-type="chain"></div>');
+ }
+
+ renderTerm(termData, termIndex) {
+ let label = super.renderTerm(termData, termIndex);
+ label.dataset.type = termData.type;
+
+ if (! termData.class) {
+ label.classList.add(termData.type);
+ }
+
+ if (termData.counterpart >= 0) {
+ label.dataset.counterpart = termData.counterpart;
+ }
+
+ return label;
+ }
+
+ autoSubmit(input, changeType, data) {
+ if (this.shouldNotAutoSubmit()) {
+ return;
+ }
+
+ let changedTerms = [];
+ if ('terms' in data) {
+ changedTerms = data['terms'];
+ }
+
+ let changedIndices = Object.keys(changedTerms).sort((a, b) => a - b);
+ if (! changedIndices.length) {
+ return;
+ }
+
+ let lastTermAt;
+ switch (changeType) {
+ case 'add':
+ case 'exchange':
+ lastTermAt = changedIndices.pop();
+ if (changedTerms[lastTermAt].type === 'value') {
+ if (! changedIndices.length) {
+ data['terms'] = {
+ ...{
+ [lastTermAt - 2]: this.usedTerms[lastTermAt - 2],
+ [lastTermAt - 1]: this.usedTerms[lastTermAt - 1]
+ },
+ ...changedTerms
+ };
+ }
+
+ break;
+ } else if (this.isGroupClose(changedTerms[lastTermAt])) {
+ break;
+ }
+
+ return;
+ case 'insert':
+ lastTermAt = changedIndices.pop();
+ if ((changedTerms[lastTermAt].type === 'value' && changedIndices.length)
+ || this.isGroupClose(changedTerms[lastTermAt])
+ || (changedTerms[lastTermAt].type === 'negation_operator'
+ && lastTermAt < this.usedTerms.length - 1
+ )
+ ) {
+ break;
+ }
+
+ return;
+ case 'save':
+ let updateAt = changedIndices[0];
+ let valueAt = updateAt;
+ switch (changedTerms[updateAt].type) {
+ case 'column':
+ if (changedTerms[updateAt].label !== this.usedTerms[updateAt].label) {
+ return;
+ }
+
+ valueAt++;
+ case 'operator':
+ valueAt++;
+ }
+
+ if (valueAt === updateAt) {
+ if (changedIndices.length === 1) {
+ data['terms'] = {
+ ...{
+ [valueAt - 2]: this.usedTerms[valueAt - 2],
+ [valueAt - 1]: this.usedTerms[valueAt - 1]
+ },
+ ...changedTerms
+ };
+ }
+
+ break;
+ } else if (this.usedTerms.length > valueAt && this.usedTerms[valueAt].type === 'value') {
+ break;
+ }
+
+ return;
+ case 'remove':
+ let firstTermAt = changedIndices.shift();
+ if (changedTerms[firstTermAt].type === 'column'
+ || this.isGroupOpen(changedTerms[firstTermAt])
+ || changedTerms[firstTermAt].type === 'negation_operator'
+ || (changedTerms[firstTermAt].type === 'logical_operator' && changedIndices.length)
+ ) {
+ break;
+ }
+
+ return;
+ }
+
+ super.autoSubmit(input, changeType, data);
+ }
+
+ encodeTerm(termData) {
+ if (termData.type === 'column' || termData.type === 'value') {
+ termData = super.encodeTerm(termData);
+ termData.search = termData.search.replace(
+ /[()]/g,
+ function(c) {
+ return '%' + c.charCodeAt(0).toString(16);
+ }
+ );
+ }
+
+ return termData;
+ }
+
+ isTermDirectionVertical() {
+ return false;
+ }
+
+ highlightTerm(label, highlightedBy = null) {
+ label.classList.add('highlighted');
+
+ let canBeHighlighted = (label) => ! ('highlightedBy' in label.dataset)
+ && label.firstChild !== document.activeElement
+ && (this.completer === null
+ || ! this.completer.isBeingCompleted(label.firstChild)
+ );
+
+ if (highlightedBy !== null) {
+ if (canBeHighlighted(label)) {
+ label.dataset.highlightedBy = highlightedBy;
+ }
+ } else {
+ highlightedBy = label.dataset.index;
+ }
+
+ let negationAt, previousIndex, nextIndex;
+ switch (label.dataset.type) {
+ case 'column':
+ case 'operator':
+ case 'value':
+ label.parentNode.querySelectorAll(':scope > [data-index]').forEach((otherLabel) => {
+ if (otherLabel !== label && canBeHighlighted(otherLabel)) {
+ otherLabel.classList.add('highlighted');
+ otherLabel.dataset.highlightedBy = highlightedBy;
+ }
+ });
+
+ negationAt = Number(label.dataset.index) - (
+ label.dataset.type === 'column'
+ ? 1 : label.dataset.type === 'operator'
+ ? 2 : 3
+ );
+ if (negationAt >= 0 && this.usedTerms[negationAt].type === 'negation_operator') {
+ let negationLabel = this.termContainer.querySelector(`[data-index="${ negationAt }"]`);
+ if (negationLabel !== null && canBeHighlighted(negationLabel)) {
+ negationLabel.classList.add('highlighted');
+ negationLabel.dataset.highlightedBy = highlightedBy;
+ }
+ }
+
+ break;
+ case 'logical_operator':
+ previousIndex = Number(label.dataset.index) - 1;
+ if (previousIndex >= 0 && this.usedTerms[previousIndex].type !== 'logical_operator') {
+ this.highlightTerm(
+ this.termContainer.querySelector(`[data-index="${ previousIndex }"]`),
+ highlightedBy
+ );
+ }
+
+ nextIndex = Number(label.dataset.index) + 1;
+ if (nextIndex < this.usedTerms.length && this.usedTerms[nextIndex].type !== 'logical_operator') {
+ this.highlightTerm(
+ this.termContainer.querySelector(`[data-index="${ nextIndex }"]`),
+ highlightedBy
+ );
+ }
+
+ break;
+ case 'negation_operator':
+ nextIndex = Number(label.dataset.index) + 1;
+ if (nextIndex < this.usedTerms.length) {
+ this.highlightTerm(
+ this.termContainer.querySelector(`[data-index="${ nextIndex }"]`),
+ highlightedBy
+ );
+ }
+
+ break;
+ case 'grouping_operator':
+ negationAt = null;
+ if (this.isGroupOpen(label.dataset)) {
+ negationAt = Number(label.dataset.index) - 1;
+ }
+
+ if (label.dataset.counterpart >= 0) {
+ let otherLabel = this.termContainer.querySelector(
+ `[data-index="${ label.dataset.counterpart }"]`
+ );
+ if (otherLabel !== null) {
+ if (negationAt === null) {
+ negationAt = Number(otherLabel.dataset.index) - 1;
+ }
+
+ if (canBeHighlighted(otherLabel)) {
+ otherLabel.classList.add('highlighted');
+ otherLabel.dataset.highlightedBy = highlightedBy;
+ }
+ }
+ }
+
+ if (negationAt >= 0 && this.usedTerms[negationAt].type === 'negation_operator') {
+ let negationLabel = this.termContainer.querySelector(`[data-index="${ negationAt }"]`);
+ if (negationLabel !== null && canBeHighlighted(negationLabel)) {
+ negationLabel.classList.add('highlighted');
+ negationLabel.dataset.highlightedBy = highlightedBy;
+ }
+ }
+ }
+ }
+
+ deHighlightTerm(label) {
+ if (! ('highlightedBy' in label.dataset)) {
+ label.classList.remove('highlighted');
+ }
+
+ this.termContainer.querySelectorAll(`[data-highlighted-by="${ label.dataset.index }"]`).forEach(
+ (label) => {
+ label.classList.remove('highlighted');
+ delete label.dataset.highlightedBy;
+ }
+ );
+ }
+
+ /**
+ * Event listeners
+ */
+
+ onTermFocusOut(event) {
+ let label = event.currentTarget;
+ if (this.completer === null || ! this.completer.isBeingCompleted(label.firstChild, event.relatedTarget)) {
+ this.deHighlightTerm(label);
+ }
+
+ if (['column', 'value'].includes(label.dataset.type) || ! this.readPartialTerm(label.firstChild)) {
+ super.onTermFocusOut(event);
+ }
+ }
+
+ onTermFocus(event) {
+ let input = event.target;
+ let isTerm = input.parentNode.dataset.index >= 0;
+ let termType = input.parentNode.dataset.type || this.termType;
+
+ if (isTerm) {
+ this.highlightTerm(input.parentNode);
+ }
+
+ let value = this.readPartialTerm(input);
+ if (! value && (termType === 'column' || termType === 'value')) {
+ if (isTerm) {
+ this.validate(input);
+ }
+
+ // No automatic suggestions without input
+ return;
+ }
+
+ super.onTermFocus(event);
+ }
+
+ onTermClick(event) {
+ if (this.disabled) {
+ return;
+ }
+
+ let input = event.target;
+ let termType = input.parentNode.dataset.type;
+
+ if (['logical_operator', 'operator'].includes(termType)) {
+ this.complete(input, { trigger: 'script', term: { label: this.readPartialTerm(input) } });
+ }
+ }
+
+ onTermHover(event) {
+ if (this.disabled) {
+ return;
+ }
+
+ let label = event.currentTarget;
+
+ if (['column', 'operator', 'value'].includes(label.dataset.type)) {
+ // This adds a class to delay the remove button. If it's shown instantly upon hover
+ // it's too easy to accidentally click it instead of the desired grouping operator.
+ label.parentNode.classList.add('_hover_delay');
+ setTimeout(function () {
+ label.parentNode.classList.remove('_hover_delay');
+ }, 500);
+ }
+
+ this.highlightTerm(label);
+ }
+
+ onTermLeave(event) {
+ if (this.disabled) {
+ return;
+ }
+
+ let label = event.currentTarget;
+ if (label.firstChild !== document.activeElement
+ && (this.completer === null || ! this.completer.isBeingCompleted(label.firstChild))
+ ) {
+ this.deHighlightTerm(label);
+ }
+ }
+
+ onRemoveCondition(event) {
+ let button = event.target.closest('button');
+ let labels = Array.from(button.parentNode.querySelectorAll(':scope > [data-index]'));
+
+ let previous = button.parentNode.previousSibling;
+ let next = button.parentNode.nextSibling;
+
+ while (previous !== null || next !== null) {
+ if (previous !== null && previous.dataset.type === 'negation_operator') {
+ labels.unshift(previous);
+ previous = previous.previousSibling;
+ }
+
+ if (next !== null && next.dataset.type === 'logical_operator') {
+ labels.push(next);
+ next = next.nextSibling;
+ } else if (previous !== null && previous.dataset.type === 'logical_operator') {
+ labels.unshift(previous);
+ previous = previous.previousSibling;
+ }
+
+ if (
+ previous && previous.dataset.type === 'grouping_operator'
+ && next && next.dataset.type === 'grouping_operator'
+ ) {
+ labels.unshift(previous);
+ labels.push(next);
+ previous = next.parentNode !== null ? next.parentNode.previousSibling : null;
+ next = next.parentNode !== null ? next.parentNode.nextSibling : null;
+ } else {
+ break
+ }
+ }
+
+ this.autoSubmit(this.input, 'remove', { terms: this.removeRange(labels) });
+ this.togglePlaceholder();
+ }
+
+ onCompletion(event) {
+ super.onCompletion(event);
+
+ if (event.target.parentNode.dataset.index >= 0) {
+ return;
+ }
+
+ if (this.termType === 'operator' || this.termType === 'logical_operator') {
+ this.complete(this.input, { term: { label: '' } });
+ }
+ }
+
+ onKeyDown(event) {
+ super.onKeyDown(event);
+ if (event.defaultPrevented) {
+ return;
+ }
+
+ let input = event.target;
+ let isTerm = input.parentNode.dataset.index >= 0;
+
+ if (this.hasSyntaxError(input)) {
+ return;
+ }
+
+ let currentValue = this.readPartialTerm(input);
+ if (isTerm && ! currentValue) {
+ // Switching contexts requires input first
+ return;
+ } else if (input.selectionStart !== input.selectionEnd) {
+ // In case the user selected a range of text, do nothing
+ return;
+ } else if (/[A-Z]/.test(event.key.charAt(0)) || event.ctrlKey || event.metaKey) {
+ // Ignore control keys not resulting in new input data
+ // TODO: Remove this and move the entire block into `onInput`
+ // once Safari supports `InputEvent.data`
+ return;
+ }
+
+ let termIndex = null;
+ let termType = this.termType;
+ if (isTerm) {
+ if (input.selectionEnd === input.value.length) {
+ // Cursor is at the end of the input
+ termIndex = Number(input.parentNode.dataset.index);
+ termType = input.parentNode.dataset.type;
+ } else if (input.selectionStart === 0) {
+ // Cursor is at the start of the input
+ termIndex = Number(input.parentNode.dataset.index);
+ if (termIndex === 0) {
+ // TODO: This is bad, if it causes problems, replace it
+ // with a proper `previousOperator` implementation
+ termType = this.usedTerms[termIndex].type;
+ termIndex -= 1;
+ } else {
+ termIndex -= 1;
+ termType = this.usedTerms[termIndex].type;
+ }
+ } else {
+ // In case the cursor is somewhere in between, do nothing
+ return;
+ }
+
+ if (termIndex > -1 && termIndex < this.usedTerms.length - 1) {
+ let nextTerm = this.usedTerms[termIndex + 1];
+ if (nextTerm.type === 'operator' || nextTerm.type === 'value') {
+ // In between parts of a condition there's no context switch possible at all
+ return;
+ }
+ }
+ } else if (input.selectionEnd !== input.value.length) {
+ // Main input processing only happens at the end of the input
+ return;
+ }
+
+ let operators;
+ let value = event.key;
+ if (! isTerm || termType === 'operator') {
+ operators = this.validOperator(
+ termType === 'operator' ? currentValue + value : value, termType, termIndex);
+ if (! operators.exactMatch && ! operators.partialMatches) {
+ operators = this.nextOperator(value, currentValue, termType, termIndex);
+ }
+ } else {
+ operators = this.nextOperator(value, currentValue, termType, termIndex);
+ }
+
+ if (isTerm) {
+ let newTerm = null;
+ let exactMatchOnly = operators.exactMatch && ! operators.partialMatches;
+ if (exactMatchOnly && operators[0].label.toLowerCase() !== value.toLowerCase()) {
+ // The user completes a partial match
+ } else if (exactMatchOnly && (termType !== 'operator' || operators[0].type !== 'operator')) {
+ newTerm = { ...operators[0] };
+ } else if (operators.partialMatches && termType !== 'operator') {
+ newTerm = { ...operators[0], label: value, search: value };
+ } else {
+ // If no match is found, the user continues typing
+ switch (termType) {
+ case 'operator':
+ newTerm = { label: value, search: value, type: 'value' };
+ break;
+ case 'logical_operator':
+ case 'negation_operator':
+ newTerm = { label: value, search: value, type: 'column' };
+ break;
+ }
+ }
+
+ if (newTerm !== null) {
+ let label = this.insertTerm(newTerm, termIndex + 1);
+ this.autoSubmit(label.firstChild, 'insert', { terms: { [termIndex + 1]: newTerm } });
+ this.complete(label.firstChild, { term: newTerm });
+ $(label.firstChild).focus({ scripted: true });
+ event.preventDefault();
+ }
+ } else {
+ if (operators.partialMatches) {
+ this.exchangeTerm();
+ this.togglePlaceholder();
+ } else if (operators.exactMatch) {
+ if (termType !== operators[0].type) {
+ this.autoSubmit(input, 'exchange', { terms: this.exchangeTerm() });
+ } else {
+ this.clearPartialTerm(input);
+ }
+
+ this.addTerm({ ...operators[0] });
+ this.autoSubmit(input, 'add', { terms: { [this.usedTerms.length - 1]: operators[0] } });
+ this.togglePlaceholder();
+ event.preventDefault();
+ } else if (termType === 'operator') {
+ let partialOperator = this.getOperator(currentValue);
+ if (partialOperator !== null) {
+ // If no match is found, the user seems to want the partial operator.
+ this.addTerm({ ...partialOperator });
+ this.clearPartialTerm(input);
+ }
+ }
+ }
+ }
+
+ onInput(event) {
+ let input = event.target;
+ if (this.hasSyntaxError(input)) {
+ return super.onInput(event);
+ }
+
+ let termIndex = Number(input.parentNode.dataset.index);
+ let isTerm = termIndex >= 0;
+
+ if (! isTerm && (this.termType === 'operator' || this.termType === 'logical_operator')) {
+ let value = this.readPartialTerm(input);
+
+ if (value && ! this.validOperator(value).partialMatches) {
+ let defaultTerm = this.termType === 'operator'
+ ? { ...this.relational_operators[0] }
+ : { ...this.logical_operators[0] };
+
+ if (value !== defaultTerm.label) {
+ this.addTerm(defaultTerm);
+ this.togglePlaceholder();
+ } else {
+ this.exchangeTerm();
+ this.togglePlaceholder();
+ }
+ }
+ }
+
+ super.onInput(event);
+
+ if (isTerm && input.checkValidity()) {
+ let value = this.readPartialTerm(input);
+ if (value && ! ['column', 'value'].includes(input.parentNode.dataset.type)) {
+ this.autoSubmit(input, 'save', { terms: { [termIndex]: this.saveTerm(input) } });
+ }
+ }
+ }
+
+ onPaste(event) {
+ if (! this.hasTerms()) {
+ this.submitTerms(event.clipboardData.getData('text/plain'));
+ event.preventDefault();
+ } else if (! this.input.value) {
+ let terms = event.clipboardData.getData('text/plain');
+ if (this.termType === 'logical_operator') {
+ if (! this.validOperator(terms[0]).exactMatch) {
+ this.registerTerm({ ...this.logical_operators[0] });
+ }
+ } else if (this.termType !== 'column') {
+ return;
+ }
+
+ this.submitTerms(this.termsToQueryString(this.usedTerms) + terms);
+ event.preventDefault();
+ }
+ }
+ }
+
+ return FilterInput;
+});
diff --git a/asset/js/widget/SearchBar.js b/asset/js/widget/SearchBar.js
new file mode 100644
index 0000000..276de17
--- /dev/null
+++ b/asset/js/widget/SearchBar.js
@@ -0,0 +1,81 @@
+define(["../notjQuery"], function ($) {
+
+ "use strict";
+
+ class SearchBar {
+ constructor(form) {
+ this.form = form;
+ this.filterInput = null;
+ }
+
+ bind() {
+ $(this.form.parentNode).on('click', '[data-search-editor-url]', this.onOpenerClick, this);
+
+ return this;
+ }
+
+ refresh(form) {
+ if (form === this.form) {
+ // If the DOM node is still the same, nothing has changed
+ return;
+ }
+
+ this.form = form;
+ this.bind();
+ }
+
+ destroy() {
+ this.form = null;
+ this.filterInput = null;
+ }
+
+ setFilterInput(filterInput) {
+ this.filterInput = filterInput;
+
+ return this;
+ }
+
+ onOpenerClick(event) {
+ let opener = event.currentTarget;
+ let editorUrl = opener.dataset.searchEditorUrl;
+ let filterQueryString = this.filterInput.getQueryString();
+ let layout = document.getElementById('layout');
+
+ editorUrl += (editorUrl.indexOf('?') > -1 ? '&' : '?') + filterQueryString;
+
+ // Disable pointer events to block further function calls
+ opener.style.pointerEvents = 'none';
+
+ let observer = new MutationObserver((mutations) => {
+ for (let mutation of mutations) {
+ if (mutation.type === 'childList') {
+ mutation.removedNodes.forEach((node) => {
+ // Remove the pointerEvent none style to make the button clickable again
+ // after the modal has been removed
+ if (node.id === 'modal') {
+ opener.style.pointerEvents = '';
+ observer.disconnect();
+ }
+ });
+ }
+ }
+ });
+
+ observer.observe(layout, {childList: true});
+
+ // The search editor should open in a modal. We simulate a click on an anchor
+ // appropriately prepared so that Icinga Web 2 will handle it natively.
+ let a = document.createElement('a');
+ a.classList.add('modal-opener');
+ a.href = editorUrl;
+ a.dataset.noIcingaAjax = '';
+ a.dataset.icingaModal = '';
+
+ opener.parentNode.insertBefore(a, opener.nextSibling);
+ a.click();
+ a.remove();
+ }
+ }
+
+ return SearchBar;
+});
diff --git a/asset/js/widget/SearchEditor.js b/asset/js/widget/SearchEditor.js
new file mode 100644
index 0000000..b8235f0
--- /dev/null
+++ b/asset/js/widget/SearchEditor.js
@@ -0,0 +1,79 @@
+define(["../notjQuery", "../vendor/Sortable"], function ($, Sortable) {
+
+ "use strict";
+
+ class SearchEditor {
+ constructor(form) {
+ this.form = form;
+ }
+
+ bind() {
+ $(this.form).on('end', this.onRuleDropped, this);
+
+ this.form.querySelectorAll('ol').forEach(sortable => {
+ let options = {
+ scroll: true,
+ group: 'rules',
+ direction: 'vertical',
+ invertSwap: true,
+ handle: '.drag-initiator'
+ };
+
+ Sortable.create(sortable, options);
+ });
+
+ return this;
+ }
+
+ refresh(form) {
+ if (form === this.form) {
+ // If the DOM node is still the same, nothing has changed
+ return;
+ }
+
+ this.form = form;
+ this.bind();
+ }
+
+ destroy() {
+ this.form = null;
+ this.filterInput = null;
+ }
+
+ onRuleDropped(event) {
+ if (event.to === event.from && event.newIndex === event.oldIndex) {
+ // The user dropped the rule at its previous position
+ return;
+ }
+
+ let placement = 'before';
+ let neighbour = event.to.querySelector(':scope > :nth-child(' + (event.newIndex + 2) + ')');
+ if (! neighbour) {
+ // User dropped the rule at the end of a group
+ placement = 'after';
+ neighbour = event.to.querySelector(':scope > :nth-child(' + event.newIndex + ')')
+ if (! neighbour) {
+ // User dropped the rule into an empty group
+ placement = 'to';
+ neighbour = event.to.closest('[id]');
+ }
+ }
+
+ // It's a submit element, the very first one, otherwise Icinga Web 2 sends another "structural-change"
+ this.form.insertBefore(
+ $.render(
+ '<input type="hidden" name="structural-change[1]" value="' + placement + ':' + neighbour.id + '">'
+ ),
+ this.form.firstChild
+ );
+ this.form.insertBefore(
+ $.render('<input type="submit" name="structural-change[0]" value="move-rule:' + event.item.id + '">'),
+ this.form.firstChild
+ );
+
+ $(this.form).trigger('submit');
+ }
+ }
+
+ return SearchEditor;
+});
diff --git a/asset/js/widget/TermInput.js b/asset/js/widget/TermInput.js
new file mode 100644
index 0000000..537f4c4
--- /dev/null
+++ b/asset/js/widget/TermInput.js
@@ -0,0 +1,196 @@
+define(["../notjQuery", "BaseInput"], function ($, BaseInput) {
+
+ "use strict";
+
+ class TermInput extends BaseInput {
+ constructor(input) {
+ super(input);
+
+ this.separator = this.input.dataset.termSeparator || ' ';
+ this.ignoreSpaceUntil = null;
+ }
+
+ bind() {
+ super.bind();
+
+ // TODO: Compatibility only. Remove as soon as possible once Web 2.12 (?) is out.
+ // Or upon any other update which lets Web trigger a real submit upon auto submit.
+ $(this.input.form).on('change', 'select.autosubmit', this.onSubmit, this);
+ $(this.input.form).on('change', 'input.autosubmit', this.onSubmit, this);
+
+ return this;
+ }
+
+ reset() {
+ super.reset();
+
+ this.ignoreSpaceUntil = null;
+ }
+
+ readPartialTerm(input) {
+ let value = super.readPartialTerm(input);
+ if (value && this.ignoreSpaceUntil && value[0] === this.ignoreSpaceUntil) {
+ value = value.slice(1);
+ if (value.slice(-1) === this.ignoreSpaceUntil) {
+ value = value.slice(0, -1);
+ }
+ }
+
+ return value;
+ }
+
+ writePartialTerm(value, input) {
+ if (this.ignoreSpaceUntil !== null && this.ignoreSpaceSince === 0) {
+ value = this.ignoreSpaceUntil + value;
+ }
+
+ super.writePartialTerm(value, input);
+ }
+
+ readFullTerm(input, termIndex = null) {
+ let termData = super.readFullTerm(input, termIndex);
+ if (termData && this.ignoreSpaceUntil !== null && input.value[0] === this.ignoreSpaceUntil) {
+ if (input.value.slice(-1) !== this.ignoreSpaceUntil || input.value.length < 2) {
+ return false;
+ }
+
+ this.ignoreSpaceUntil = null;
+ }
+
+ return termData;
+ }
+
+ hasSyntaxError(input) {
+ if ((typeof input === 'undefined' || input === this.input) && this.ignoreSpaceUntil !== null) {
+ if (this.input.value === this.ignoreSpaceUntil) {
+ return true;
+ }
+ }
+
+ return super.hasSyntaxError(input);
+ }
+
+ termsToQueryString(terms) {
+ let quoted = [];
+ for (const termData of terms) {
+ let search = this.encodeTerm(termData).search;
+ if (search.indexOf(this.separator) >= 0) {
+ search = '"' + termData.search + '"';
+ }
+
+ quoted.push(search);
+ }
+
+ return quoted.join(this.separator).trim();
+ }
+
+ complete(input, data) {
+ data.exclude = this.usedTerms.map(termData => termData.search);
+
+ super.complete(input, data);
+ }
+
+ /**
+ * Event listeners
+ */
+
+ onSubmit(event) {
+ super.onSubmit(event);
+
+ this.ignoreSpaceUntil = null;
+ }
+
+ onInput(event) {
+ let label = event.target.parentNode;
+ if (label.dataset.index >= 0) {
+ super.onInput(event);
+ return;
+ }
+
+ let input = event.target;
+ let firstChar = input.value[0];
+
+ if (this.ignoreSpaceUntil !== null) {
+ // Reset if the user changes/removes the source char
+ if (firstChar !== this.ignoreSpaceUntil) {
+ this.ignoreSpaceUntil = null;
+ }
+ }
+
+ if (this.ignoreSpaceUntil === null && (firstChar === "'" || firstChar === '"')) {
+ this.ignoreSpaceUntil = firstChar;
+ }
+
+ super.onInput(event);
+ }
+
+ onKeyDown(event) {
+ super.onKeyDown(event);
+ if (event.defaultPrevented) {
+ return;
+ }
+
+ let label = event.target.parentNode;
+ if (label.dataset.index >= 0) {
+ return;
+ }
+
+ if (event.key !== this.separator && event.key !== 'Enter') {
+ return;
+ }
+
+ let addedTerms = this.exchangeTerm();
+ if (Object.keys(addedTerms).length) {
+ this.togglePlaceholder();
+ event.preventDefault();
+ this.autoSubmit(this.input, 'exchange', { terms: addedTerms });
+ }
+ }
+
+ onKeyUp(event) {
+ super.onKeyUp(event);
+
+ let label = event.target.parentNode;
+ if (label.dataset.index >= 0) {
+ return;
+ }
+
+ if (this.ignoreSpaceUntil !== null) {
+ // Reset if the user changes/removes the source char
+ let value = event.target.value;
+ if (value[this.ignoreSpaceSince] !== this.ignoreSpaceUntil) {
+ this.ignoreSpaceUntil = null;
+ this.ignoreSpaceSince = null;
+ }
+ }
+
+ let input = event.target;
+ switch (event.key) {
+ case '"':
+ case "'":
+ if (this.ignoreSpaceUntil === null) {
+ this.ignoreSpaceUntil = event.key;
+ this.ignoreSpaceSince = input.selectionStart - 1;
+ }
+ }
+ }
+
+ onButtonClick(event) {
+ if (! this.hasSyntaxError()) {
+ let addedTerms = this.exchangeTerm();
+ if (Object.keys(addedTerms).length) {
+ this.togglePlaceholder();
+ event.preventDefault();
+ this.autoSubmit(this.input, 'exchange', { terms: addedTerms });
+ this.ignoreSpaceUntil = null;
+
+ return;
+ }
+ }
+
+ super.onButtonClick(event);
+ }
+ }
+
+ return TermInput;
+});
diff --git a/asset/static/font/awesome/fa-brands-400.ttf b/asset/static/font/awesome/fa-brands-400.ttf
new file mode 100644
index 0000000..f10a07d
--- /dev/null
+++ b/asset/static/font/awesome/fa-brands-400.ttf
Binary files differ
diff --git a/asset/static/font/awesome/fa-brands-400.woff2 b/asset/static/font/awesome/fa-brands-400.woff2
new file mode 100644
index 0000000..15086bb
--- /dev/null
+++ b/asset/static/font/awesome/fa-brands-400.woff2
Binary files differ
diff --git a/asset/static/font/awesome/fa-regular-400.ttf b/asset/static/font/awesome/fa-regular-400.ttf
new file mode 100644
index 0000000..6a4c99f
--- /dev/null
+++ b/asset/static/font/awesome/fa-regular-400.ttf
Binary files differ
diff --git a/asset/static/font/awesome/fa-regular-400.woff2 b/asset/static/font/awesome/fa-regular-400.woff2
new file mode 100644
index 0000000..ccfb785
--- /dev/null
+++ b/asset/static/font/awesome/fa-regular-400.woff2
Binary files differ
diff --git a/asset/static/font/awesome/fa-solid-900.ttf b/asset/static/font/awesome/fa-solid-900.ttf
new file mode 100644
index 0000000..175b96f
--- /dev/null
+++ b/asset/static/font/awesome/fa-solid-900.ttf
Binary files differ
diff --git a/asset/static/font/awesome/fa-solid-900.woff2 b/asset/static/font/awesome/fa-solid-900.woff2
new file mode 100644
index 0000000..034deca
--- /dev/null
+++ b/asset/static/font/awesome/fa-solid-900.woff2
Binary files differ
diff --git a/asset/static/font/awesome/fa-v4compatibility.ttf b/asset/static/font/awesome/fa-v4compatibility.ttf
new file mode 100644
index 0000000..fdcc621
--- /dev/null
+++ b/asset/static/font/awesome/fa-v4compatibility.ttf
Binary files differ
diff --git a/asset/static/font/awesome/fa-v4compatibility.woff2 b/asset/static/font/awesome/fa-v4compatibility.woff2
new file mode 100644
index 0000000..2e22c38
--- /dev/null
+++ b/asset/static/font/awesome/fa-v4compatibility.woff2
Binary files differ
diff --git a/asset/static/font/icinga-icons/fonts/Icinga-Icons.svg b/asset/static/font/icinga-icons/fonts/Icinga-Icons.svg
new file mode 100644
index 0000000..6afa055
--- /dev/null
+++ b/asset/static/font/icinga-icons/fonts/Icinga-Icons.svg
@@ -0,0 +1,22 @@
+<?xml version="1.0" standalone="no"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" >
+<svg xmlns="http://www.w3.org/2000/svg">
+<metadata>Generated by IcoMoon</metadata>
+<defs>
+<font id="Icinga-Icons" horiz-adv-x="1024">
+<font-face units-per-em="1024" ascent="960" descent="-64" />
+<missing-glyph horiz-adv-x="1024" />
+<glyph unicode="&#x20;" horiz-adv-x="512" d="" />
+<glyph unicode="&#xe900;" glyph-name="list-view-minimal" d="M192.009 831.995c0-35.361-28.665-64.026-64.026-64.026s-64.026 28.665-64.026 64.026c0 35.361 28.665 64.026 64.026 64.026s64.026-28.665 64.026-64.026zM192.009 639.671c0-35.361-28.665-64.026-64.026-64.026s-64.026 28.665-64.026 64.026c0 35.361 28.665 64.026 64.026 64.026s64.026-28.665 64.026-64.026zM192.009 447.671c0-35.361-28.665-64.026-64.026-64.026s-64.026 28.665-64.026 64.026c0 35.361 28.665 64.026 64.026 64.026s64.026-28.665 64.026-64.026zM320.006 863.997h640.004v-64.005h-640.004v64.005zM320.006 479.674h640.004v-64.005h-640.004v64.005zM320.006 671.674h640.004v-64.005h-640.004v64.005zM320.006 287.674h640.004v-64.005h-640.004v64.005zM320.006 95.674h640.004v-64.005h-640.004v64.005zM192.009 255.348c0-35.361-28.665-64.026-64.026-64.026s-64.026 28.665-64.026 64.026c0 35.361 28.665 64.026 64.026 64.026s64.026-28.665 64.026-64.026zM192.009 63.671c0-35.361-28.665-64.026-64.026-64.026s-64.026 28.665-64.026 64.026c0 35.361 28.665 64.026 64.026 64.026s64.026-28.665 64.026-64.026z" />
+<glyph unicode="&#xe901;" glyph-name="list-view-detailed" d="M320.007 831.679h639.993v-191.358h-639.993v191.358zM320.007 575.997h639.993v-63.992h-639.993v63.992zM256.014 736.317c0-53.041-42.998-96.039-96.039-96.039s-96.039 42.998-96.039 96.039c0 53.041 42.998 96.039 96.039 96.039s96.039-42.998 96.039-96.039zM256.014 287.992c0-53.041-42.998-96.039-96.039-96.039s-96.039 42.998-96.039 96.039c0 53.041 42.998 96.039 96.039 96.039s96.039-42.998 96.039-96.039zM320.007 384.004h639.993v-192.005h-639.993v192.005zM320.007 128.005h639.993v-63.992h-639.993v63.992z" />
+<glyph unicode="&#xe902;" glyph-name="list-view-default" d="M256.015 767.992c0-53.041-42.998-96.039-96.039-96.039s-96.039 42.998-96.039 96.039c0 53.041 42.998 96.039 96.039 96.039s96.039-42.998 96.039-96.039zM384.001 864h576.002v-192.008h-576.002v192.008zM384.001 543.998h576.002v-192.008h-576.002v192.008zM384.001 223.998h576.002v-192.008h-576.002v192.008zM256.015 447.99c0-53.041-42.998-96.039-96.039-96.039s-96.039 42.998-96.039 96.039c0 53.041 42.998 96.039 96.039 96.039s96.039-42.998 96.039-96.039zM256.015 127.99c0-53.041-42.998-96.039-96.039-96.039s-96.039 42.998-96.039 96.039c0 53.041 42.998 96.039 96.039 96.039s96.039-42.998 96.039-96.039z" />
+<glyph unicode="&#xe903;" glyph-name="grid" d="M64.059 48.925v274.364c0 14.39 4.781 25.902 14.342 35.495s21.035 14.39 35.377 15.349h273.451c13.386 0 24.859-4.797 35.377-15.349s15.298-22.064 14.342-35.495v-274.364c0-13.43-4.781-24.942-14.342-34.535s-21.035-14.39-35.377-14.39h-273.451c-14.342 0-25.815 4.797-35.377 14.39s-14.342 21.105-14.342 34.535zM64.059 572.711v274.364c0 13.43 4.781 24.942 14.342 34.535s21.035 14.39 35.377 14.39h273.451c13.386 0 24.859-4.797 35.377-14.39s15.298-21.105 14.342-34.535v-274.364c0-14.39-4.781-25.902-14.342-35.495s-21.035-14.39-35.377-15.349h-273.451c-13.386 0-24.859 4.797-35.377 15.349s-15.298 22.064-14.342 35.495zM148.197 83.461h204.61v205.293h-204.61v-205.293zM148.197 607.247h204.61v204.334h-204.61v-204.334zM587.058 48.925v274.364c0 14.39 4.781 25.902 14.342 35.495s21.035 14.39 35.377 15.349h273.451c13.386 0 24.859-4.797 35.377-15.349s15.298-22.064 14.342-35.495v-274.364c0-13.43-4.781-24.942-14.342-34.535s-21.035-14.39-35.377-14.39h-273.451c-13.386 0-24.859 4.797-35.377 14.39s-15.298 21.105-14.342 34.535zM587.058 572.711v274.364c0 13.43 4.781 24.942 14.342 34.535s21.035 14.39 35.377 14.39h273.451c14.342 0 25.815-4.797 35.377-14.39s14.342-21.105 14.342-34.535v-274.364c0-14.39-4.781-25.902-14.342-35.495s-21.035-14.39-35.377-15.349h-273.451c-13.386 0-24.859 4.797-35.377 15.349s-15.298 22.064-14.342 35.495zM671.197 83.461h205.566v205.293h-205.566v-205.293zM671.197 607.247h205.566v204.334h-205.566v-204.334z" />
+<glyph unicode="&#xe904;" glyph-name="bracket-open" d="M473.568 179.2c0-59.098 44.467-107.789 101.76-114.432l6.682-0.576 6.758-0.192h-153.6l-6.758 0.192c-58.253 3.379-104.87 49.997-108.25 108.25l-0.192 6.758v537.6l0.192 6.758c3.226 55.91 46.349 101.107 101.299 107.635l6.95 0.614 6.758 0.192h153.6l-6.758-0.192c-55.91-3.226-101.107-46.349-107.635-101.299l-0.614-6.95-0.192-6.758v-537.6z" />
+<glyph unicode="&#xe905;" glyph-name="bracket-close" d="M447.136 179.2c0-59.098-44.467-107.789-101.76-114.432l-6.682-0.576-6.758-0.192h153.6l6.758 0.192c58.253 3.379 104.87 49.997 108.25 108.25l0.192 6.758v537.6l-0.192 6.758c-3.226 55.91-46.349 101.107-101.299 107.635l-6.95 0.614-6.758 0.192h-153.6l6.758-0.192c55.91-3.226 101.107-46.349 107.635-101.299l0.614-6.95 0.192-6.758v-537.6z" />
+<glyph unicode="&#xe906;" glyph-name="certificate" d="M64 960h896c35.328 0 64-28.672 64-64v-640c0-35.328-28.672-64-64-64h-350.72v64h350.72v640h-896v-640h33.28v-64h-33.28c-35.328 0-64 28.672-64 64v640c0 35.328 28.672 64 64 64zM576.048 478.878c0-123.698-100.277-223.976-223.976-223.976s-223.976 100.277-223.976 223.976c0 123.698 100.277 223.976 223.976 223.976s223.976-100.277 223.976-223.976zM511.488 239.104l64-303.104-224.32 128-223.168-128 64 303.488c45.76-30.656 100.8-48.576 160-48.576 58.944 0 113.792 17.728 159.488 48.192zM896 768c0 16.96-6.784 33.28-18.752 45.248-12.032 12.032-28.288 18.752-45.248 18.752-71.040 0-185.024 0-256 0-17.024 0-33.28-6.72-45.248-18.752-12.032-11.968-18.752-28.288-18.752-45.248s6.72-33.28 18.752-45.248c11.968-12.032 28.224-18.752 45.248-18.752 70.976 0 184.96 0 256 0 16.96 0 33.216 6.72 45.248 18.752 11.968 11.968 18.752 28.288 18.752 45.248zM896 576c0 16.96-6.784 33.28-18.752 45.248-12.032 12.032-28.288 18.752-45.248 18.752-71.040 0-57.024 0-128 0-17.024 0-33.28-6.72-45.248-18.752-12.032-11.968-18.752-28.288-18.752-45.248s6.72-33.28 18.752-45.248c11.968-12.032 28.224-18.752 45.248-18.752 70.976 0 56.96 0 128 0 16.96 0 33.216 6.72 45.248 18.752 11.968 11.968 18.752 28.288 18.752 45.248z" />
+<glyph unicode="&#xe907;" glyph-name="icinga" d="M574.496 878.589l45.262-8.286-149.128-422.304-45.261 8.286 149.126 422.304zM896.001 590.671v-29.341l-379.111-128.001-9.78 29.341 388.891 128.001zM656 192v-43.787l-164.906 224.295 41.812 23.571 123.093-204.079zM205.566 114.412l-27.131 27.175 205.565 242.414 63.999-13.589-242.434-255.999zM192.001 639.999l-38.798 52.36 308.952-225.624-28.309-38.763-241.845 212.028zM576.418 959.103c75.061 0 136.002-60.94 136.002-136s-60.941-136-136.002-136c-75.058 0-135.999 60.94-135.999 136s60.941 136 135.999 136zM911.998 687.103c61.815 0 111.999-50.187 111.999-112 0-61.816-50.185-112-111.999-112s-111.999 50.184-111.999 112c0 61.813 50.185 112 111.999 112zM656 240.002c44.154 0 80.002-35.85 80.002-80.001 0-44.155-35.848-80.001-80.002-80.001-44.15 0-79.998 35.846-79.998 80.001 0 44.151 35.848 80.001 79.998 80.001zM143.999 224.001c79.478 0 144.002-64.526 144.002-144.002s-64.524-143.999-144.002-143.999c-79.475 0-143.999 64.524-143.999 143.999s64.524 144.002 143.999 144.002zM139.048 768.978c52.984 0 96.001-43.016 96.001-96.001 0-52.982-43.018-95.998-96.001-95.998s-95.998 43.016-95.998 95.998c0 52.985 43.014 96.001 95.998 96.001zM448 640.294c105.968 0 192-86.034 192-192.001s-86.032-191.999-192-191.999c-105.968 0-192 86.032-192 191.999s86.032 192.001 192 192.001z" />
+<glyph unicode="&#xe908;" glyph-name="ca-circle-check" d="M177.038 352.521c-5.88-0.539-12.299-0.833-19.306-0.833-22.54 0-43.317 4.018-62.378 12.103-19.061 8.036-35.672 19.453-49.883 34.202-14.259 14.749-25.382 32.34-33.418 52.725s-12.103 43.072-12.103 68.013c0 24.941 4.165 47.727 12.495 68.405s19.6 38.22 33.81 52.725c14.21 14.504 30.968 25.48 50.324 33.026 19.306 7.497 40.23 11.27 62.77 11.27 20.384 0 40.671-3.92 60.761-11.711 20.139-7.742 36.358-19.159 48.707-34.202l-48.266-52.333c-6.468 10.241-15.043 17.591-25.774 22.148s-22.001 6.86-33.81 6.86c-11.809 0-22.932-2.401-33.418-7.252-10.437-4.851-19.453-11.515-26.95-20.139-7.497-8.575-13.279-18.767-17.297-30.576s-6.076-24.696-6.076-38.613c0-13.965 2.058-26.999 6.076-39.054 4.018-12.103 9.8-22.295 17.297-30.576 7.497-8.33 16.219-14.896 26.166-19.747 9.898-4.802 21.070-7.252 33.369-7.252 13.965 0 26.313 2.989 37.044 8.869 8.575 4.851 15.827 11.025 21.756 18.522l-41.896-96.58zM484.864 365.888l-18.752 49.408h-123.2l-23.296-63.616h-82.944l132.8 321.984h74.88l90.688-222.4c-21.632-25.92-38.336-54.336-50.176-85.376zM405.696 587.52l-40.192-110.272h79.68l-39.488 110.272zM1024 254.976c-2.176-72.512-27.456-132.992-75.84-181.504-48.384-48.576-108.672-73.344-180.992-74.496-72.256 1.152-132.288 25.92-180.096 74.496-47.808 48.512-72.832 108.992-75.072 181.504 2.24 72.512 27.264 133.056 75.072 181.568s107.84 73.344 180.096 74.432c72.32-1.088 132.608-25.92 180.992-74.432s73.664-109.056 75.84-181.568zM966.144 378.752c-0.512 0.704-1.088 1.344-1.728 1.92-22.656 22.72-59.52 22.72-82.176 0l-80.448-80.32-33.024-76.608c0 0-25.6 65.728-25.6 65.728l-29.312 29.312c-22.656 22.656-59.52 22.656-82.176 0-22.72-22.72-22.72-59.52 0-82.24l94.272-94.272c11.2-11.2 25.856-16.832 40.512-16.96 0.448 0 0.896 0 1.28 0 14.656 0.192 29.248 5.824 40.384 16.96l156.224 156.224c22.016 22.016 22.656 57.472 1.792 80.256z" />
+<glyph unicode="&#xe909;" glyph-name="refresh-cert" d="M319.936 512h384v-257.088h-384v257.088zM383.936 544v96c0 35.328 28.672 64 64 64h128c35.328 0 64-28.672 64-64v-96h-256zM575.936 640h-128v-96h128v96zM192.448 235.136c68.864-103.168 186.368-171.136 319.552-171.136 141.568 0 265.344 76.8 331.904 190.912h142.4c-76.288-187.008-260.032-318.912-474.304-318.912-180.544 0-339.392 93.632-430.592 235.008l-81.536-47.104 2.112 324.096 281.472-160.384-91.008-52.48zM833.472 657.92c-68.544 104.832-187.008 174.080-321.472 174.080-167.040 0-309.376-106.944-362.112-256h-133.76c56.896 220.736 257.472 384 495.872 384 181.824 0 341.632-94.976 432.448-237.952l79.68 45.952-2.112-324.096-281.472 160.384 92.928 53.632z" />
+<glyph unicode="&#xe90a;" glyph-name="th-list" d="M64.491 172.602c0-19.125 6.694-35.381 20.081-48.768s29.644-20.081 48.768-20.081h30.6c19.125 0 35.381 6.694 48.768 20.081s20.081 29.644 20.081 48.768c0 19.125-6.694 35.381-20.081 48.768s-29.644 20.081-48.768 20.081h-30.6c-19.125 0-35.381-6.694-48.768-20.081s-20.081-29.644-20.081-48.768zM64.491 448c0-19.125 6.694-35.381 20.081-48.768s29.644-20.081 48.768-20.081h30.6c19.125 0 35.381 6.694 48.768 20.081s20.081 29.644 20.081 48.768c0 19.125-6.694 35.381-20.081 48.768s-29.644 20.081-48.768 20.081h-30.6c-19.125 0-35.381-6.694-48.768-20.081s-20.081-29.644-20.081-48.768zM64.491 723.398c0-19.125 6.694-35.381 20.081-48.768s29.644-20.081 48.768-20.081h30.6c19.125 0 35.381 6.694 48.768 20.081s20.081 29.644 20.081 48.768c0 19.125-6.694 35.381-20.081 48.768s-29.644 20.081-48.768 20.081h-30.6c-19.125 0-35.381-6.694-48.768-20.081s-20.081-29.644-20.081-48.768zM288.252 172.602c0-19.125 6.694-35.381 20.081-48.768s29.644-20.081 48.768-20.081h534.54c19.125 0 35.381 6.694 48.768 20.081s20.081 29.644 20.081 48.768c0 19.125-6.694 35.381-20.081 48.768s-29.644 20.081-48.768 20.081h-534.54c-19.125 0-35.381-6.694-48.768-20.081s-20.081-29.644-20.081-48.768zM288.252 448c0-19.125 6.694-35.381 20.081-48.768s29.644-20.081 48.768-20.081h534.54c19.125 0 35.381 6.694 48.768 20.081s20.081 29.644 20.081 48.768c0 19.125-6.694 35.381-20.081 48.768s-29.644 20.081-48.768 20.081h-534.54c-19.125 0-35.381-6.694-48.768-20.081s-20.081-29.644-20.081-48.768zM288.252 723.398c0-19.125 6.694-35.381 20.081-48.768s29.644-20.081 48.768-20.081h534.54c19.125 0 35.381 6.694 48.768 20.081s20.081 29.644 20.081 48.768c0 19.125-6.694 35.381-20.081 48.768s-29.644 20.081-48.768 20.081h-534.54c-19.125 0-35.381-6.694-48.768-20.081s-20.081-29.644-20.081-48.768z" />
+<glyph unicode="&#xe90b;" glyph-name="filter-check-circle" d="M7.232 869.504c11.776 24.896 36.672 40.704 64.192 40.704h768c27.584 0 52.48-15.808 64.192-40.704s8.192-54.208-9.216-75.52l-189.376-231.488c-142.592-29.312-249.6-155.392-249.6-306.496 0-48.704 11.2-94.912 31.104-136-2.816 1.408-5.696 3.2-8.32 5.184l-113.792 85.312c-14.4 10.688-22.784 27.52-22.784 45.504v140.608l-325.312 397.504c-17.216 21.184-20.992 50.688-9.088 75.392zM1024 254.976c-2.176-72.512-27.456-132.992-75.84-181.504-48.384-48.576-108.672-73.344-180.992-74.496-72.256 1.152-132.288 25.92-180.096 74.496-47.808 48.512-72.832 108.992-75.072 181.504 2.24 72.512 27.264 133.056 75.072 181.568s107.84 73.344 180.096 74.432c72.32-1.088 132.608-25.92 180.992-74.432s73.664-109.056 75.84-181.568zM966.144 378.752c-0.512 0.704-1.088 1.344-1.728 1.92-22.656 22.72-59.52 22.72-82.176 0l-80.448-80.32-33.024-76.608c0 0-25.6 65.728-25.6 65.728l-29.312 29.312c-22.656 22.656-59.52 22.656-82.176 0-22.72-22.72-22.72-59.52 0-82.24l94.272-94.272c11.2-11.2 25.856-16.832 40.512-16.96 0.448 0 0.896 0 1.28 0 14.656 0.192 29.248 5.824 40.384 16.96l156.224 156.224c22.016 22.016 22.656 57.472 1.792 80.256z" />
+</font></defs></svg> \ No newline at end of file
diff --git a/asset/static/font/icinga-icons/fonts/Icinga-Icons.ttf b/asset/static/font/icinga-icons/fonts/Icinga-Icons.ttf
new file mode 100644
index 0000000..c281593
--- /dev/null
+++ b/asset/static/font/icinga-icons/fonts/Icinga-Icons.ttf
Binary files differ
diff --git a/asset/static/font/icinga-icons/fonts/Icinga-Icons.woff b/asset/static/font/icinga-icons/fonts/Icinga-Icons.woff
new file mode 100644
index 0000000..7f8ef7a
--- /dev/null
+++ b/asset/static/font/icinga-icons/fonts/Icinga-Icons.woff
Binary files differ
diff --git a/asset/static/font/icinga-icons/selection.json b/asset/static/font/icinga-icons/selection.json
new file mode 100644
index 0000000..015faf0
--- /dev/null
+++ b/asset/static/font/icinga-icons/selection.json
@@ -0,0 +1 @@
+{"IcoMoonType":"selection","icons":[{"icon":{"paths":["M64 0h896c35.328 0 64 28.672 64 64v640c0 35.328-28.672 64-64 64h-350.72v-64h350.72v-640h-896v640h33.28v64h-33.28c-35.328 0-64-28.672-64-64v-640c0-35.328 28.672-64 64-64z","M576.048 481.122c0 123.698-100.277 223.976-223.976 223.976s-223.976-100.277-223.976-223.976c0-123.698 100.277-223.976 223.976-223.976s223.976 100.277 223.976 223.976z","M511.488 720.896l64 303.104-224.32-128-223.168 128 64-303.488c45.76 30.656 100.8 48.576 160 48.576 58.944 0 113.792-17.728 159.488-48.192z","M896 192c0-16.96-6.784-33.28-18.752-45.248-12.032-12.032-28.288-18.752-45.248-18.752-71.040 0-185.024 0-256 0-17.024 0-33.28 6.72-45.248 18.752-12.032 11.968-18.752 28.288-18.752 45.248s6.72 33.28 18.752 45.248c11.968 12.032 28.224 18.752 45.248 18.752 70.976 0 184.96 0 256 0 16.96 0 33.216-6.72 45.248-18.752 11.968-11.968 18.752-28.288 18.752-45.248z","M896 384c0-16.96-6.784-33.28-18.752-45.248-12.032-12.032-28.288-18.752-45.248-18.752-71.040 0-57.024 0-128 0-17.024 0-33.28 6.72-45.248 18.752-12.032 11.968-18.752 28.288-18.752 45.248s6.72 33.28 18.752 45.248c11.968 12.032 28.224 18.752 45.248 18.752 70.976 0 56.96 0 128 0 16.96 0 33.216-6.72 45.248-18.752 11.968-11.968 18.752-28.288 18.752-45.248z"],"attrs":[],"grid":0,"tags":["certificate"]},"attrs":[],"properties":{"order":18,"id":11,"name":"certificate","prevSize":32,"code":59654},"setIdx":0,"setId":1,"iconIdx":0},{"icon":{"paths":["M7.232 90.496c11.776-24.896 36.672-40.704 64.192-40.704h768c27.584 0 52.48 15.808 64.192 40.704s8.192 54.208-9.216 75.52l-189.376 231.488c-142.592 29.312-249.6 155.392-249.6 306.496 0 48.704 11.2 94.912 31.104 136-2.816-1.408-5.696-3.2-8.32-5.184l-113.792-85.312c-14.4-10.688-22.784-27.52-22.784-45.504v-140.608l-325.312-397.504c-17.216-21.184-20.992-50.688-9.088-75.392z","M1024 705.024c-2.176 72.512-27.456 132.992-75.84 181.504-48.384 48.576-108.672 73.344-180.992 74.496-72.256-1.152-132.288-25.92-180.096-74.496-47.808-48.512-72.832-108.992-75.072-181.504 2.24-72.512 27.264-133.056 75.072-181.568s107.84-73.344 180.096-74.432c72.32 1.088 132.608 25.92 180.992 74.432s73.664 109.056 75.84 181.568zM966.144 581.248c-0.512-0.704-1.088-1.344-1.728-1.92-22.656-22.72-59.52-22.72-82.176 0l-80.448 80.32-33.024 76.608c0 0-25.6-65.728-25.6-65.728l-29.312-29.312c-22.656-22.656-59.52-22.656-82.176 0-22.72 22.72-22.72 59.52 0 82.24l94.272 94.272c11.2 11.2 25.856 16.832 40.512 16.96 0.448 0 0.896 0 1.28 0 14.656-0.192 29.248-5.824 40.384-16.96l156.224-156.224c22.016-22.016 22.656-57.472 1.792-80.256z"],"attrs":[],"grid":0,"tags":["filter-check-circle"]},"attrs":[],"properties":{"order":15,"id":10,"name":"filter-check-circle","prevSize":32,"code":59659},"setIdx":0,"setId":1,"iconIdx":1},{"icon":{"paths":["M177.038 607.479c-5.88 0.539-12.299 0.833-19.306 0.833-22.54 0-43.317-4.018-62.378-12.103-19.061-8.036-35.672-19.453-49.883-34.202-14.259-14.749-25.382-32.34-33.418-52.725s-12.103-43.072-12.103-68.013c0-24.941 4.165-47.727 12.495-68.405s19.6-38.22 33.81-52.725c14.21-14.504 30.968-25.48 50.324-33.026 19.306-7.497 40.23-11.27 62.77-11.27 20.384 0 40.671 3.92 60.761 11.711 20.139 7.742 36.358 19.159 48.707 34.202l-48.266 52.333c-6.468-10.241-15.043-17.591-25.774-22.148s-22.001-6.86-33.81-6.86c-11.809 0-22.932 2.401-33.418 7.252-10.437 4.851-19.453 11.515-26.95 20.139-7.497 8.575-13.279 18.767-17.297 30.576s-6.076 24.696-6.076 38.613c0 13.965 2.058 26.999 6.076 39.054 4.018 12.103 9.8 22.295 17.297 30.576 7.497 8.33 16.219 14.896 26.166 19.747 9.898 4.802 21.070 7.252 33.369 7.252 13.965 0 26.313-2.989 37.044-8.869 8.575-4.851 15.827-11.025 21.756-18.522l-41.896 96.58z","M484.864 594.112l-18.752-49.408h-123.2l-23.296 63.616h-82.944l132.8-321.984h74.88l90.688 222.4c-21.632 25.92-38.336 54.336-50.176 85.376zM405.696 372.48l-40.192 110.272h79.68l-39.488-110.272z","M1024 705.024c-2.176 72.512-27.456 132.992-75.84 181.504-48.384 48.576-108.672 73.344-180.992 74.496-72.256-1.152-132.288-25.92-180.096-74.496-47.808-48.512-72.832-108.992-75.072-181.504 2.24-72.512 27.264-133.056 75.072-181.568s107.84-73.344 180.096-74.432c72.32 1.088 132.608 25.92 180.992 74.432s73.664 109.056 75.84 181.568zM966.144 581.248c-0.512-0.704-1.088-1.344-1.728-1.92-22.656-22.72-59.52-22.72-82.176 0l-80.448 80.32-33.024 76.608c0 0-25.6-65.728-25.6-65.728l-29.312-29.312c-22.656-22.656-59.52-22.656-82.176 0-22.72 22.72-22.72 59.52 0 82.24l94.272 94.272c11.2 11.2 25.856 16.832 40.512 16.96 0.448 0 0.896 0 1.28 0 14.656-0.192 29.248-5.824 40.384-16.96l156.224-156.224c22.016-22.016 22.656-57.472 1.792-80.256z"],"attrs":[],"grid":0,"tags":["filter-circle-check"]},"attrs":[],"properties":{"order":16,"id":9,"name":"ca-circle-check","prevSize":32,"code":59656},"setIdx":0,"setId":1,"iconIdx":2},{"icon":{"paths":["M319.936 448h384v257.088h-384v-257.088z","M383.936 416v-96c0-35.328 28.672-64 64-64h128c35.328 0 64 28.672 64 64v96h-256zM575.936 320h-128v96h128v-96z","M192.448 724.864c68.864 103.168 186.368 171.136 319.552 171.136 141.568 0 265.344-76.8 331.904-190.912h142.4c-76.288 187.008-260.032 318.912-474.304 318.912-180.544 0-339.392-93.632-430.592-235.008l-81.536 47.104 2.112-324.096 281.472 160.384-91.008 52.48zM833.472 302.080c-68.544-104.832-187.008-174.080-321.472-174.080-167.040 0-309.376 106.944-362.112 256h-133.76c56.896-220.736 257.472-384 495.872-384 181.824 0 341.632 94.976 432.448 237.952l79.68-45.952-2.112 324.096-281.472-160.384 92.928-53.632z"],"attrs":[],"grid":0,"tags":["refresh-cert"]},"attrs":[],"properties":{"order":17,"id":8,"name":"refresh-cert","prevSize":32,"code":59657},"setIdx":0,"setId":1,"iconIdx":3},{"icon":{"paths":["M64.491 787.398c0 19.125 6.694 35.381 20.081 48.768s29.644 20.081 48.768 20.081h30.6c19.125 0 35.381-6.694 48.768-20.081s20.081-29.644 20.081-48.768c0-19.125-6.694-35.381-20.081-48.768s-29.644-20.081-48.768-20.081h-30.6c-19.125 0-35.381 6.694-48.768 20.081s-20.081 29.644-20.081 48.768zM64.491 512c0 19.125 6.694 35.381 20.081 48.768s29.644 20.081 48.768 20.081h30.6c19.125 0 35.381-6.694 48.768-20.081s20.081-29.644 20.081-48.768c0-19.125-6.694-35.381-20.081-48.768s-29.644-20.081-48.768-20.081h-30.6c-19.125 0-35.381 6.694-48.768 20.081s-20.081 29.644-20.081 48.768zM64.491 236.602c0 19.125 6.694 35.381 20.081 48.768s29.644 20.081 48.768 20.081h30.6c19.125 0 35.381-6.694 48.768-20.081s20.081-29.644 20.081-48.768c0-19.125-6.694-35.381-20.081-48.768s-29.644-20.081-48.768-20.081h-30.6c-19.125 0-35.381 6.694-48.768 20.081s-20.081 29.644-20.081 48.768zM288.252 787.398c0 19.125 6.694 35.381 20.081 48.768s29.644 20.081 48.768 20.081h534.54c19.125 0 35.381-6.694 48.768-20.081s20.081-29.644 20.081-48.768c0-19.125-6.694-35.381-20.081-48.768s-29.644-20.081-48.768-20.081h-534.54c-19.125 0-35.381 6.694-48.768 20.081s-20.081 29.644-20.081 48.768zM288.252 512c0 19.125 6.694 35.381 20.081 48.768s29.644 20.081 48.768 20.081h534.54c19.125 0 35.381-6.694 48.768-20.081s20.081-29.644 20.081-48.768c0-19.125-6.694-35.381-20.081-48.768s-29.644-20.081-48.768-20.081h-534.54c-19.125 0-35.381 6.694-48.768 20.081s-20.081 29.644-20.081 48.768zM288.252 236.602c0 19.125 6.694 35.381 20.081 48.768s29.644 20.081 48.768 20.081h534.54c19.125 0 35.381-6.694 48.768-20.081s20.081-29.644 20.081-48.768c0-19.125-6.694-35.381-20.081-48.768s-29.644-20.081-48.768-20.081h-534.54c-19.125 0-35.381 6.694-48.768 20.081s-20.081 29.644-20.081 48.768z"],"attrs":[],"grid":0,"tags":["th-list"]},"attrs":[],"properties":{"order":11,"id":7,"name":"th-list","prevSize":32,"code":59658},"setIdx":0,"setId":1,"iconIdx":4},{"icon":{"paths":["M574.496 81.411l45.262 8.286-149.128 422.304-45.261-8.286 149.126-422.304z","M896.001 369.329v29.341l-379.111 128.001-9.78-29.341 388.891-128.001z","M656 768v43.787l-164.906-224.295 41.812-23.571 123.093 204.079z","M205.566 845.588l-27.131-27.175 205.565-242.414 63.999 13.589-242.434 255.999z","M192.001 320.001l-38.798-52.36 308.952 225.624-28.309 38.763-241.845-212.028z","M576.418 0.897c75.061 0 136.002 60.94 136.002 136s-60.941 136-136.002 136c-75.058 0-135.999-60.94-135.999-136s60.941-136 135.999-136z","M911.998 272.897c61.815 0 111.999 50.187 111.999 112 0 61.816-50.185 112-111.999 112s-111.999-50.184-111.999-112c0-61.813 50.185-112 111.999-112z","M656 719.998c44.154 0 80.002 35.85 80.002 80.001 0 44.155-35.848 80.001-80.002 80.001-44.15 0-79.998-35.846-79.998-80.001 0-44.151 35.848-80.001 79.998-80.001z","M143.999 735.999c79.478 0 144.002 64.526 144.002 144.002s-64.524 143.999-144.002 143.999c-79.475 0-143.999-64.524-143.999-143.999s64.524-144.002 143.999-144.002z","M139.048 191.022c52.984 0 96.001 43.016 96.001 96.001 0 52.982-43.018 95.998-96.001 95.998s-95.998-43.016-95.998-95.998c0-52.985 43.014-96.001 95.998-96.001z","M448 319.706c105.968 0 192 86.034 192 192.001s-86.032 191.999-192 191.999c-105.968 0-192-86.032-192-191.999s86.032-192.001 192-192.001z"],"attrs":[],"grid":0,"tags":["icinga"]},"attrs":[],"properties":{"order":10,"id":6,"name":"icinga","prevSize":32,"code":59655},"setIdx":0,"setId":1,"iconIdx":5},{"icon":{"paths":["M192.009 128.005c0 35.361-28.665 64.026-64.026 64.026s-64.026-28.665-64.026-64.026c0-35.361 28.665-64.026 64.026-64.026s64.026 28.665 64.026 64.026z","M192.009 320.329c0 35.361-28.665 64.026-64.026 64.026s-64.026-28.665-64.026-64.026c0-35.361 28.665-64.026 64.026-64.026s64.026 28.665 64.026 64.026z","M192.009 512.329c0 35.361-28.665 64.026-64.026 64.026s-64.026-28.665-64.026-64.026c0-35.361 28.665-64.026 64.026-64.026s64.026 28.665 64.026 64.026z","M320.006 96.003h640.004v64.005h-640.004v-64.005z","M320.006 480.326h640.004v64.005h-640.004v-64.005z","M320.006 288.326h640.004v64.005h-640.004v-64.005z","M320.006 672.326h640.004v64.005h-640.004v-64.005z","M320.006 864.326h640.004v64.005h-640.004v-64.005z","M192.009 704.652c0 35.361-28.665 64.026-64.026 64.026s-64.026-28.665-64.026-64.026c0-35.361 28.665-64.026 64.026-64.026s64.026 28.665 64.026 64.026z","M192.009 896.329c0 35.361-28.665 64.026-64.026 64.026s-64.026-28.665-64.026-64.026c0-35.361 28.665-64.026 64.026-64.026s64.026 28.665 64.026 64.026z"],"attrs":[],"grid":0,"tags":["list-view-minimal"]},"attrs":[],"properties":{"order":4,"id":5,"name":"list-view-minimal","prevSize":32,"code":59648},"setIdx":0,"setId":1,"iconIdx":6},{"icon":{"paths":["M320.007 128.321h639.993v191.358h-639.993v-191.358z","M320.007 384.003h639.993v63.992h-639.993v-63.992z","M256.014 223.683c0 53.041-42.998 96.039-96.039 96.039s-96.039-42.998-96.039-96.039c0-53.041 42.998-96.039 96.039-96.039s96.039 42.998 96.039 96.039z","M256.014 672.008c0 53.041-42.998 96.039-96.039 96.039s-96.039-42.998-96.039-96.039c0-53.041 42.998-96.039 96.039-96.039s96.039 42.998 96.039 96.039z","M320.007 575.996h639.993v192.005h-639.993v-192.005z","M320.007 831.995h639.993v63.992h-639.993v-63.992z"],"attrs":[],"grid":0,"tags":["list-view-detailed"]},"attrs":[],"properties":{"order":5,"id":4,"name":"list-view-detailed","prevSize":32,"code":59649},"setIdx":0,"setId":1,"iconIdx":7},{"icon":{"paths":["M256.015 192.008c0 53.041-42.998 96.039-96.039 96.039s-96.039-42.998-96.039-96.039c0-53.041 42.998-96.039 96.039-96.039s96.039 42.998 96.039 96.039z","M384.001 96h576.002v192.008h-576.002v-192.008z","M384.001 416.002h576.002v192.008h-576.002v-192.008z","M384.001 736.002h576.002v192.008h-576.002v-192.008z","M256.015 512.010c0 53.041-42.998 96.039-96.039 96.039s-96.039-42.998-96.039-96.039c0-53.041 42.998-96.039 96.039-96.039s96.039 42.998 96.039 96.039z","M256.015 832.010c0 53.041-42.998 96.039-96.039 96.039s-96.039-42.998-96.039-96.039c0-53.041 42.998-96.039 96.039-96.039s96.039 42.998 96.039 96.039z"],"attrs":[],"grid":0,"tags":["listr-view-default"]},"attrs":[],"properties":{"order":6,"id":3,"name":"list-view-default","prevSize":32,"code":59650},"setIdx":0,"setId":1,"iconIdx":8},{"icon":{"paths":["M64.059 911.075v-274.364c0-14.39 4.781-25.902 14.342-35.495s21.035-14.39 35.377-15.349h273.451c13.386 0 24.859 4.797 35.377 15.349s15.298 22.064 14.342 35.495v274.364c0 13.43-4.781 24.942-14.342 34.535s-21.035 14.39-35.377 14.39h-273.451c-14.342 0-25.815-4.797-35.377-14.39s-14.342-21.105-14.342-34.535zM64.059 387.289v-274.364c0-13.43 4.781-24.942 14.342-34.535s21.035-14.39 35.377-14.39h273.451c13.386 0 24.859 4.797 35.377 14.39s15.298 21.105 14.342 34.535v274.364c0 14.39-4.781 25.902-14.342 35.495s-21.035 14.39-35.377 15.349h-273.451c-13.386 0-24.859-4.797-35.377-15.349s-15.298-22.064-14.342-35.495zM148.197 876.539h204.61v-205.293h-204.61v205.293zM148.197 352.753h204.61v-204.334h-204.61v204.334zM587.058 911.075v-274.364c0-14.39 4.781-25.902 14.342-35.495s21.035-14.39 35.377-15.349h273.451c13.386 0 24.859 4.797 35.377 15.349s15.298 22.064 14.342 35.495v274.364c0 13.43-4.781 24.942-14.342 34.535s-21.035 14.39-35.377 14.39h-273.451c-13.386 0-24.859-4.797-35.377-14.39s-15.298-21.105-14.342-34.535zM587.058 387.289v-274.364c0-13.43 4.781-24.942 14.342-34.535s21.035-14.39 35.377-14.39h273.451c14.342 0 25.815 4.797 35.377 14.39s14.342 21.105 14.342 34.535v274.364c0 14.39-4.781 25.902-14.342 35.495s-21.035 14.39-35.377 15.349h-273.451c-13.386 0-24.859-4.797-35.377-15.349s-15.298-22.064-14.342-35.495zM671.197 876.539h205.566v-205.293h-205.566v205.293zM671.197 352.753h205.566v-204.334h-205.566v204.334z"],"attrs":[],"grid":0,"tags":["th-thumb-empty"]},"attrs":[],"properties":{"order":7,"id":2,"name":"grid","prevSize":32,"code":59651},"setIdx":0,"setId":1,"iconIdx":9},{"icon":{"paths":["M473.568 780.8c0 59.098 44.467 107.789 101.76 114.432l6.682 0.576 6.758 0.192h-153.6l-6.758-0.192c-58.253-3.379-104.87-49.997-108.25-108.25l-0.192-6.758v-537.6l0.192-6.758c3.226-55.91 46.349-101.107 101.299-107.635l6.95-0.614 6.758-0.192h153.6l-6.758 0.192c-55.91 3.226-101.107 46.349-107.635 101.299l-0.614 6.95-0.192 6.758v537.6z"],"attrs":[],"grid":0,"tags":["bracket-open"]},"attrs":[],"properties":{"order":8,"id":1,"name":"bracket-open","prevSize":32,"code":59652},"setIdx":0,"setId":1,"iconIdx":10},{"icon":{"paths":["M447.136 780.8c0 59.098-44.467 107.789-101.76 114.432l-6.682 0.576-6.758 0.192h153.6l6.758-0.192c58.253-3.379 104.87-49.997 108.25-108.25l0.192-6.758v-537.6l-0.192-6.758c-3.226-55.91-46.349-101.107-101.299-107.635l-6.95-0.614-6.758-0.192h-153.6l6.758 0.192c55.91 3.226 101.107 46.349 107.635 101.299l0.614 6.95 0.192 6.758v537.6z"],"attrs":[],"grid":0,"tags":["bracket-close"]},"attrs":[],"properties":{"order":13,"id":0,"name":"bracket-close","prevSize":32,"code":59653},"setIdx":0,"setId":1,"iconIdx":11}],"height":1024,"metadata":{"name":"Icinga-Icons","url":"https://icinga.com","designer":"Florian Strohmaier (Icinga)","designerURL":"https://icinga.com","license":"Proprietary"},"preferences":{"showGlyphs":true,"showQuickUse":true,"showQuickUse2":true,"showSVGs":true,"fontPref":{"prefix":"iicon-","metadata":{"fontFamily":"Icinga-Icons","majorVersion":1,"minorVersion":0,"fontURL":"https://icinga.com","copyright":"Icinga GmbH","designer":"Florian Strohmaier (Icinga)","designerURL":"https://icinga.com","license":"Proprietary"},"metrics":{"emSize":1024,"baseline":6.25,"whitespace":50},"embed":false,"noie8":true,"ie7":false,"showSelector":true,"showMetrics":false,"showMetadata":false,"showVersion":false},"imagePref":{"prefix":"icon-","png":true,"useClassSelector":true,"color":0,"bgColor":16777215,"classSelector":".icon"},"historySize":50,"showCodes":true,"gridSize":16,"showGrid":false}} \ No newline at end of file
diff --git a/asset/static/font/icinga-icons/src/bracket-close.svg b/asset/static/font/icinga-icons/src/bracket-close.svg
new file mode 100644
index 0000000..0656ae8
--- /dev/null
+++ b/asset/static/font/icinga-icons/src/bracket-close.svg
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg width="100%" height="100%" viewBox="0 0 16 16" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" xmlns:serif="http://www.serif.com/" style="fill-rule:evenodd;clip-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:2;">
+ <g transform="matrix(1,0,0,1,-120,-134)">
+ <g transform="matrix(0.25,0,0,0.25,120,134)">
+ <rect id="bracket-close" x="0" y="0" width="64" height="64" style="fill:none;"/>
+ <g id="bracket-close1" serif:id="bracket-close">
+ <g transform="matrix(2.4,0,0,2.4,20.746,8)">
+ <path d="M3,17C3,18.539 1.842,19.807 0.35,19.98L0.176,19.995L0,20L4,20L4.176,19.995C5.693,19.907 6.907,18.693 6.995,17.176L7,17L7,3L6.995,2.824C6.911,1.368 5.788,0.191 4.357,0.021L4.176,0.005L4,0L0,0L0.176,0.005C1.632,0.089 2.809,1.212 2.979,2.643L2.995,2.824L3,3L3,17Z"/>
+ </g>
+ </g>
+ </g>
+ </g>
+</svg>
diff --git a/asset/static/font/icinga-icons/src/bracket-open.svg b/asset/static/font/icinga-icons/src/bracket-open.svg
new file mode 100644
index 0000000..c604286
--- /dev/null
+++ b/asset/static/font/icinga-icons/src/bracket-open.svg
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg width="100%" height="100%" viewBox="0 0 16 16" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" xmlns:serif="http://www.serif.com/" style="fill-rule:evenodd;clip-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:2;">
+ <g transform="matrix(1,0,0,1,-100,-134)">
+ <g transform="matrix(0.25,0,0,0.25,100,134)">
+ <rect id="bracket-open" x="0" y="0" width="64" height="64" style="fill:none;"/>
+ <g id="bracket-open1" serif:id="bracket-open">
+ <g transform="matrix(-2.4,0,0,2.4,36.846,8)">
+ <path d="M3,17C3,18.539 1.842,19.807 0.35,19.98L0.176,19.995L0,20L4,20L4.176,19.995C5.693,19.907 6.907,18.693 6.995,17.176L7,17L7,3L6.995,2.824C6.911,1.368 5.788,0.191 4.357,0.021L4.176,0.005L4,0L0,0L0.176,0.005C1.632,0.089 2.809,1.212 2.979,2.643L2.995,2.824L3,3L3,17Z"/>
+ </g>
+ </g>
+ </g>
+ </g>
+</svg>
diff --git a/asset/static/font/icinga-icons/src/ca-check-circle.svg b/asset/static/font/icinga-icons/src/ca-check-circle.svg
new file mode 100644
index 0000000..e112c3c
--- /dev/null
+++ b/asset/static/font/icinga-icons/src/ca-check-circle.svg
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg width="100%" height="100%" viewBox="0 0 16 16" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" xmlns:serif="http://www.serif.com/" style="fill-rule:evenodd;clip-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:2;">
+ <g transform="matrix(1,0,0,1,-216,-134)">
+ <g transform="matrix(0.25,0,0,0.25,216,134)">
+ <rect id="filter-circle-check" x="0" y="0" width="64" height="64" style="fill:none;"/>
+ <g id="filter-circle-check1" serif:id="filter-circle-check">
+ <g transform="matrix(3.06254,0,0,3.06254,-937.661,-403.905)">
+ <path d="M309.784,144.283C309.664,144.294 309.533,144.3 309.39,144.3C308.93,144.3 308.506,144.218 308.117,144.053C307.728,143.889 307.389,143.656 307.099,143.355C306.808,143.054 306.581,142.695 306.417,142.279C306.253,141.863 306.17,141.4 306.17,140.891C306.17,140.382 306.255,139.917 306.425,139.495C306.595,139.073 306.825,138.715 307.115,138.419C307.405,138.123 307.747,137.899 308.142,137.745C308.536,137.592 308.963,137.515 309.423,137.515C309.839,137.515 310.253,137.595 310.663,137.754C311.074,137.912 311.405,138.145 311.657,138.452L310.672,139.52C310.54,139.311 310.365,139.161 310.146,139.068C309.927,138.975 309.697,138.928 309.456,138.928C309.215,138.928 308.988,138.977 308.774,139.076C308.561,139.175 308.377,139.311 308.224,139.487C308.071,139.662 307.953,139.87 307.871,140.111C307.789,140.352 307.747,140.615 307.747,140.899C307.747,141.184 307.789,141.45 307.871,141.696C307.953,141.943 308.071,142.151 308.224,142.32C308.377,142.49 308.555,142.624 308.758,142.723C308.96,142.821 309.188,142.871 309.439,142.871C309.724,142.871 309.976,142.81 310.195,142.69C310.37,142.591 310.518,142.465 310.639,142.312L309.784,144.283Z" style="fill-rule:nonzero;"/>
+ </g>
+ <g transform="matrix(4,0,0,4,-1224.68,-536)">
+ <path d="M313.746,143.283L313.453,142.511L311.528,142.511L311.164,143.505L309.868,143.505L311.943,138.474L313.113,138.474L314.53,141.949C314.192,142.354 313.931,142.798 313.746,143.283ZM312.509,139.82L311.881,141.543L313.126,141.543L312.509,139.82Z" style="fill-rule:nonzero;"/>
+ </g>
+ <g transform="matrix(4,0,0,4,-1224.68,-536)">
+ <path d="M322.17,145.016C322.136,146.149 321.741,147.094 320.985,147.852C320.229,148.611 319.287,148.998 318.157,149.016C317.028,148.998 316.09,148.611 315.343,147.852C314.596,147.094 314.205,146.149 314.17,145.016C314.205,143.883 314.596,142.937 315.343,142.179C316.09,141.421 317.028,141.033 318.157,141.016C319.287,141.033 320.229,141.421 320.985,142.179C321.741,142.937 322.136,143.883 322.17,145.016ZM321.266,143.082C321.258,143.071 321.249,143.061 321.239,143.052C320.885,142.697 320.309,142.697 319.955,143.052L318.698,144.307L318.182,145.504C318.182,145.504 317.782,144.477 317.782,144.477L317.324,144.019C316.97,143.665 316.394,143.665 316.04,144.019C315.685,144.374 315.685,144.949 316.04,145.304L317.513,146.777C317.688,146.952 317.917,147.04 318.146,147.042C318.153,147.042 318.16,147.042 318.166,147.042C318.395,147.039 318.623,146.951 318.797,146.777L321.238,144.336C321.582,143.992 321.592,143.438 321.266,143.082Z" style="fill-rule:nonzero;"/>
+ </g>
+ </g>
+ </g>
+ </g>
+</svg>
diff --git a/asset/static/font/icinga-icons/src/certificate.svg b/asset/static/font/icinga-icons/src/certificate.svg
new file mode 100644
index 0000000..12eadc8
--- /dev/null
+++ b/asset/static/font/icinga-icons/src/certificate.svg
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg width="100%" height="100%" viewBox="0 0 16 16" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" xmlns:serif="http://www.serif.com/" style="fill-rule:evenodd;clip-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:2;">
+ <g transform="matrix(1,0,0,1,-242,-134)">
+ <g transform="matrix(0.25,0,0,0.25,242,134)">
+ <rect id="certificate" x="0" y="0" width="64" height="64" style="fill:none;"/>
+ <g id="certificate1" serif:id="certificate">
+ <g transform="matrix(4,0,0,4,-1329.92,-536)">
+ <path d="M333.48,134L347.48,134C348.032,134 348.48,134.448 348.48,135L348.48,145C348.48,145.552 348.032,146 347.48,146L342,146L342,145L347.48,145L347.48,135L333.48,135L333.48,145L334,145L334,146L333.48,146C332.928,146 332.48,145.552 332.48,145L332.48,135C332.48,134.448 332.928,134 333.48,134Z"/>
+ </g>
+ <g transform="matrix(4.32185,0,0,4.32185,-1439.2,-580.832)">
+ <circle cx="338.097" cy="141.352" r="3.239"/>
+ </g>
+ <g transform="matrix(4,0,0,4,-1329.92,-536)">
+ <path d="M340.472,145.264L341.472,150L337.967,148L334.48,150L335.48,145.258C336.195,145.737 337.055,146.017 337.98,146.017C338.901,146.017 339.758,145.74 340.472,145.264Z" style="fill-rule:nonzero;"/>
+ </g>
+ <g transform="matrix(4,0,0,4,-1329.92,-536)">
+ <path d="M346.48,137C346.48,136.735 346.374,136.48 346.187,136.293C345.999,136.105 345.745,136 345.48,136C344.37,136 342.589,136 341.48,136C341.214,136 340.96,136.105 340.773,136.293C340.585,136.48 340.48,136.735 340.48,137C340.48,137.265 340.585,137.52 340.773,137.707C340.96,137.895 341.214,138 341.48,138C342.589,138 344.37,138 345.48,138C345.745,138 345.999,137.895 346.187,137.707C346.374,137.52 346.48,137.265 346.48,137Z"/>
+ </g>
+ <g transform="matrix(4,0,0,4,-1329.92,-524)">
+ <path d="M346.48,137C346.48,136.735 346.374,136.48 346.187,136.293C345.999,136.105 345.745,136 345.48,136C344.37,136 344.589,136 343.48,136C343.214,136 342.96,136.105 342.773,136.293C342.585,136.48 342.48,136.735 342.48,137C342.48,137.265 342.585,137.52 342.773,137.707C342.96,137.895 343.214,138 343.48,138C344.589,138 344.37,138 345.48,138C345.745,138 345.999,137.895 346.187,137.707C346.374,137.52 346.48,137.265 346.48,137Z"/>
+ </g>
+ </g>
+ </g>
+ </g>
+</svg>
diff --git a/asset/static/font/icinga-icons/src/filter-check-circle.svg b/asset/static/font/icinga-icons/src/filter-check-circle.svg
new file mode 100644
index 0000000..d9fdd5f
--- /dev/null
+++ b/asset/static/font/icinga-icons/src/filter-check-circle.svg
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg width="100%" height="100%" viewBox="0 0 16 16" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" xmlns:serif="http://www.serif.com/" style="fill-rule:evenodd;clip-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:2;">
+ <g transform="matrix(1,0,0,1,-162,-134)">
+ <g transform="matrix(0.25,0,0,0.25,162,134)">
+ <rect id="filter-circle-check" x="0" y="0" width="64" height="64" style="fill:none;"/>
+ <g id="filter-circle-check1" serif:id="filter-circle-check">
+ <g transform="matrix(4,0,0,4,-1008,-536)">
+ <path d="M252.113,135.414C252.297,135.025 252.686,134.778 253.116,134.778L265.116,134.778C265.547,134.778 265.936,135.025 266.119,135.414C266.302,135.803 266.247,136.261 265.975,136.594L263.016,140.211C260.788,140.669 259.116,142.639 259.116,145C259.116,145.761 259.291,146.483 259.602,147.125C259.558,147.103 259.513,147.075 259.472,147.044L257.694,145.711C257.469,145.544 257.338,145.281 257.338,145L257.338,142.803L252.255,136.592C251.986,136.261 251.927,135.8 252.113,135.414Z" style="fill-rule:nonzero;"/>
+ </g>
+ <g transform="matrix(4,0,0,4,-1224.68,-536)">
+ <path d="M322.17,145.016C322.136,146.149 321.741,147.094 320.985,147.852C320.229,148.611 319.287,148.998 318.157,149.016C317.028,148.998 316.09,148.611 315.343,147.852C314.596,147.094 314.205,146.149 314.17,145.016C314.205,143.883 314.596,142.937 315.343,142.179C316.09,141.421 317.028,141.033 318.157,141.016C319.287,141.033 320.229,141.421 320.985,142.179C321.741,142.937 322.136,143.883 322.17,145.016ZM321.266,143.082C321.258,143.071 321.249,143.061 321.239,143.052C320.885,142.697 320.309,142.697 319.955,143.052L318.698,144.307L318.182,145.504C318.182,145.504 317.782,144.477 317.782,144.477L317.324,144.019C316.97,143.665 316.394,143.665 316.04,144.019C315.685,144.374 315.685,144.949 316.04,145.304L317.513,146.777C317.688,146.952 317.917,147.04 318.146,147.042C318.153,147.042 318.16,147.042 318.166,147.042C318.395,147.039 318.623,146.951 318.797,146.777L321.238,144.336C321.582,143.992 321.592,143.438 321.266,143.082Z" style="fill-rule:nonzero;"/>
+ </g>
+ </g>
+ </g>
+ </g>
+</svg>
diff --git a/asset/static/font/icinga-icons/src/icinga.svg b/asset/static/font/icinga-icons/src/icinga.svg
new file mode 100644
index 0000000..4f1b13b
--- /dev/null
+++ b/asset/static/font/icinga-icons/src/icinga.svg
@@ -0,0 +1,49 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg width="100%" height="100%" viewBox="0 0 16 16" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" xmlns:serif="http://www.serif.com/" style="fill-rule:evenodd;clip-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:2;">
+ <g transform="matrix(1,0,0,1,-140,-134)">
+ <g transform="matrix(0.25,0,0,0.25,140,134)">
+ <rect id="icinga" x="0" y="0" width="64" height="64" style="fill:none;"/>
+ <clipPath id="_clip1">
+ <rect id="icinga1" serif:id="icinga" x="0" y="0" width="64" height="64"/>
+ </clipPath>
+ <g clip-path="url(#_clip1)">
+ <g transform="matrix(0.028493,0,0,0.028493,1.07196,0)">
+ <g transform="matrix(4,0,0,4,0,0)">
+ <path d="M305.637,44.644L330.458,49.188L248.679,280.771L223.859,276.227L305.637,44.644Z"/>
+ </g>
+ <g transform="matrix(4,0,0,4,0,0)">
+ <path d="M481.944,202.533L481.944,218.623L274.047,288.816L268.684,272.726L481.944,202.533Z"/>
+ </g>
+ <g transform="matrix(4,0,0,4,0,0)">
+ <path d="M350.332,421.156L350.332,445.168L259.901,322.169L282.83,309.243L350.332,421.156Z"/>
+ </g>
+ <g transform="matrix(4,0,0,4,0,0)">
+ <path d="M103.323,463.704L88.445,448.802L201.173,315.867L236.269,323.319L103.323,463.704Z"/>
+ </g>
+ <g transform="matrix(4,0,0,4,0,0)">
+ <path d="M95.884,175.482L74.608,146.769L244.031,270.497L228.507,291.754L95.884,175.482Z"/>
+ </g>
+ <g id="Orb-1" serif:id="Orb 1" transform="matrix(6.01058,0,0,6.08489,-684.883,1.9677)">
+ <path d="M318.047,0C345.44,0 367.68,21.968 367.68,49.026C367.68,76.084 345.44,98.052 318.047,98.052C290.655,98.052 268.415,76.084 268.415,49.026C268.415,21.968 290.655,0 318.047,0Z"/>
+ </g>
+ <g id="Orb-2" serif:id="Orb 2" transform="matrix(6.2603,0,0,6.3377,-1189.12,-493.419)">
+ <path d="M503.488,172.306C525.147,172.306 542.731,189.676 542.731,211.07C542.731,232.465 525.147,249.834 503.488,249.834C481.829,249.834 464.245,232.465 464.245,211.07C464.245,189.676 481.829,172.306 503.488,172.306Z"/>
+ </g>
+ <g id="Orb-3" serif:id="Orb 3" transform="matrix(9.01966,0,0,9.13117,-1337.13,-2229.08)">
+ <path d="M303.61,417.078C314.348,417.078 323.066,425.69 323.066,436.296C323.066,446.903 314.348,455.514 303.61,455.514C292.873,455.514 284.155,446.903 284.155,436.296C284.155,425.69 292.873,417.078 303.61,417.078Z"/>
+ </g>
+ <g id="Orb-4" serif:id="Orb 4" transform="matrix(4.93841,0,0,4.99946,-37.6219,-561.24)">
+ <path d="M63.961,435.181C99.263,435.181 127.923,463.492 127.923,498.362C127.923,533.232 99.263,561.542 63.961,561.542C28.66,561.542 0,533.232 0,498.362C0,463.492 28.66,435.181 63.961,435.181Z"/>
+ </g>
+ <g id="Orb-5" serif:id="Orb 5" transform="matrix(6.84016,0,0,6.92473,-189.854,-460.346)">
+ <path d="M66.846,126.988C83.837,126.988 97.632,140.614 97.632,157.398C97.632,174.181 83.837,187.807 66.846,187.807C49.855,187.807 36.061,174.181 36.061,157.398C36.061,140.614 49.855,126.988 66.846,126.988Z"/>
+ </g>
+ <g id="Orb-Center" serif:id="Orb Center" transform="matrix(4.34182,0,0,4.3955,19.5912,-110.981)">
+ <path d="M213.156,184.794C266.692,184.794 310.156,227.728 310.156,280.61C310.156,333.492 266.692,376.425 213.156,376.425C159.62,376.425 116.156,333.492 116.156,280.61C116.156,227.728 159.62,184.794 213.156,184.794Z"/>
+ </g>
+ </g>
+ </g>
+ </g>
+ </g>
+</svg>
diff --git a/asset/static/font/icinga-icons/src/list-view-default.svg b/asset/static/font/icinga-icons/src/list-view-default.svg
new file mode 100644
index 0000000..ad4c9d0
--- /dev/null
+++ b/asset/static/font/icinga-icons/src/list-view-default.svg
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg width="100%" height="100%" viewBox="0 0 16 16" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" xmlns:serif="http://www.serif.com/" style="fill-rule:evenodd;clip-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:2;">
+ <g transform="matrix(1,0,0,1,-40,-134)">
+ <g transform="matrix(0.25,0,0,0.25,40,134)">
+ <rect id="list-view-default" x="0" y="0" width="64" height="64" style="fill:none;"/>
+ <clipPath id="_clip1">
+ <rect id="list-view-default1" serif:id="list-view-default" x="0" y="0" width="64" height="64"/>
+ </clipPath>
+ <g clip-path="url(#_clip1)">
+ <g id="_16-list-view-default" serif:id="16/list-view-default" transform="matrix(1.02005,0,0,1.02005,-2.30518,-1.16359)">
+ <g transform="matrix(3.92139,0,0,3.92139,2.25988,-492.954)">
+ <rect x="0" y="126" width="16" height="16" style="fill:none;"/>
+ </g>
+ <g transform="matrix(5.76344,0,0,5.76344,-25.17,-51.3628)">
+ <circle cx="6.46" cy="11.151" r="1.021"/>
+ </g>
+ <g transform="matrix(0.802102,0,0,0.961081,-54.422,-3.54908)">
+ <rect x="100" y="11" width="44" height="12.241"/>
+ </g>
+ <g transform="matrix(0.802102,0,0,0.961081,-54.422,16.0579)">
+ <rect x="100" y="11" width="44" height="12.241"/>
+ </g>
+ <g transform="matrix(0.802102,0,0,0.961081,-54.422,35.6648)">
+ <rect x="100" y="11" width="44" height="12.241"/>
+ </g>
+ <g transform="matrix(5.76344,0,0,5.76344,-25.17,-31.7558)">
+ <circle cx="6.46" cy="11.151" r="1.021"/>
+ </g>
+ <g transform="matrix(5.76344,0,0,5.76344,-25.17,-12.1489)">
+ <circle cx="6.46" cy="11.151" r="1.021"/>
+ </g>
+ </g>
+ </g>
+ </g>
+ </g>
+</svg>
diff --git a/asset/static/font/icinga-icons/src/list-view-detailed.svg b/asset/static/font/icinga-icons/src/list-view-detailed.svg
new file mode 100644
index 0000000..2ba71ad
--- /dev/null
+++ b/asset/static/font/icinga-icons/src/list-view-detailed.svg
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg width="100%" height="100%" viewBox="0 0 16 16" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" xmlns:serif="http://www.serif.com/" style="fill-rule:evenodd;clip-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:2;">
+ <g transform="matrix(1,0,0,1,-20,-134)">
+ <g transform="matrix(0.25,0,0,0.25,20,134)">
+ <rect id="list-view-detailed" x="0" y="0" width="64" height="64" style="fill:none;"/>
+ <g id="list-view-detailed1" serif:id="list-view-detailed">
+ <g id="_16-list-view-detailed" serif:id="16/list-view-detailed">
+ <g transform="matrix(4,0,0,4,0,-504)">
+ <rect x="0" y="126" width="16" height="16" style="fill:none;"/>
+ </g>
+ <g transform="matrix(1.00393,0,0,1.07437,1.27514,2.18191)">
+ <rect x="18.652" y="5.434" width="39.843" height="11.132"/>
+ </g>
+ <g transform="matrix(1.00393,0,0,1.03883,1.27514,14.5728)">
+ <rect x="18.652" y="9.075" width="39.843" height="3.85"/>
+ </g>
+ <g transform="matrix(5.87898,0,0,5.87898,-27.9798,-51.5763)">
+ <circle cx="6.46" cy="11.151" r="1.021"/>
+ </g>
+ <g transform="matrix(5.87898,0,0,5.87898,-27.9798,-23.556)">
+ <circle cx="6.46" cy="11.151" r="1.021"/>
+ </g>
+ <g transform="matrix(1.00393,0,0,1.078,1.27514,30.1419)">
+ <rect x="18.652" y="5.434" width="39.843" height="11.132"/>
+ </g>
+ <g transform="matrix(1.00393,0,0,1.03533,1.27513,42.6113)">
+ <rect x="18.652" y="9.068" width="39.843" height="3.863"/>
+ </g>
+ </g>
+ </g>
+ </g>
+ </g>
+</svg>
diff --git a/asset/static/font/icinga-icons/src/list-view-minimal.svg b/asset/static/font/icinga-icons/src/list-view-minimal.svg
new file mode 100644
index 0000000..40de605
--- /dev/null
+++ b/asset/static/font/icinga-icons/src/list-view-minimal.svg
@@ -0,0 +1,46 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg width="100%" height="100%" viewBox="0 0 16 16" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" xmlns:serif="http://www.serif.com/" style="fill-rule:evenodd;clip-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:2;">
+ <g transform="matrix(1,0,0,1,0,-134)">
+ <g transform="matrix(0.25,0,0,0.25,0,134)">
+ <rect id="list-view-minimal" x="0" y="0" width="64" height="64" style="fill:none;"/>
+ <g id="list-view-minimal1" serif:id="list-view-minimal">
+ <g id="_16-list-view-minimal" serif:id="16/list-view-minimal">
+ <g transform="matrix(4,0,0,4,0,-504)">
+ <rect x="0" y="126" width="16" height="16" style="fill:none;"/>
+ </g>
+ <g transform="matrix(3.91932,0,0,3.91932,-17.3199,-35.704)">
+ <circle cx="6.46" cy="11.151" r="1.021"/>
+ </g>
+ <g transform="matrix(3.91932,0,0,3.91932,-17.3199,-23.6838)">
+ <circle cx="6.46" cy="11.151" r="1.021"/>
+ </g>
+ <g transform="matrix(3.91932,0,0,3.91932,-17.3199,-11.6838)">
+ <circle cx="6.46" cy="11.151" r="1.021"/>
+ </g>
+ <g transform="matrix(1.02326,0,0,0.6611,-1.44408,0.727897)">
+ <rect x="20.957" y="7.975" width="39.091" height="6.051"/>
+ </g>
+ <g transform="matrix(1.02326,0,0,0.6611,-1.44408,24.7481)">
+ <rect x="20.957" y="7.975" width="39.091" height="6.051"/>
+ </g>
+ <g transform="matrix(1.02326,0,0,0.6611,-1.44408,12.7481)">
+ <rect x="20.957" y="7.975" width="39.091" height="6.051"/>
+ </g>
+ <g transform="matrix(1.02326,0,0,0.6611,-1.44408,36.7481)">
+ <rect x="20.957" y="7.975" width="39.091" height="6.051"/>
+ </g>
+ <g transform="matrix(1.02326,0,0,0.6611,-1.44408,48.7481)">
+ <rect x="20.957" y="7.975" width="39.091" height="6.051"/>
+ </g>
+ <g transform="matrix(3.91932,0,0,3.91932,-17.3199,0.336422)">
+ <circle cx="6.46" cy="11.151" r="1.021"/>
+ </g>
+ <g transform="matrix(3.91932,0,0,3.91932,-17.3199,12.3162)">
+ <circle cx="6.46" cy="11.151" r="1.021"/>
+ </g>
+ </g>
+ </g>
+ </g>
+ </g>
+</svg>
diff --git a/asset/static/font/icinga-icons/src/refresh-cert.svg b/asset/static/font/icinga-icons/src/refresh-cert.svg
new file mode 100644
index 0000000..68be9eb
--- /dev/null
+++ b/asset/static/font/icinga-icons/src/refresh-cert.svg
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg width="100%" height="100%" viewBox="0 0 16 16" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" xmlns:serif="http://www.serif.com/" style="fill-rule:evenodd;clip-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:2;">
+ <g transform="matrix(1,0,0,1,-268,-134)">
+ <g transform="matrix(0.25,0,0,0.25,268,134)">
+ <rect id="refresh-cert" x="0" y="0" width="64" height="64" style="fill:none;"/>
+ <clipPath id="_clip1">
+ <rect id="refresh-cert1" serif:id="refresh-cert" x="0" y="0" width="64" height="64"/>
+ </clipPath>
+ <g clip-path="url(#_clip1)">
+ <g transform="matrix(4,0,0,4,-1435.16,-536)">
+ <rect x="363.789" y="141" width="6" height="4.017" style="fill-rule:nonzero;"/>
+ </g>
+ <g transform="matrix(4,0,0,4,-1435.16,-536)">
+ <path d="M364.789,140.5L364.789,139C364.789,138.448 365.237,138 365.789,138L367.789,138C368.341,138 368.789,138.448 368.789,139L368.789,140.5L364.789,140.5ZM367.789,139L365.789,139L365.789,140.5L367.789,140.5L367.789,139Z"/>
+ </g>
+ <g transform="matrix(4,0,0,4,-1432,-536)">
+ <path d="M361.007,145.326C362.083,146.938 363.919,148 366,148C368.212,148 370.146,146.8 371.186,145.017L373.411,145.017C372.219,147.939 369.348,150 366,150C363.179,150 360.697,148.537 359.272,146.328L357.998,147.064L358.031,142L362.429,144.506L361.007,145.326ZM371.023,138.72C369.952,137.082 368.101,136 366,136C363.39,136 361.166,137.671 360.342,140L358.252,140C359.141,136.551 362.275,134 366,134C368.841,134 371.338,135.484 372.757,137.718L374.002,137L373.969,142.064L369.571,139.558L371.023,138.72Z"/>
+ </g>
+ </g>
+ </g>
+ </g>
+</svg>
diff --git a/asset/static/font/icinga-icons/src/th-list.svg b/asset/static/font/icinga-icons/src/th-list.svg
new file mode 100644
index 0000000..20d3746
--- /dev/null
+++ b/asset/static/font/icinga-icons/src/th-list.svg
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg width="100%" height="100%" viewBox="0 0 16 16" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" xmlns:serif="http://www.serif.com/" style="fill-rule:evenodd;clip-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:2;">
+ <g transform="matrix(1,0,0,1,-80,-134)">
+ <g transform="matrix(0.25,0,0,0.25,80,134)">
+ <rect id="th-list" x="0" y="0" width="64" height="64" style="fill:none;"/>
+ <clipPath id="_clip1">
+ <rect id="th-list1" serif:id="th-list" x="0" y="0" width="64" height="64"/>
+ </clipPath>
+ <g clip-path="url(#_clip1)">
+ <g id="th-list2" serif:id="th-list">
+ <g transform="matrix(5.33333,0,0,5.33333,-563.593,-880)">
+ <rect x="105.674" y="165" width="12" height="12" style="fill:none;"/>
+ </g>
+ <g transform="matrix(59.7652,0,0,59.7652,4.03068,52.9178)">
+ <path d="M0,-0.062C0,-0.042 0.007,-0.025 0.021,-0.011C0.035,0.003 0.052,0.01 0.072,0.01L0.104,0.01C0.124,0.01 0.141,0.003 0.155,-0.011C0.169,-0.025 0.176,-0.042 0.176,-0.062C0.176,-0.082 0.169,-0.099 0.155,-0.113C0.141,-0.127 0.124,-0.134 0.104,-0.134L0.072,-0.134C0.052,-0.134 0.035,-0.127 0.021,-0.113C0.007,-0.099 0,-0.082 0,-0.062ZM0,-0.35C0,-0.33 0.007,-0.313 0.021,-0.299C0.035,-0.285 0.052,-0.278 0.072,-0.278L0.104,-0.278C0.124,-0.278 0.141,-0.285 0.155,-0.299C0.169,-0.313 0.176,-0.33 0.176,-0.35C0.176,-0.37 0.169,-0.387 0.155,-0.401C0.141,-0.415 0.124,-0.422 0.104,-0.422L0.072,-0.422C0.052,-0.422 0.035,-0.415 0.021,-0.401C0.007,-0.387 0,-0.37 0,-0.35ZM0,-0.638C0,-0.618 0.007,-0.601 0.021,-0.587C0.035,-0.573 0.052,-0.566 0.072,-0.566L0.104,-0.566C0.124,-0.566 0.141,-0.573 0.155,-0.587C0.169,-0.601 0.176,-0.618 0.176,-0.638C0.176,-0.658 0.169,-0.675 0.155,-0.689C0.141,-0.703 0.124,-0.71 0.104,-0.71L0.072,-0.71C0.052,-0.71 0.035,-0.703 0.021,-0.689C0.007,-0.675 0,-0.658 0,-0.638ZM0.234,-0.062C0.234,-0.042 0.241,-0.025 0.255,-0.011C0.269,0.003 0.286,0.01 0.306,0.01L0.865,0.01C0.885,0.01 0.902,0.003 0.916,-0.011C0.93,-0.025 0.937,-0.042 0.937,-0.062C0.937,-0.082 0.93,-0.099 0.916,-0.113C0.902,-0.127 0.885,-0.134 0.865,-0.134L0.306,-0.134C0.286,-0.134 0.269,-0.127 0.255,-0.113C0.241,-0.099 0.234,-0.082 0.234,-0.062ZM0.234,-0.35C0.234,-0.33 0.241,-0.313 0.255,-0.299C0.269,-0.285 0.286,-0.278 0.306,-0.278L0.865,-0.278C0.885,-0.278 0.902,-0.285 0.916,-0.299C0.93,-0.313 0.937,-0.33 0.937,-0.35C0.937,-0.37 0.93,-0.387 0.916,-0.401C0.902,-0.415 0.885,-0.422 0.865,-0.422L0.306,-0.422C0.286,-0.422 0.269,-0.415 0.255,-0.401C0.241,-0.387 0.234,-0.37 0.234,-0.35ZM0.234,-0.638C0.234,-0.618 0.241,-0.601 0.255,-0.587C0.269,-0.573 0.286,-0.566 0.306,-0.566L0.865,-0.566C0.885,-0.566 0.902,-0.573 0.916,-0.587C0.93,-0.601 0.937,-0.618 0.937,-0.638C0.937,-0.658 0.93,-0.675 0.916,-0.689C0.902,-0.703 0.885,-0.71 0.865,-0.71L0.306,-0.71C0.286,-0.71 0.269,-0.703 0.255,-0.689C0.241,-0.675 0.234,-0.658 0.234,-0.638Z" style="fill-rule:nonzero;"/>
+ </g>
+ </g>
+ </g>
+ </g>
+ </g>
+</svg>
diff --git a/asset/static/font/icinga-icons/src/th-thumb-empty.svg b/asset/static/font/icinga-icons/src/th-thumb-empty.svg
new file mode 100644
index 0000000..4bc5619
--- /dev/null
+++ b/asset/static/font/icinga-icons/src/th-thumb-empty.svg
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg width="100%" height="100%" viewBox="0 0 16 16" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" xmlns:serif="http://www.serif.com/" style="fill-rule:evenodd;clip-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:2;">
+ <g transform="matrix(1,0,0,1,-60,-134)">
+ <g transform="matrix(0.25,0,0,0.25,60,134)">
+ <rect id="grid" x="0" y="0" width="64" height="64" style="fill:none;"/>
+ <g id="grid1" serif:id="grid">
+ <g>
+ <g transform="matrix(5.33333,0,0,5.33333,-320,-880)">
+ <g>
+ <rect x="60" y="165" width="12" height="12" style="fill:none;"/>
+ </g>
+ </g>
+ <g transform="matrix(59.7577,0,0,59.9572,4.01886,52.985)">
+ <path d="M0,0.066L0,-0.22C0,-0.235 0.005,-0.247 0.015,-0.257C0.025,-0.267 0.037,-0.272 0.052,-0.273L0.338,-0.273C0.352,-0.273 0.364,-0.268 0.375,-0.257C0.386,-0.246 0.391,-0.234 0.39,-0.22L0.39,0.066C0.39,0.08 0.385,0.092 0.375,0.102C0.365,0.112 0.353,0.117 0.338,0.117L0.052,0.117C0.037,0.117 0.025,0.112 0.015,0.102C0.005,0.092 0,0.08 0,0.066ZM0,-0.48L0,-0.766C0,-0.78 0.005,-0.792 0.015,-0.802C0.025,-0.812 0.037,-0.817 0.052,-0.817L0.338,-0.817C0.352,-0.817 0.364,-0.812 0.375,-0.802C0.386,-0.792 0.391,-0.78 0.39,-0.766L0.39,-0.48C0.39,-0.465 0.385,-0.453 0.375,-0.443C0.365,-0.433 0.353,-0.428 0.338,-0.427L0.052,-0.427C0.038,-0.427 0.026,-0.432 0.015,-0.443C0.004,-0.454 -0.001,-0.466 0,-0.48ZM0.088,0.03L0.302,0.03L0.302,-0.184L0.088,-0.184L0.088,0.03ZM0.088,-0.516L0.302,-0.516L0.302,-0.729L0.088,-0.729L0.088,-0.516ZM0.547,0.066L0.547,-0.22C0.547,-0.235 0.552,-0.247 0.562,-0.257C0.572,-0.267 0.584,-0.272 0.599,-0.273L0.885,-0.273C0.899,-0.273 0.911,-0.268 0.922,-0.257C0.933,-0.246 0.938,-0.234 0.937,-0.22L0.937,0.066C0.937,0.08 0.932,0.092 0.922,0.102C0.912,0.112 0.9,0.117 0.885,0.117L0.599,0.117C0.585,0.117 0.573,0.112 0.562,0.102C0.551,0.092 0.546,0.08 0.547,0.066ZM0.547,-0.48L0.547,-0.766C0.547,-0.78 0.552,-0.792 0.562,-0.802C0.572,-0.812 0.584,-0.817 0.599,-0.817L0.885,-0.817C0.9,-0.817 0.912,-0.812 0.922,-0.802C0.932,-0.792 0.937,-0.78 0.937,-0.766L0.937,-0.48C0.937,-0.465 0.932,-0.453 0.922,-0.443C0.912,-0.433 0.9,-0.428 0.885,-0.427L0.599,-0.427C0.585,-0.427 0.573,-0.432 0.562,-0.443C0.551,-0.454 0.546,-0.466 0.547,-0.48ZM0.635,0.03L0.85,0.03L0.85,-0.184L0.635,-0.184L0.635,0.03ZM0.635,-0.516L0.85,-0.516L0.85,-0.729L0.635,-0.729L0.635,-0.516Z" style="fill-rule:nonzero;"/>
+ </g>
+ </g>
+ </g>
+ </g>
+ </g>
+</svg>
diff --git a/asset/static/font/icinga-icons/style.css b/asset/static/font/icinga-icons/style.css
new file mode 100644
index 0000000..dde73b4
--- /dev/null
+++ b/asset/static/font/icinga-icons/style.css
@@ -0,0 +1,62 @@
+@font-face {
+ font-family: 'Icinga-Icons';
+ src:
+ url('fonts/Icinga-Icons.ttf?xnw9vw') format('truetype'),
+ url('fonts/Icinga-Icons.woff?xnw9vw') format('woff'),
+ url('fonts/Icinga-Icons.svg?xnw9vw#Icinga-Icons') format('svg');
+ font-weight: normal;
+ font-style: normal;
+ font-display: block;
+}
+
+[class^="iicon-"], [class*=" iicon-"] {
+ /* use !important to prevent issues with browser extensions that change fonts */
+ font-family: 'Icinga-Icons' !important;
+ speak: never;
+ font-style: normal;
+ font-weight: normal;
+ font-variant: normal;
+ text-transform: none;
+ line-height: 1;
+
+ /* Better Font Rendering =========== */
+ -webkit-font-smoothing: antialiased;
+ -moz-osx-font-smoothing: grayscale;
+}
+
+.iicon-certificate:before {
+ content: "\e906";
+}
+.iicon-filter-check-circle:before {
+ content: "\e90b";
+}
+.iicon-ca-check-circle:before {
+ content: "\e908";
+}
+.iicon-refresh-cert:before {
+ content: "\e909";
+}
+.iicon-th-list:before {
+ content: "\e90a";
+}
+.iicon-icinga:before {
+ content: "\e907";
+}
+.iicon-list-view-minimal:before {
+ content: "\e900";
+}
+.iicon-list-view-detailed:before {
+ content: "\e901";
+}
+.iicon-list-view-default:before {
+ content: "\e902";
+}
+.iicon-grid:before {
+ content: "\e903";
+}
+.iicon-bracket-open:before {
+ content: "\e904";
+}
+.iicon-bracket-close:before {
+ content: "\e905";
+}
diff --git a/asset/static/img/select-icon-text-color.svg b/asset/static/img/select-icon-text-color.svg
new file mode 100644
index 0000000..b2dc857
--- /dev/null
+++ b/asset/static/img/select-icon-text-color.svg
@@ -0,0 +1 @@
+<svg height="32" viewBox="0 0 24 32" width="24" xmlns="http://www.w3.org/2000/svg"><path d="m5.20126707.78766623 4.45386238 4.20402191c.16721345.15783356.16291017.40979541-.00961164.56277256-.081158.0719638-.18974398.11220597-.3027668.11220597h-8.90772462c-.24025844 0-.43502639-.17818569-.43502639-.39798892 0-.10340014.04398717-.20274128.12264801-.27698961l4.45386234-4.20402191c.16721345-.15783357.44262326-.16177048.61514507-.00879333.00325382.00288518.00645805.00581661.00961165.00879333z" fill="#282E39" transform="matrix(1 0 0 -1 7 20.666667)"/></svg>
diff --git a/asset/static/img/select-icon.svg b/asset/static/img/select-icon.svg
new file mode 100644
index 0000000..cc8a011
--- /dev/null
+++ b/asset/static/img/select-icon.svg
@@ -0,0 +1 @@
+<svg height="32" viewBox="0 0 24 32" width="24" xmlns="http://www.w3.org/2000/svg"><path d="m5.20126707.78766623 4.45386238 4.20402191c.16721345.15783356.16291017.40979541-.00961164.56277256-.081158.0719638-.18974398.11220597-.3027668.11220597h-8.90772462c-.24025844 0-.43502639-.17818569-.43502639-.39798892 0-.10340014.04398717-.20274128.12264801-.27698961l4.45386234-4.20402191c.16721345-.15783357.44262326-.16177048.61514507-.00879333.00325382.00288518.00645805.00581661.00961165.00879333z" fill="#00c3ed" transform="matrix(1 0 0 -1 7 20.666667)"/></svg> \ No newline at end of file