bootstrap-italia 2.12.1 → 2.13.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.EN.md +1 -1
- package/README.md +1 -1
- package/dist/bootstrap-italia.esm.js +1 -1
- package/dist/css/bootstrap-italia.min.css +9 -1
- package/dist/css/bootstrap-italia.min.css.map +1 -1
- package/dist/js/bootstrap-italia.bundle.min.js +19 -23
- package/dist/js/bootstrap-italia.min.js +18 -2
- package/dist/plugins/accept-overlay.js +19 -9
- package/dist/plugins/accept-overlay.js.map +1 -1
- package/dist/plugins/accordion.js +19 -24
- package/dist/plugins/accordion.js.map +1 -1
- package/dist/plugins/alert.js +67 -2
- package/dist/plugins/alert.js.map +1 -1
- package/dist/plugins/{backToTop.js → back-to-top.js} +14 -5
- package/dist/plugins/back-to-top.js.map +1 -0
- package/dist/plugins/base-component.js +91 -0
- package/dist/plugins/base-component.js.map +1 -0
- package/dist/plugins/button.js +58 -2
- package/dist/plugins/button.js.map +1 -1
- package/dist/plugins/carousel-bi.js +19 -9
- package/dist/plugins/carousel-bi.js.map +1 -1
- package/dist/plugins/carousel.js +445 -2
- package/dist/plugins/carousel.js.map +1 -1
- package/dist/plugins/collapse.js +273 -2
- package/dist/plugins/collapse.js.map +1 -1
- package/dist/plugins/cookiebar.js +39 -52
- package/dist/plugins/cookiebar.js.map +1 -1
- package/dist/plugins/dimmer.js +19 -8
- package/dist/plugins/dimmer.js.map +1 -1
- package/dist/plugins/dom/data.js +61 -0
- package/dist/plugins/dom/data.js.map +1 -0
- package/dist/plugins/dom/event-handler.js +296 -0
- package/dist/plugins/dom/event-handler.js.map +1 -0
- package/dist/plugins/dom/manipulator.js +76 -0
- package/dist/plugins/dom/manipulator.js.map +1 -0
- package/dist/plugins/dom/selector-engine.js +82 -0
- package/dist/plugins/dom/selector-engine.js.map +1 -0
- package/dist/plugins/dropdown.js +433 -2
- package/dist/plugins/dropdown.js.map +1 -1
- package/dist/plugins/fonts-loader.js +9 -1
- package/dist/plugins/fonts-loader.js.map +1 -1
- package/dist/plugins/form-validate.js +22 -8
- package/dist/plugins/form-validate.js.map +1 -1
- package/dist/plugins/forward.js +21 -18
- package/dist/plugins/forward.js.map +1 -1
- package/dist/plugins/header-sticky.js +11 -2
- package/dist/plugins/header-sticky.js.map +1 -1
- package/dist/plugins/history-back.js +17 -17
- package/dist/plugins/history-back.js.map +1 -1
- package/dist/plugins/init.js +9 -0
- package/dist/plugins/init.js.map +1 -1
- package/dist/plugins/input-label.js +14 -3
- package/dist/plugins/input-label.js.map +1 -1
- package/dist/plugins/input-number.js +13 -4
- package/dist/plugins/input-number.js.map +1 -1
- package/dist/plugins/input-password.js +48 -37
- package/dist/plugins/input-password.js.map +1 -1
- package/dist/plugins/input-search-autocomplete.js +9 -11
- package/dist/plugins/input-search-autocomplete.js.map +1 -1
- package/dist/plugins/input.js +12 -3
- package/dist/plugins/input.js.map +1 -1
- package/dist/plugins/list.js +23 -12
- package/dist/plugins/list.js.map +1 -1
- package/dist/plugins/masonry.js +29 -29
- package/dist/plugins/masonry.js.map +1 -1
- package/dist/plugins/modal.js +358 -2
- package/dist/plugins/modal.js.map +1 -1
- package/dist/plugins/navbar-collapsible.js +55 -45
- package/dist/plugins/navbar-collapsible.js.map +1 -1
- package/dist/plugins/navscroll.js +16 -23
- package/dist/plugins/navscroll.js.map +1 -1
- package/dist/plugins/notification.js +34 -23
- package/dist/plugins/notification.js.map +1 -1
- package/dist/plugins/offcanvas.js +259 -2
- package/dist/plugins/offcanvas.js.map +1 -1
- package/dist/plugins/popover.js +76 -2
- package/dist/plugins/popover.js.map +1 -1
- package/dist/plugins/progress-donut.js +19 -12
- package/dist/plugins/progress-donut.js.map +1 -1
- package/dist/plugins/scrollspy.js +273 -2
- package/dist/plugins/scrollspy.js.map +1 -1
- package/dist/plugins/select-autocomplete.js +10 -1
- package/dist/plugins/select-autocomplete.js.map +1 -1
- package/dist/plugins/sticky.js +21 -18
- package/dist/plugins/sticky.js.map +1 -1
- package/dist/plugins/tab.js +244 -27
- package/dist/plugins/tab.js.map +1 -1
- package/dist/plugins/toast.js +203 -2
- package/dist/plugins/toast.js.map +1 -1
- package/dist/plugins/tooltip.js +602 -2
- package/dist/plugins/tooltip.js.map +1 -1
- package/dist/plugins/track-focus.js +8 -0
- package/dist/plugins/track-focus.js.map +1 -1
- package/dist/plugins/transfer.js +11 -16
- package/dist/plugins/transfer.js.map +1 -1
- package/dist/plugins/upload-dragdrop.js +13 -4
- package/dist/plugins/upload-dragdrop.js.map +1 -1
- package/dist/plugins/util/backdrop.js +155 -0
- package/dist/plugins/util/backdrop.js.map +1 -0
- package/dist/plugins/util/component-functions.js +38 -0
- package/dist/plugins/util/component-functions.js.map +1 -0
- package/dist/plugins/util/config.js +70 -0
- package/dist/plugins/util/config.js.map +1 -0
- package/dist/plugins/util/cookies.js +8 -0
- package/dist/plugins/util/cookies.js.map +1 -1
- package/dist/plugins/util/device.js +0 -3
- package/dist/plugins/util/device.js.map +1 -1
- package/dist/plugins/util/dom.js +8 -0
- package/dist/plugins/util/dom.js.map +1 -1
- package/dist/plugins/util/focustrap.js +121 -0
- package/dist/plugins/util/focustrap.js.map +1 -0
- package/dist/plugins/util/index.js +280 -0
- package/dist/plugins/util/index.js.map +1 -0
- package/dist/plugins/util/observer.js +8 -0
- package/dist/plugins/util/observer.js.map +1 -1
- package/dist/plugins/util/on-document-scroll.js +20 -9
- package/dist/plugins/util/on-document-scroll.js.map +1 -1
- package/dist/plugins/util/pageScroll.js +8 -0
- package/dist/plugins/util/pageScroll.js.map +1 -1
- package/dist/plugins/util/sanitizer.js +115 -0
- package/dist/plugins/util/sanitizer.js.map +1 -0
- package/dist/plugins/util/scrollbar.js +120 -0
- package/dist/plugins/util/scrollbar.js.map +1 -0
- package/dist/plugins/util/swipe.js +150 -0
- package/dist/plugins/util/swipe.js.map +1 -0
- package/dist/plugins/util/template-factory.js +166 -0
- package/dist/plugins/util/template-factory.js.map +1 -0
- package/dist/plugins/util/tween.js +10 -1
- package/dist/plugins/util/tween.js.map +1 -1
- package/dist/plugins/util/youtube-video.js +12 -21
- package/dist/plugins/util/youtube-video.js.map +1 -1
- package/dist/plugins/videoplayer.js +19 -8
- package/dist/plugins/videoplayer.js.map +1 -1
- package/dist/version.js +10 -3
- package/dist/version.js.map +1 -1
- package/package.json +6 -7
- package/src/js/bootstrap-italia.entry.js +8 -0
- package/src/js/bootstrap-italia.esm.js +9 -1
- package/src/js/icons.js +8 -0
- package/src/js/load-plugin.js +8 -0
- package/src/js/plugins/accept-overlay.js +18 -10
- package/src/js/plugins/accordion.js +16 -22
- package/src/js/plugins/alert.js +66 -2
- package/src/js/plugins/{backToTop.js → back-to-top.js} +12 -4
- package/src/js/plugins/base-component.js +89 -0
- package/src/js/plugins/button.js +57 -2
- package/src/js/plugins/carousel-bi.js +18 -9
- package/src/js/plugins/carousel.js +444 -2
- package/src/js/plugins/collapse.js +272 -2
- package/src/js/plugins/cookiebar.js +37 -60
- package/src/js/plugins/dimmer.js +18 -8
- package/src/js/plugins/dom/data.js +58 -0
- package/src/js/plugins/dom/event-handler.js +301 -0
- package/src/js/plugins/dom/manipulator.js +75 -0
- package/src/js/plugins/dom/selector-engine.js +80 -0
- package/src/js/plugins/dropdown.js +432 -2
- package/src/js/plugins/fonts-loader.js +9 -1
- package/src/js/plugins/form-validate.js +21 -8
- package/src/js/plugins/form.js +11 -3
- package/src/js/plugins/forward.js +18 -16
- package/src/js/plugins/header-sticky.js +10 -2
- package/src/js/plugins/history-back.js +14 -14
- package/src/js/plugins/init.js +8 -0
- package/src/js/plugins/input-label.js +13 -3
- package/src/js/plugins/input-number.js +12 -4
- package/src/js/plugins/input-password.js +46 -36
- package/src/js/plugins/input-search-autocomplete.js +9 -13
- package/src/js/plugins/input.js +11 -3
- package/src/js/plugins/list.js +22 -12
- package/src/js/plugins/masonry.js +26 -27
- package/src/js/plugins/modal.js +357 -2
- package/src/js/plugins/navbar-collapsible.js +55 -53
- package/src/js/plugins/navscroll.js +16 -23
- package/src/js/plugins/notification.js +33 -23
- package/src/js/plugins/offcanvas.js +258 -2
- package/src/js/plugins/popover.js +75 -2
- package/src/js/plugins/progress-donut.js +17 -13
- package/src/js/plugins/scrollspy.js +272 -2
- package/src/js/plugins/select-autocomplete.js +9 -1
- package/src/js/plugins/sticky.js +21 -23
- package/src/js/plugins/tab.js +243 -27
- package/src/js/plugins/toast.js +206 -2
- package/src/js/plugins/tooltip.js +601 -2
- package/src/js/plugins/track-focus.js +8 -0
- package/src/js/plugins/transfer.js +12 -24
- package/src/js/plugins/upload-dragdrop.js +12 -4
- package/src/js/plugins/util/backdrop.js +153 -0
- package/src/js/plugins/util/component-functions.js +36 -0
- package/src/js/plugins/util/config.js +68 -0
- package/src/js/plugins/util/cookies.js +8 -0
- package/src/js/plugins/util/device.js +0 -3
- package/src/js/plugins/util/dom.js +8 -0
- package/src/js/plugins/util/focustrap.js +119 -0
- package/src/js/plugins/util/index.js +317 -0
- package/src/js/plugins/util/observer.js +8 -0
- package/src/js/plugins/util/on-document-scroll.js +19 -9
- package/src/js/plugins/util/pageScroll.js +8 -0
- package/src/js/plugins/util/sanitizer.js +112 -0
- package/src/js/plugins/util/scrollbar.js +118 -0
- package/src/js/plugins/util/swipe.js +148 -0
- package/src/js/plugins/util/template-factory.js +164 -0
- package/src/js/plugins/util/tween.js +9 -1
- package/src/js/plugins/util/youtube-video.js +12 -21
- package/src/js/plugins/videoplayer.js +18 -8
- package/src/js/version.js +10 -3
- package/src/scss/base/_containers.scss +41 -0
- package/src/scss/base/_functions.scss +373 -0
- package/src/scss/base/_helpers.scss +10 -0
- package/src/scss/base/_maps.scss +54 -0
- package/src/scss/base/_mixins.scss +44 -0
- package/src/scss/base/_reboot.scss +590 -0
- package/src/scss/base/_root.scss +73 -0
- package/src/scss/base/_transitions.scss +27 -0
- package/src/scss/base/_utilities.scss +742 -0
- package/src/scss/base/_variables.scss +2123 -0
- package/src/scss/base/_version.scss +3 -0
- package/src/scss/base/helpers/_clearfix.scss +3 -0
- package/src/scss/base/helpers/_color-bg.scss +10 -0
- package/src/scss/base/helpers/_colored-links.scss +16 -0
- package/src/scss/base/helpers/_position.scss +36 -0
- package/src/scss/base/helpers/_ratio.scss +26 -0
- package/src/scss/base/helpers/_stacks.scss +15 -0
- package/src/scss/base/helpers/_stretched-link.scss +15 -0
- package/src/scss/base/helpers/_text-truncation.scss +7 -0
- package/src/scss/base/helpers/_visually-hidden.scss +8 -0
- package/src/scss/base/helpers/_vr.scss +8 -0
- package/src/scss/base/mixins/_alert.scss +15 -0
- package/src/scss/base/mixins/_backdrop.scss +18 -0
- package/src/scss/base/mixins/_banner.scss +11 -0
- package/src/scss/base/mixins/_border-radius.scss +77 -0
- package/src/scss/base/mixins/_box-shadow.scss +18 -0
- package/src/scss/base/mixins/_breakpoints.scss +127 -0
- package/src/scss/base/mixins/_buttons.scss +141 -0
- package/src/scss/base/mixins/_caret.scss +64 -0
- package/src/scss/base/mixins/_clearfix.scss +9 -0
- package/src/scss/base/mixins/_color-scheme.scss +7 -0
- package/src/scss/base/mixins/_container.scss +11 -0
- package/src/scss/base/mixins/_deprecate.scss +10 -0
- package/src/scss/base/mixins/_forms.scss +152 -0
- package/src/scss/base/mixins/_gradients.scss +47 -0
- package/src/scss/base/mixins/_grid.scss +151 -0
- package/src/scss/base/mixins/_image.scss +15 -0
- package/src/scss/base/mixins/_list-group.scss +24 -0
- package/src/scss/base/mixins/_lists.scss +7 -0
- package/src/scss/base/mixins/_pagination.scss +10 -0
- package/src/scss/base/mixins/_reset-text.scss +17 -0
- package/src/scss/base/mixins/_resize.scss +6 -0
- package/src/scss/base/mixins/_table-variants.scss +24 -0
- package/src/scss/base/mixins/_text-truncate.scss +8 -0
- package/src/scss/base/mixins/_transition.scss +26 -0
- package/src/scss/base/mixins/_utilities.scss +96 -0
- package/src/scss/base/mixins/_visually-hidden.scss +29 -0
- package/src/scss/base/utilities/_api.scss +45 -0
- package/src/scss/base/vendor/_rfs.scss +337 -0
- package/src/scss/bootstrap-italia.scss +137 -156
- package/src/scss/components/_accordion.scss +297 -0
- package/src/scss/components/_badge.scss +60 -0
- package/src/scss/components/_breadcrumb.scss +95 -0
- package/src/scss/components/_button-group.scss +143 -0
- package/src/scss/components/_buttons.scss +467 -0
- package/src/scss/{custom → components}/_card.scss +228 -0
- package/src/scss/{custom → components}/_carousel.scss +225 -3
- package/src/scss/components/_dropdown.scss +480 -0
- package/src/scss/{custom → components}/_grid.scss +33 -0
- package/src/scss/{custom → components}/_gridlist.scss +7 -0
- package/src/scss/{custom → components}/_hero.scss +23 -57
- package/src/scss/components/_images.scss +48 -0
- package/src/scss/{custom → components}/_linklist.scss +0 -1
- package/src/scss/components/_list-group.scss +190 -0
- package/src/scss/components/_modal.scss +475 -0
- package/src/scss/components/_nav.scss +169 -0
- package/src/scss/components/_navbar.scss +273 -0
- package/src/scss/components/_offcanvas.scss +144 -0
- package/src/scss/components/_pagination.scss +108 -0
- package/src/scss/components/_placeholders.scss +51 -0
- package/src/scss/components/_popover.scss +298 -0
- package/src/scss/components/_progress-bars.scss +126 -0
- package/src/scss/{custom → components}/_steppers.scss +2 -2
- package/src/scss/{custom → components}/_tab.scss +3 -7
- package/src/scss/components/_tables.scss +171 -0
- package/src/scss/components/_toasts.scss +73 -0
- package/src/scss/{custom → components}/_toolbar.scss +19 -12
- package/src/scss/components/_tooltip.scss +139 -0
- package/src/scss/{custom → components}/_type.scss +92 -0
- package/src/scss/forms/_accessible-autocomplete.scss +188 -0
- package/src/scss/forms/_floating-labels.scss +75 -0
- package/src/scss/forms/_form-check.scss +175 -0
- package/src/scss/forms/_form-control.scss +201 -0
- package/src/scss/forms/_form-range.scss +95 -0
- package/src/scss/{custom → forms}/_form-select.scss +72 -0
- package/src/scss/forms/_form-text.scss +11 -0
- package/src/scss/{custom → forms}/_forms.scss +8 -12
- package/src/scss/forms/_input-group.scss +129 -0
- package/src/scss/forms/_labels.scss +36 -0
- package/src/scss/forms/_validation.scss +12 -0
- package/src/scss/utilities/icons.scss +5 -5
- package/types/index.d.ts +4 -1
- package/types/plugins/video.ts +33 -0
- package/dist/plugins/backToTop.js.map +0 -1
- package/src/scss/_functions.scss +0 -38
- package/src/scss/_variables.scss +0 -639
- package/src/scss/custom/_accessible-autocomplete.scss +0 -30
- package/src/scss/custom/_accordion.scss +0 -176
- package/src/scss/custom/_badge.scss +0 -29
- package/src/scss/custom/_breadcrumb.scss +0 -51
- package/src/scss/custom/_buttons.scss +0 -235
- package/src/scss/custom/_componente-base.scss +0 -6
- package/src/scss/custom/_dropdown.scss +0 -248
- package/src/scss/custom/_form-datepicker.scss +0 -604
- package/src/scss/custom/_images.scss +0 -10
- package/src/scss/custom/_modal.scss +0 -248
- package/src/scss/custom/_popover.scss +0 -106
- package/src/scss/custom/_progress-bars.scss +0 -70
- package/src/scss/custom/_tables.scss +0 -11
- package/src/scss/custom/_timepicker.scss +0 -252
- package/src/scss/custom/_tooltip.scss +0 -33
- package/src/scss/custom/_version.scss +0 -3
- package/src/scss/custom/mixins/_buttons.scss +0 -67
- package/src/scss/utilities/colors_vars.scss +0 -426
- /package/src/scss/{custom → base}/mixins/_text-emphasis.scss +0 -0
- /package/src/scss/{custom → components}/_accept-overlay.scss +0 -0
- /package/src/scss/{custom → components}/_affix.scss +0 -0
- /package/src/scss/{custom → components}/_alert.scss +0 -0
- /package/src/scss/{custom → components}/_anchor.scss +0 -0
- /package/src/scss/{custom → components}/_avatar.scss +0 -0
- /package/src/scss/{custom → components}/_back-to-top.scss +0 -0
- /package/src/scss/{custom → components}/_bottomnav.scss +0 -0
- /package/src/scss/{custom → components}/_calendar.scss +0 -0
- /package/src/scss/{custom → components}/_callout.scss +0 -0
- /package/src/scss/{custom → components}/_chips.scss +0 -0
- /package/src/scss/{custom → components}/_code.scss +0 -0
- /package/src/scss/{custom → components}/_cookiebar.scss +0 -0
- /package/src/scss/{custom → components}/_dimmer.scss +0 -0
- /package/src/scss/{custom → components}/_figcaption.scss +0 -0
- /package/src/scss/{custom → components}/_font.scss +0 -0
- /package/src/scss/{custom → components}/_footer.scss +0 -0
- /package/src/scss/{custom → components}/_forward.scss +0 -0
- /package/src/scss/{custom → components}/_header.scss +0 -0
- /package/src/scss/{custom → components}/_headercenter.scss +0 -0
- /package/src/scss/{custom → components}/_headercentertheme.scss +0 -0
- /package/src/scss/{custom → components}/_headernavbar.scss +0 -0
- /package/src/scss/{custom → components}/_headernavbartheme.scss +0 -0
- /package/src/scss/{custom → components}/_headerslim.scss +0 -0
- /package/src/scss/{custom → components}/_headerslimtheme.scss +0 -0
- /package/src/scss/{custom → components}/_imgresponsive.scss +0 -0
- /package/src/scss/{custom → components}/_list.scss +0 -0
- /package/src/scss/{custom → components}/_map.scss +0 -0
- /package/src/scss/{custom → components}/_masonry-loader.scss +0 -0
- /package/src/scss/{custom → components}/_megamenu.scss +0 -0
- /package/src/scss/{custom → components}/_navigation.scss +0 -0
- /package/src/scss/{custom → components}/_navigationtheme.scss +0 -0
- /package/src/scss/{custom → components}/_navscroll.scss +0 -0
- /package/src/scss/{custom → components}/_navscrolltheme.scss +0 -0
- /package/src/scss/{custom → components}/_notifications.scss +0 -0
- /package/src/scss/{custom → components}/_overlay-panel.scss +0 -0
- /package/src/scss/{custom → components}/_page-scroll.scss +0 -0
- /package/src/scss/{custom → components}/_pager.scss +0 -0
- /package/src/scss/{custom → components}/_point-list.scss +0 -0
- /package/src/scss/{custom → components}/_print.scss +0 -0
- /package/src/scss/{custom → components}/_progress-donuts.scss +0 -0
- /package/src/scss/{custom → components}/_progress-spinners.scss +0 -0
- /package/src/scss/{custom → components}/_rating-list.scss +0 -0
- /package/src/scss/{custom → components}/_rating.scss +0 -0
- /package/src/scss/{custom → components}/_sections.scss +0 -0
- /package/src/scss/{custom → components}/_sidebar.scss +0 -0
- /package/src/scss/{custom → components}/_sidebarthemes.scss +0 -0
- /package/src/scss/{custom → components}/_skiplinks.scss +0 -0
- /package/src/scss/{custom → components}/_sticky.scss +0 -0
- /package/src/scss/{custom → components}/_thumbnav.scss +0 -0
- /package/src/scss/{custom → components}/_timeline.scss +0 -0
- /package/src/scss/{custom → components}/_videoplayer.scss +0 -0
- /package/src/scss/{custom → forms}/_autocomplete.scss +0 -0
- /package/src/scss/{custom → forms}/_form-input-file.scss +0 -0
- /package/src/scss/{custom → forms}/_form-input-number.scss +0 -0
- /package/src/scss/{custom → forms}/_form-input-upload.scss +0 -0
- /package/src/scss/{custom → forms}/_form-password.scss +0 -0
- /package/src/scss/{custom → forms}/_form-toggles.scss +0 -0
- /package/src/scss/{custom → forms}/_form-transfer.scss +0 -0
- /package/src/scss/{custom → forms}/_just-validate.scss +0 -0
- /package/types/plugins/{backToTop.d.ts → back-to-top.d.ts} +0 -0
|
@@ -0,0 +1,317 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* --------------------------------------------------------------------------
|
|
3
|
+
* Bootstrap Italia (https://italia.github.io/bootstrap-italia/)
|
|
4
|
+
* Authors: https://github.com/italia/bootstrap-italia/blob/main/AUTHORS
|
|
5
|
+
* Licensed under BSD-3-Clause license (https://github.com/italia/bootstrap-italia/blob/main/LICENSE)
|
|
6
|
+
* This a fork of Bootstrap: Initial license and original file name below
|
|
7
|
+
* Bootstrap (v5.2.3): util/index.js
|
|
8
|
+
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
|
|
9
|
+
* --------------------------------------------------------------------------
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
const MAX_UID = 1_000_000
|
|
13
|
+
const MILLISECONDS_MULTIPLIER = 1000
|
|
14
|
+
const TRANSITION_END = 'transitionend'
|
|
15
|
+
|
|
16
|
+
// Shout-out Angus Croll (https://goo.gl/pxwQGp)
|
|
17
|
+
const toType = (object) => {
|
|
18
|
+
if (object === null || object === undefined) {
|
|
19
|
+
return `${object}`
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
return Object.prototype.toString
|
|
23
|
+
.call(object)
|
|
24
|
+
.match(/\s([a-z]+)/i)[1]
|
|
25
|
+
.toLowerCase()
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Public Util API
|
|
30
|
+
*/
|
|
31
|
+
|
|
32
|
+
const getUID = (prefix) => {
|
|
33
|
+
do {
|
|
34
|
+
prefix += Math.floor(Math.random() * MAX_UID)
|
|
35
|
+
} while (document.getElementById(prefix))
|
|
36
|
+
|
|
37
|
+
return prefix
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
const getSelector = (element) => {
|
|
41
|
+
let selector = element.getAttribute('data-bs-target')
|
|
42
|
+
|
|
43
|
+
if (!selector || selector === '#') {
|
|
44
|
+
let hrefAttribute = element.getAttribute('href')
|
|
45
|
+
|
|
46
|
+
// The only valid content that could double as a selector are IDs or classes,
|
|
47
|
+
// so everything starting with `#` or `.`. If a "real" URL is used as the selector,
|
|
48
|
+
// `document.querySelector` will rightfully complain it is invalid.
|
|
49
|
+
// See https://github.com/twbs/bootstrap/issues/32273
|
|
50
|
+
if (!hrefAttribute || (!hrefAttribute.includes('#') && !hrefAttribute.startsWith('.'))) {
|
|
51
|
+
return null
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
// Just in case some CMS puts out a full URL with the anchor appended
|
|
55
|
+
if (hrefAttribute.includes('#') && !hrefAttribute.startsWith('#')) {
|
|
56
|
+
hrefAttribute = `#${hrefAttribute.split('#')[1]}`
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
selector = hrefAttribute && hrefAttribute !== '#' ? hrefAttribute.trim() : null
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
return selector
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
const getSelectorFromElement = (element) => {
|
|
66
|
+
const selector = getSelector(element)
|
|
67
|
+
|
|
68
|
+
if (selector) {
|
|
69
|
+
return document.querySelector(selector) ? selector : null
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
return null
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
const getElementFromSelector = (element) => {
|
|
76
|
+
const selector = getSelector(element)
|
|
77
|
+
|
|
78
|
+
return selector ? document.querySelector(selector) : null
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
const getTransitionDurationFromElement = (element) => {
|
|
82
|
+
if (!element) {
|
|
83
|
+
return 0
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
// Get transition-duration of the element
|
|
87
|
+
let { transitionDuration, transitionDelay } = window.getComputedStyle(element)
|
|
88
|
+
|
|
89
|
+
const floatTransitionDuration = Number.parseFloat(transitionDuration)
|
|
90
|
+
const floatTransitionDelay = Number.parseFloat(transitionDelay)
|
|
91
|
+
|
|
92
|
+
// Return 0 if element or transition duration is not found
|
|
93
|
+
if (!floatTransitionDuration && !floatTransitionDelay) {
|
|
94
|
+
return 0
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
// If multiple durations are defined, take the first
|
|
98
|
+
transitionDuration = transitionDuration.split(',')[0]
|
|
99
|
+
transitionDelay = transitionDelay.split(',')[0]
|
|
100
|
+
|
|
101
|
+
return (Number.parseFloat(transitionDuration) + Number.parseFloat(transitionDelay)) * MILLISECONDS_MULTIPLIER
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
const triggerTransitionEnd = (element) => {
|
|
105
|
+
element.dispatchEvent(new Event(TRANSITION_END))
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
const isElement = (object) => {
|
|
109
|
+
if (!object || typeof object !== 'object') {
|
|
110
|
+
return false
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
return typeof object.nodeType !== 'undefined'
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
const getElement = (object) => {
|
|
117
|
+
if (isElement(object)) {
|
|
118
|
+
return object
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
if (typeof object === 'string' && object.length > 0) {
|
|
122
|
+
return document.querySelector(object)
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
return null
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
const isVisible = (element) => {
|
|
129
|
+
if (!isElement(element) || element.getClientRects().length === 0) {
|
|
130
|
+
return false
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
const elementIsVisible = getComputedStyle(element).getPropertyValue('visibility') === 'visible'
|
|
134
|
+
// Handle `details` element as its content may falsie appear visible when it is closed
|
|
135
|
+
const closedDetails = element.closest('details:not([open])')
|
|
136
|
+
|
|
137
|
+
if (!closedDetails) {
|
|
138
|
+
return elementIsVisible
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
if (closedDetails !== element) {
|
|
142
|
+
const summary = element.closest('summary')
|
|
143
|
+
if (summary && summary.parentNode !== closedDetails) {
|
|
144
|
+
return false
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
if (summary === null) {
|
|
148
|
+
return false
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
return elementIsVisible
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
const isDisabled = (element) => {
|
|
156
|
+
if (!element || element.nodeType !== Node.ELEMENT_NODE) {
|
|
157
|
+
return true
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
if (element.classList.contains('disabled')) {
|
|
161
|
+
return true
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
if (typeof element.disabled !== 'undefined') {
|
|
165
|
+
return element.disabled
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
return element.hasAttribute('disabled') && element.getAttribute('disabled') !== 'false'
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
const findShadowRoot = (element) => {
|
|
172
|
+
if (!document.documentElement.attachShadow) {
|
|
173
|
+
return null
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
// Can find the shadow root otherwise it'll return the document
|
|
177
|
+
if (typeof element.getRootNode === 'function') {
|
|
178
|
+
const root = element.getRootNode()
|
|
179
|
+
return root instanceof ShadowRoot ? root : null
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
if (element instanceof ShadowRoot) {
|
|
183
|
+
return element
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
// when we don't find a shadow root
|
|
187
|
+
if (!element.parentNode) {
|
|
188
|
+
return null
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
return findShadowRoot(element.parentNode)
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
const noop = () => {}
|
|
195
|
+
|
|
196
|
+
/**
|
|
197
|
+
* Trick to restart an element's animation
|
|
198
|
+
*
|
|
199
|
+
* @param {HTMLElement} element
|
|
200
|
+
* @return void
|
|
201
|
+
*
|
|
202
|
+
* @see https://www.charistheo.io/blog/2021/02/restart-a-css-animation-with-javascript/#restarting-a-css-animation
|
|
203
|
+
*/
|
|
204
|
+
const reflow = (element) => {
|
|
205
|
+
element.offsetHeight
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
const DOMContentLoadedCallbacks = []
|
|
209
|
+
|
|
210
|
+
const onDOMContentLoaded = (callback) => {
|
|
211
|
+
if (document.readyState === 'loading') {
|
|
212
|
+
// add listener on the first call when the document is in loading state
|
|
213
|
+
if (!DOMContentLoadedCallbacks.length) {
|
|
214
|
+
document.addEventListener('DOMContentLoaded', () => {
|
|
215
|
+
for (const callback of DOMContentLoadedCallbacks) {
|
|
216
|
+
callback()
|
|
217
|
+
}
|
|
218
|
+
})
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
DOMContentLoadedCallbacks.push(callback)
|
|
222
|
+
} else {
|
|
223
|
+
callback()
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
const isRTL = () => {
|
|
228
|
+
if (typeof window !== 'undefined' && typeof document !== 'undefined') {
|
|
229
|
+
return document.documentElement.dir === 'rtl'
|
|
230
|
+
} else {
|
|
231
|
+
return false
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
const execute = (callback) => {
|
|
236
|
+
if (typeof callback === 'function') {
|
|
237
|
+
callback()
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
const executeAfterTransition = (callback, transitionElement, waitForTransition = true) => {
|
|
242
|
+
if (!waitForTransition) {
|
|
243
|
+
execute(callback)
|
|
244
|
+
return
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
const durationPadding = 5
|
|
248
|
+
const emulatedDuration = getTransitionDurationFromElement(transitionElement) + durationPadding
|
|
249
|
+
|
|
250
|
+
let called = false
|
|
251
|
+
|
|
252
|
+
const handler = ({ target }) => {
|
|
253
|
+
if (target !== transitionElement) {
|
|
254
|
+
return
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
called = true
|
|
258
|
+
transitionElement.removeEventListener(TRANSITION_END, handler)
|
|
259
|
+
execute(callback)
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
transitionElement.addEventListener(TRANSITION_END, handler)
|
|
263
|
+
setTimeout(() => {
|
|
264
|
+
if (!called) {
|
|
265
|
+
triggerTransitionEnd(transitionElement)
|
|
266
|
+
}
|
|
267
|
+
}, emulatedDuration)
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
/**
|
|
271
|
+
* Return the previous/next element of a list.
|
|
272
|
+
*
|
|
273
|
+
* @param {array} list The list of elements
|
|
274
|
+
* @param activeElement The active element
|
|
275
|
+
* @param shouldGetNext Choose to get next or previous element
|
|
276
|
+
* @param isCycleAllowed
|
|
277
|
+
* @return {Element|elem} The proper element
|
|
278
|
+
*/
|
|
279
|
+
const getNextActiveElement = (list, activeElement, shouldGetNext, isCycleAllowed) => {
|
|
280
|
+
const listLength = list.length
|
|
281
|
+
let index = list.indexOf(activeElement)
|
|
282
|
+
|
|
283
|
+
// if the element does not exist in the list return an element
|
|
284
|
+
// depending on the direction and if cycle is allowed
|
|
285
|
+
if (index === -1) {
|
|
286
|
+
return !shouldGetNext && isCycleAllowed ? list[listLength - 1] : list[0]
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
index += shouldGetNext ? 1 : -1
|
|
290
|
+
|
|
291
|
+
if (isCycleAllowed) {
|
|
292
|
+
index = (index + listLength) % listLength
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
return list[Math.max(0, Math.min(index, listLength - 1))]
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
export {
|
|
299
|
+
execute,
|
|
300
|
+
executeAfterTransition,
|
|
301
|
+
findShadowRoot,
|
|
302
|
+
getElement,
|
|
303
|
+
getElementFromSelector,
|
|
304
|
+
getNextActiveElement,
|
|
305
|
+
getSelectorFromElement,
|
|
306
|
+
getTransitionDurationFromElement,
|
|
307
|
+
getUID,
|
|
308
|
+
isDisabled,
|
|
309
|
+
isElement,
|
|
310
|
+
isRTL,
|
|
311
|
+
isVisible,
|
|
312
|
+
noop,
|
|
313
|
+
onDOMContentLoaded,
|
|
314
|
+
reflow,
|
|
315
|
+
triggerTransitionEnd,
|
|
316
|
+
toType,
|
|
317
|
+
}
|
|
@@ -1,3 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* --------------------------------------------------------------------------
|
|
3
|
+
* Bootstrap Italia (https://italia.github.io/bootstrap-italia/)
|
|
4
|
+
* Authors: https://github.com/italia/bootstrap-italia/blob/main/AUTHORS
|
|
5
|
+
* Licensed under BSD-3-Clause license (https://github.com/italia/bootstrap-italia/blob/main/LICENSE)
|
|
6
|
+
* --------------------------------------------------------------------------
|
|
7
|
+
*/
|
|
8
|
+
|
|
1
9
|
/**
|
|
2
10
|
* Mutation CSS Class Observer Object
|
|
3
11
|
*/
|
|
@@ -1,3 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* --------------------------------------------------------------------------
|
|
3
|
+
* Bootstrap Italia (https://italia.github.io/bootstrap-italia/)
|
|
4
|
+
* Authors: https://github.com/italia/bootstrap-italia/blob/main/AUTHORS
|
|
5
|
+
* Licensed under BSD-3-Clause license (https://github.com/italia/bootstrap-italia/blob/main/LICENSE)
|
|
6
|
+
* --------------------------------------------------------------------------
|
|
7
|
+
*/
|
|
8
|
+
|
|
1
9
|
import { v4 as uuidv4 } from 'uuid'
|
|
2
10
|
|
|
3
11
|
let ticking = false
|
|
@@ -29,15 +37,17 @@ const onDocumentScroll = (callback) => {
|
|
|
29
37
|
return
|
|
30
38
|
}
|
|
31
39
|
if (!callbacks.length) {
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
40
|
+
if (typeof window !== 'undefined' && typeof document !== 'undefined') {
|
|
41
|
+
document.addEventListener('scroll', (evt) => {
|
|
42
|
+
if (!ticking) {
|
|
43
|
+
window.requestAnimationFrame(() => {
|
|
44
|
+
callbacks.forEach((cbObj) => cbObj.cb._execute(evt))
|
|
45
|
+
ticking = false
|
|
46
|
+
})
|
|
47
|
+
ticking = true
|
|
48
|
+
}
|
|
49
|
+
})
|
|
50
|
+
}
|
|
41
51
|
}
|
|
42
52
|
|
|
43
53
|
if (typeof callback === 'function') {
|
|
@@ -1,3 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* --------------------------------------------------------------------------
|
|
3
|
+
* Bootstrap Italia (https://italia.github.io/bootstrap-italia/)
|
|
4
|
+
* Authors: https://github.com/italia/bootstrap-italia/blob/main/AUTHORS
|
|
5
|
+
* Licensed under BSD-3-Clause license (https://github.com/italia/bootstrap-italia/blob/main/LICENSE)
|
|
6
|
+
* --------------------------------------------------------------------------
|
|
7
|
+
*/
|
|
8
|
+
|
|
1
9
|
/**
|
|
2
10
|
* Prevents page scroll
|
|
3
11
|
*/
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* --------------------------------------------------------------------------
|
|
3
|
+
* Bootstrap Italia (https://italia.github.io/bootstrap-italia/)
|
|
4
|
+
* Authors: https://github.com/italia/bootstrap-italia/blob/main/AUTHORS
|
|
5
|
+
* Licensed under BSD-3-Clause license (https://github.com/italia/bootstrap-italia/blob/main/LICENSE)
|
|
6
|
+
* This a fork of Bootstrap: Initial license and original file name below
|
|
7
|
+
* Bootstrap (v5.2.3): util/sanitizer.js
|
|
8
|
+
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
|
|
9
|
+
* --------------------------------------------------------------------------
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
const uriAttributes = new Set(['background', 'cite', 'href', 'itemtype', 'longdesc', 'poster', 'src', 'xlink:href'])
|
|
13
|
+
|
|
14
|
+
const ARIA_ATTRIBUTE_PATTERN = /^aria-[\w-]*$/i
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* A pattern that recognizes a commonly useful subset of URLs that are safe.
|
|
18
|
+
*
|
|
19
|
+
* Shout-out to Angular https://github.com/angular/angular/blob/12.2.x/packages/core/src/sanitization/url_sanitizer.ts
|
|
20
|
+
*/
|
|
21
|
+
const SAFE_URL_PATTERN = /^(?:(?:https?|mailto|ftp|tel|file|sms):|[^#&/:?]*(?:[#/?]|$))/i
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* A pattern that matches safe data URLs. Only matches image, video and audio types.
|
|
25
|
+
*
|
|
26
|
+
* Shout-out to Angular https://github.com/angular/angular/blob/12.2.x/packages/core/src/sanitization/url_sanitizer.ts
|
|
27
|
+
*/
|
|
28
|
+
const DATA_URL_PATTERN = /^data:(?:image\/(?:bmp|gif|jpeg|jpg|png|tiff|webp)|video\/(?:mpeg|mp4|ogg|webm)|audio\/(?:mp3|oga|ogg|opus));base64,[\d+/a-z]+=*$/i
|
|
29
|
+
|
|
30
|
+
const allowedAttribute = (attribute, allowedAttributeList) => {
|
|
31
|
+
const attributeName = attribute.nodeName.toLowerCase()
|
|
32
|
+
|
|
33
|
+
if (allowedAttributeList.includes(attributeName)) {
|
|
34
|
+
if (uriAttributes.has(attributeName)) {
|
|
35
|
+
return Boolean(SAFE_URL_PATTERN.test(attribute.nodeValue) || DATA_URL_PATTERN.test(attribute.nodeValue))
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
return true
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
// Check if a regular expression validates the attribute.
|
|
42
|
+
return allowedAttributeList.filter((attributeRegex) => attributeRegex instanceof RegExp).some((regex) => regex.test(attributeName))
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
export const DefaultAllowlist = {
|
|
46
|
+
// Global attributes allowed on any supplied element below.
|
|
47
|
+
'*': ['class', 'dir', 'id', 'lang', 'role', ARIA_ATTRIBUTE_PATTERN],
|
|
48
|
+
a: ['target', 'href', 'title', 'rel'],
|
|
49
|
+
area: [],
|
|
50
|
+
b: [],
|
|
51
|
+
br: [],
|
|
52
|
+
col: [],
|
|
53
|
+
code: [],
|
|
54
|
+
div: [],
|
|
55
|
+
em: [],
|
|
56
|
+
hr: [],
|
|
57
|
+
h1: [],
|
|
58
|
+
h2: [],
|
|
59
|
+
h3: [],
|
|
60
|
+
h4: [],
|
|
61
|
+
h5: [],
|
|
62
|
+
h6: [],
|
|
63
|
+
i: [],
|
|
64
|
+
img: ['src', 'srcset', 'alt', 'title', 'width', 'height'],
|
|
65
|
+
li: [],
|
|
66
|
+
ol: [],
|
|
67
|
+
p: [],
|
|
68
|
+
pre: [],
|
|
69
|
+
s: [],
|
|
70
|
+
small: [],
|
|
71
|
+
span: [],
|
|
72
|
+
sub: [],
|
|
73
|
+
sup: [],
|
|
74
|
+
strong: [],
|
|
75
|
+
u: [],
|
|
76
|
+
ul: [],
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
export function sanitizeHtml(unsafeHtml, allowList, sanitizeFunction) {
|
|
80
|
+
if (!unsafeHtml.length) {
|
|
81
|
+
return unsafeHtml
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
if (sanitizeFunction && typeof sanitizeFunction === 'function') {
|
|
85
|
+
return sanitizeFunction(unsafeHtml)
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
const domParser = new window.DOMParser()
|
|
89
|
+
const createdDocument = domParser.parseFromString(unsafeHtml, 'text/html')
|
|
90
|
+
const elements = [].concat(...createdDocument.body.querySelectorAll('*'))
|
|
91
|
+
|
|
92
|
+
for (const element of elements) {
|
|
93
|
+
const elementName = element.nodeName.toLowerCase()
|
|
94
|
+
|
|
95
|
+
if (!Object.keys(allowList).includes(elementName)) {
|
|
96
|
+
element.remove()
|
|
97
|
+
|
|
98
|
+
continue
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
const attributeList = [].concat(...element.attributes)
|
|
102
|
+
const allowedAttributes = [].concat(allowList['*'] || [], allowList[elementName] || [])
|
|
103
|
+
|
|
104
|
+
for (const attribute of attributeList) {
|
|
105
|
+
if (!allowedAttribute(attribute, allowedAttributes)) {
|
|
106
|
+
element.removeAttribute(attribute.nodeName)
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
return createdDocument.body.innerHTML
|
|
112
|
+
}
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* --------------------------------------------------------------------------
|
|
3
|
+
* Bootstrap Italia (https://italia.github.io/bootstrap-italia/)
|
|
4
|
+
* Authors: https://github.com/italia/bootstrap-italia/blob/main/AUTHORS
|
|
5
|
+
* Licensed under BSD-3-Clause license (https://github.com/italia/bootstrap-italia/blob/main/LICENSE)
|
|
6
|
+
* This a fork of Bootstrap: Initial license and original file name below
|
|
7
|
+
* Bootstrap (v5.2.3): util/scrollBar.js
|
|
8
|
+
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
|
|
9
|
+
* --------------------------------------------------------------------------
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
import SelectorEngine from '../dom/selector-engine'
|
|
13
|
+
import Manipulator from '../dom/manipulator'
|
|
14
|
+
import { isElement } from './index'
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Constants
|
|
18
|
+
*/
|
|
19
|
+
|
|
20
|
+
const SELECTOR_FIXED_CONTENT = '.fixed-top, .fixed-bottom, .is-fixed, .sticky-top'
|
|
21
|
+
const SELECTOR_STICKY_CONTENT = '.sticky-top'
|
|
22
|
+
const PROPERTY_PADDING = 'padding-right'
|
|
23
|
+
const PROPERTY_MARGIN = 'margin-right'
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Class definition
|
|
27
|
+
*/
|
|
28
|
+
|
|
29
|
+
class ScrollBarHelper {
|
|
30
|
+
constructor() {
|
|
31
|
+
this._element = document.body
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
// Public
|
|
35
|
+
getWidth() {
|
|
36
|
+
// https://developer.mozilla.org/en-US/docs/Web/API/Window/innerWidth#usage_notes
|
|
37
|
+
const documentWidth = document.documentElement.clientWidth
|
|
38
|
+
return Math.abs(window.innerWidth - documentWidth)
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
hide() {
|
|
42
|
+
const width = this.getWidth()
|
|
43
|
+
this._disableOverFlow()
|
|
44
|
+
// give padding to element to balance the hidden scrollbar width
|
|
45
|
+
this._setElementAttributes(this._element, PROPERTY_PADDING, (calculatedValue) => calculatedValue + width)
|
|
46
|
+
// trick: We adjust positive paddingRight and negative marginRight to sticky-top elements to keep showing fullwidth
|
|
47
|
+
this._setElementAttributes(SELECTOR_FIXED_CONTENT, PROPERTY_PADDING, (calculatedValue) => calculatedValue + width)
|
|
48
|
+
this._setElementAttributes(SELECTOR_STICKY_CONTENT, PROPERTY_MARGIN, (calculatedValue) => calculatedValue - width)
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
reset() {
|
|
52
|
+
this._resetElementAttributes(this._element, 'overflow')
|
|
53
|
+
this._resetElementAttributes(this._element, PROPERTY_PADDING)
|
|
54
|
+
this._resetElementAttributes(SELECTOR_FIXED_CONTENT, PROPERTY_PADDING)
|
|
55
|
+
this._resetElementAttributes(SELECTOR_STICKY_CONTENT, PROPERTY_MARGIN)
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
isOverflowing() {
|
|
59
|
+
return this.getWidth() > 0
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
// Private
|
|
63
|
+
_disableOverFlow() {
|
|
64
|
+
this._saveInitialAttribute(this._element, 'overflow')
|
|
65
|
+
this._element.style.overflow = 'hidden'
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
_setElementAttributes(selector, styleProperty, callback) {
|
|
69
|
+
const scrollbarWidth = this.getWidth()
|
|
70
|
+
const manipulationCallBack = (element) => {
|
|
71
|
+
if (element !== this._element && window.innerWidth > element.clientWidth + scrollbarWidth) {
|
|
72
|
+
return
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
this._saveInitialAttribute(element, styleProperty)
|
|
76
|
+
const calculatedValue = window.getComputedStyle(element).getPropertyValue(styleProperty)
|
|
77
|
+
element.style.setProperty(styleProperty, `${callback(Number.parseFloat(calculatedValue))}px`)
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
this._applyManipulationCallback(selector, manipulationCallBack)
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
_saveInitialAttribute(element, styleProperty) {
|
|
84
|
+
const actualValue = element.style.getPropertyValue(styleProperty)
|
|
85
|
+
if (actualValue) {
|
|
86
|
+
Manipulator.setDataAttribute(element, styleProperty, actualValue)
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
_resetElementAttributes(selector, styleProperty) {
|
|
91
|
+
const manipulationCallBack = (element) => {
|
|
92
|
+
const value = Manipulator.getDataAttribute(element, styleProperty)
|
|
93
|
+
// We only want to remove the property if the value is `null`; the value can also be zero
|
|
94
|
+
if (value === null) {
|
|
95
|
+
element.style.removeProperty(styleProperty)
|
|
96
|
+
return
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
Manipulator.removeDataAttribute(element, styleProperty)
|
|
100
|
+
element.style.setProperty(styleProperty, value)
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
this._applyManipulationCallback(selector, manipulationCallBack)
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
_applyManipulationCallback(selector, callBack) {
|
|
107
|
+
if (isElement(selector)) {
|
|
108
|
+
callBack(selector)
|
|
109
|
+
return
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
for (const sel of SelectorEngine.find(selector, this._element)) {
|
|
113
|
+
callBack(sel)
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
export default ScrollBarHelper
|