mirror of
https://github.com/twbs/bootstrap.git
synced 2025-02-26 23:54:23 +01:00
Be SSR friendly when accessing DOM objects
This commit is contained in:
parent
c44d99f55c
commit
8306213650
@ -1,8 +1,10 @@
|
|||||||
{
|
{
|
||||||
"root": true,
|
"root": true,
|
||||||
|
"plugins": ["ssr-friendly"],
|
||||||
"extends": [
|
"extends": [
|
||||||
"plugin:import/errors",
|
"plugin:import/errors",
|
||||||
"plugin:import/warnings",
|
"plugin:import/warnings",
|
||||||
|
"plugin:ssr-friendly/recommended",
|
||||||
"plugin:unicorn/recommended",
|
"plugin:unicorn/recommended",
|
||||||
"xo",
|
"xo",
|
||||||
"xo/browser"
|
"xo/browser"
|
||||||
@ -50,6 +52,8 @@
|
|||||||
"error",
|
"error",
|
||||||
"never"
|
"never"
|
||||||
],
|
],
|
||||||
|
"ssr-friendly/no-dom-globals-in-react-cc-render": "off",
|
||||||
|
"ssr-friendly/no-dom-globals-in-react-fc": "off",
|
||||||
"unicorn/explicit-length-check": "off",
|
"unicorn/explicit-length-check": "off",
|
||||||
"unicorn/no-array-callback-reference": "off",
|
"unicorn/no-array-callback-reference": "off",
|
||||||
"unicorn/no-array-method-this-argument": "off",
|
"unicorn/no-array-method-this-argument": "off",
|
||||||
|
@ -6,7 +6,12 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import Data from './dom/data'
|
import Data from './dom/data'
|
||||||
import { executeAfterTransition, getElement } from './util/index'
|
import {
|
||||||
|
executeAfterTransition,
|
||||||
|
getElement,
|
||||||
|
getWindow,
|
||||||
|
getDocument
|
||||||
|
} from './util/index'
|
||||||
import EventHandler from './dom/event-handler'
|
import EventHandler from './dom/event-handler'
|
||||||
import Config from './util/config'
|
import Config from './util/config'
|
||||||
|
|
||||||
@ -30,6 +35,8 @@ class BaseComponent extends Config {
|
|||||||
}
|
}
|
||||||
|
|
||||||
this._element = element
|
this._element = element
|
||||||
|
this._window = getWindow()
|
||||||
|
this._document = getDocument()
|
||||||
this._config = this._getConfig(config)
|
this._config = this._getConfig(config)
|
||||||
|
|
||||||
Data.set(this._element, this.constructor.DATA_KEY, this)
|
Data.set(this._element, this.constructor.DATA_KEY, this)
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
* --------------------------------------------------------------------------
|
* --------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { defineJQueryPlugin } from './util/index'
|
import { defineJQueryPlugin, getDocument } from './util/index'
|
||||||
import EventHandler from './dom/event-handler'
|
import EventHandler from './dom/event-handler'
|
||||||
import BaseComponent from './base-component'
|
import BaseComponent from './base-component'
|
||||||
|
|
||||||
@ -54,7 +54,7 @@ class Button extends BaseComponent {
|
|||||||
* Data API implementation
|
* Data API implementation
|
||||||
*/
|
*/
|
||||||
|
|
||||||
EventHandler.on(document, EVENT_CLICK_DATA_API, SELECTOR_DATA_TOGGLE, event => {
|
EventHandler.on(getDocument(), EVENT_CLICK_DATA_API, SELECTOR_DATA_TOGGLE, event => {
|
||||||
event.preventDefault()
|
event.preventDefault()
|
||||||
|
|
||||||
const button = event.target.closest(SELECTOR_DATA_TOGGLE)
|
const button = event.target.closest(SELECTOR_DATA_TOGGLE)
|
||||||
|
@ -12,7 +12,9 @@ import {
|
|||||||
isRTL,
|
isRTL,
|
||||||
isVisible,
|
isVisible,
|
||||||
reflow,
|
reflow,
|
||||||
triggerTransitionEnd
|
triggerTransitionEnd,
|
||||||
|
getDocument,
|
||||||
|
getWindow
|
||||||
} from './util/index'
|
} from './util/index'
|
||||||
import EventHandler from './dom/event-handler'
|
import EventHandler from './dom/event-handler'
|
||||||
import Manipulator from './dom/manipulator'
|
import Manipulator from './dom/manipulator'
|
||||||
@ -129,7 +131,7 @@ class Carousel extends BaseComponent {
|
|||||||
// FIXME TODO use `document.visibilityState`
|
// FIXME TODO use `document.visibilityState`
|
||||||
// Don't call next when the page isn't visible
|
// Don't call next when the page isn't visible
|
||||||
// or the carousel or its parent isn't visible
|
// or the carousel or its parent isn't visible
|
||||||
if (!document.hidden && isVisible(this._element)) {
|
if (!this._document.hidden && isVisible(this._element)) {
|
||||||
this.next()
|
this.next()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -505,9 +507,9 @@ class Carousel extends BaseComponent {
|
|||||||
* Data API implementation
|
* Data API implementation
|
||||||
*/
|
*/
|
||||||
|
|
||||||
EventHandler.on(document, EVENT_CLICK_DATA_API, SELECTOR_DATA_SLIDE, Carousel.dataApiClickHandler)
|
EventHandler.on(getDocument(), EVENT_CLICK_DATA_API, SELECTOR_DATA_SLIDE, Carousel.dataApiClickHandler)
|
||||||
|
|
||||||
EventHandler.on(window, EVENT_LOAD_DATA_API, () => {
|
EventHandler.on(getWindow(), EVENT_LOAD_DATA_API, () => {
|
||||||
const carousels = SelectorEngine.find(SELECTOR_DATA_RIDE)
|
const carousels = SelectorEngine.find(SELECTOR_DATA_RIDE)
|
||||||
|
|
||||||
for (const carousel of carousels) {
|
for (const carousel of carousels) {
|
||||||
|
@ -10,7 +10,8 @@ import {
|
|||||||
getElement,
|
getElement,
|
||||||
getElementFromSelector,
|
getElementFromSelector,
|
||||||
getSelectorFromElement,
|
getSelectorFromElement,
|
||||||
reflow
|
reflow,
|
||||||
|
getDocument
|
||||||
} from './util/index'
|
} from './util/index'
|
||||||
import EventHandler from './dom/event-handler'
|
import EventHandler from './dom/event-handler'
|
||||||
import SelectorEngine from './dom/selector-engine'
|
import SelectorEngine from './dom/selector-engine'
|
||||||
@ -279,7 +280,7 @@ class Collapse extends BaseComponent {
|
|||||||
* Data API implementation
|
* Data API implementation
|
||||||
*/
|
*/
|
||||||
|
|
||||||
EventHandler.on(document, EVENT_CLICK_DATA_API, SELECTOR_DATA_TOGGLE, function (event) {
|
EventHandler.on(getDocument(), EVENT_CLICK_DATA_API, SELECTOR_DATA_TOGGLE, function (event) {
|
||||||
// preventDefault only for <a> elements (which change the URL) not inside the collapsible element
|
// preventDefault only for <a> elements (which change the URL) not inside the collapsible element
|
||||||
if (event.target.tagName === 'A' || (event.delegateTarget && event.delegateTarget.tagName === 'A')) {
|
if (event.target.tagName === 'A' || (event.delegateTarget && event.delegateTarget.tagName === 'A')) {
|
||||||
event.preventDefault()
|
event.preventDefault()
|
||||||
|
@ -5,6 +5,8 @@
|
|||||||
* --------------------------------------------------------------------------
|
* --------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
import { getWindow } from '../util/index'
|
||||||
|
|
||||||
function normalizeData(value) {
|
function normalizeData(value) {
|
||||||
if (value === 'true') {
|
if (value === 'true') {
|
||||||
return true
|
return true
|
||||||
@ -61,10 +63,11 @@ const Manipulator = {
|
|||||||
|
|
||||||
offset(element) {
|
offset(element) {
|
||||||
const rect = element.getBoundingClientRect()
|
const rect = element.getBoundingClientRect()
|
||||||
|
const windowRef = getWindow()
|
||||||
|
|
||||||
return {
|
return {
|
||||||
top: rect.top + window.pageYOffset,
|
top: rect.top + windowRef.pageYOffset,
|
||||||
left: rect.left + window.pageXOffset
|
left: rect.left + windowRef.pageXOffset
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -5,18 +5,18 @@
|
|||||||
* --------------------------------------------------------------------------
|
* --------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { isDisabled, isVisible } from '../util/index'
|
import { getDocument, isDisabled, isVisible } from '../util/index'
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constants
|
* Constants
|
||||||
*/
|
*/
|
||||||
|
|
||||||
const SelectorEngine = {
|
const SelectorEngine = {
|
||||||
find(selector, element = document.documentElement) {
|
find(selector, element = getDocument().documentElement) {
|
||||||
return [].concat(...Element.prototype.querySelectorAll.call(element, selector))
|
return [].concat(...Element.prototype.querySelectorAll.call(element, selector))
|
||||||
},
|
},
|
||||||
|
|
||||||
findOne(selector, element = document.documentElement) {
|
findOne(selector, element = getDocument().documentElement) {
|
||||||
return Element.prototype.querySelector.call(element, selector)
|
return Element.prototype.querySelector.call(element, selector)
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -14,7 +14,8 @@ import {
|
|||||||
isElement,
|
isElement,
|
||||||
isRTL,
|
isRTL,
|
||||||
isVisible,
|
isVisible,
|
||||||
noop
|
noop,
|
||||||
|
getDocument
|
||||||
} from './util/index'
|
} from './util/index'
|
||||||
import EventHandler from './dom/event-handler'
|
import EventHandler from './dom/event-handler'
|
||||||
import Manipulator from './dom/manipulator'
|
import Manipulator from './dom/manipulator'
|
||||||
@ -133,8 +134,8 @@ class Dropdown extends BaseComponent {
|
|||||||
// empty mouseover listeners to the body's immediate children;
|
// empty mouseover listeners to the body's immediate children;
|
||||||
// only needed because of broken event delegation on iOS
|
// only needed because of broken event delegation on iOS
|
||||||
// https://www.quirksmode.org/blog/archives/2014/02/mouse_event_bub.html
|
// https://www.quirksmode.org/blog/archives/2014/02/mouse_event_bub.html
|
||||||
if ('ontouchstart' in document.documentElement && !this._parent.closest(SELECTOR_NAVBAR_NAV)) {
|
if ('ontouchstart' in this._document.documentElement && !this._parent.closest(SELECTOR_NAVBAR_NAV)) {
|
||||||
for (const element of [].concat(...document.body.children)) {
|
for (const element of [].concat(...this._document.body.children)) {
|
||||||
EventHandler.on(element, 'mouseover', noop)
|
EventHandler.on(element, 'mouseover', noop)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -434,11 +435,13 @@ class Dropdown extends BaseComponent {
|
|||||||
* Data API implementation
|
* Data API implementation
|
||||||
*/
|
*/
|
||||||
|
|
||||||
EventHandler.on(document, EVENT_KEYDOWN_DATA_API, SELECTOR_DATA_TOGGLE, Dropdown.dataApiKeydownHandler)
|
const documentRef = getDocument()
|
||||||
EventHandler.on(document, EVENT_KEYDOWN_DATA_API, SELECTOR_MENU, Dropdown.dataApiKeydownHandler)
|
|
||||||
EventHandler.on(document, EVENT_CLICK_DATA_API, Dropdown.clearMenus)
|
EventHandler.on(documentRef, EVENT_KEYDOWN_DATA_API, SELECTOR_DATA_TOGGLE, Dropdown.dataApiKeydownHandler)
|
||||||
EventHandler.on(document, EVENT_KEYUP_DATA_API, Dropdown.clearMenus)
|
EventHandler.on(documentRef, EVENT_KEYDOWN_DATA_API, SELECTOR_MENU, Dropdown.dataApiKeydownHandler)
|
||||||
EventHandler.on(document, EVENT_CLICK_DATA_API, SELECTOR_DATA_TOGGLE, function (event) {
|
EventHandler.on(documentRef, EVENT_CLICK_DATA_API, Dropdown.clearMenus)
|
||||||
|
EventHandler.on(documentRef, EVENT_KEYUP_DATA_API, Dropdown.clearMenus)
|
||||||
|
EventHandler.on(documentRef, EVENT_CLICK_DATA_API, SELECTOR_DATA_TOGGLE, function (event) {
|
||||||
event.preventDefault()
|
event.preventDefault()
|
||||||
Dropdown.getOrCreateInstance(this).toggle()
|
Dropdown.getOrCreateInstance(this).toggle()
|
||||||
})
|
})
|
||||||
|
@ -5,7 +5,14 @@
|
|||||||
* --------------------------------------------------------------------------
|
* --------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { defineJQueryPlugin, getElementFromSelector, isRTL, isVisible, reflow } from './util/index'
|
import {
|
||||||
|
defineJQueryPlugin,
|
||||||
|
getElementFromSelector,
|
||||||
|
isRTL,
|
||||||
|
isVisible,
|
||||||
|
reflow,
|
||||||
|
getDocument
|
||||||
|
} from './util/index'
|
||||||
import EventHandler from './dom/event-handler'
|
import EventHandler from './dom/event-handler'
|
||||||
import SelectorEngine from './dom/selector-engine'
|
import SelectorEngine from './dom/selector-engine'
|
||||||
import ScrollBarHelper from './util/scrollbar'
|
import ScrollBarHelper from './util/scrollbar'
|
||||||
@ -184,8 +191,8 @@ class Modal extends BaseComponent {
|
|||||||
|
|
||||||
_showElement(relatedTarget) {
|
_showElement(relatedTarget) {
|
||||||
// try to append dynamic modal
|
// try to append dynamic modal
|
||||||
if (!document.body.contains(this._element)) {
|
if (!this._document.body.contains(this._element)) {
|
||||||
document.body.append(this._element)
|
this._document.body.append(this._element)
|
||||||
}
|
}
|
||||||
|
|
||||||
this._element.style.display = 'block'
|
this._element.style.display = 'block'
|
||||||
@ -255,7 +262,7 @@ class Modal extends BaseComponent {
|
|||||||
this._isTransitioning = false
|
this._isTransitioning = false
|
||||||
|
|
||||||
this._backdrop.hide(() => {
|
this._backdrop.hide(() => {
|
||||||
document.body.classList.remove(CLASS_NAME_OPEN)
|
this._document.body.classList.remove(CLASS_NAME_OPEN)
|
||||||
this._resetAdjustments()
|
this._resetAdjustments()
|
||||||
this._scrollBar.reset()
|
this._scrollBar.reset()
|
||||||
EventHandler.trigger(this._element, EVENT_HIDDEN)
|
EventHandler.trigger(this._element, EVENT_HIDDEN)
|
||||||
@ -272,7 +279,7 @@ class Modal extends BaseComponent {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
const isModalOverflowing = this._element.scrollHeight > document.documentElement.clientHeight
|
const isModalOverflowing = this._element.scrollHeight > this._document.documentElement.clientHeight
|
||||||
const initialOverflowY = this._element.style.overflowY
|
const initialOverflowY = this._element.style.overflowY
|
||||||
// return if the following background transition hasn't yet completed
|
// return if the following background transition hasn't yet completed
|
||||||
if (initialOverflowY === 'hidden' || this._element.classList.contains(CLASS_NAME_STATIC)) {
|
if (initialOverflowY === 'hidden' || this._element.classList.contains(CLASS_NAME_STATIC)) {
|
||||||
@ -299,7 +306,7 @@ class Modal extends BaseComponent {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
_adjustDialog() {
|
_adjustDialog() {
|
||||||
const isModalOverflowing = this._element.scrollHeight > document.documentElement.clientHeight
|
const isModalOverflowing = this._element.scrollHeight > this._document.documentElement.clientHeight
|
||||||
const scrollbarWidth = this._scrollBar.getWidth()
|
const scrollbarWidth = this._scrollBar.getWidth()
|
||||||
const isBodyOverflowing = scrollbarWidth > 0
|
const isBodyOverflowing = scrollbarWidth > 0
|
||||||
|
|
||||||
@ -341,7 +348,7 @@ class Modal extends BaseComponent {
|
|||||||
* Data API implementation
|
* Data API implementation
|
||||||
*/
|
*/
|
||||||
|
|
||||||
EventHandler.on(document, EVENT_CLICK_DATA_API, SELECTOR_DATA_TOGGLE, function (event) {
|
EventHandler.on(getDocument(), EVENT_CLICK_DATA_API, SELECTOR_DATA_TOGGLE, function (event) {
|
||||||
const target = getElementFromSelector(this)
|
const target = getElementFromSelector(this)
|
||||||
|
|
||||||
if (['A', 'AREA'].includes(this.tagName)) {
|
if (['A', 'AREA'].includes(this.tagName)) {
|
||||||
|
@ -9,7 +9,9 @@ import {
|
|||||||
defineJQueryPlugin,
|
defineJQueryPlugin,
|
||||||
getElementFromSelector,
|
getElementFromSelector,
|
||||||
isDisabled,
|
isDisabled,
|
||||||
isVisible
|
isVisible,
|
||||||
|
getDocument,
|
||||||
|
getWindow
|
||||||
} from './util/index'
|
} from './util/index'
|
||||||
import ScrollBarHelper from './util/scrollbar'
|
import ScrollBarHelper from './util/scrollbar'
|
||||||
import EventHandler from './dom/event-handler'
|
import EventHandler from './dom/event-handler'
|
||||||
@ -209,7 +211,7 @@ class Offcanvas extends BaseComponent {
|
|||||||
* Data API implementation
|
* Data API implementation
|
||||||
*/
|
*/
|
||||||
|
|
||||||
EventHandler.on(document, EVENT_CLICK_DATA_API, SELECTOR_DATA_TOGGLE, function (event) {
|
EventHandler.on(getDocument(), EVENT_CLICK_DATA_API, SELECTOR_DATA_TOGGLE, function (event) {
|
||||||
const target = getElementFromSelector(this)
|
const target = getElementFromSelector(this)
|
||||||
|
|
||||||
if (['A', 'AREA'].includes(this.tagName)) {
|
if (['A', 'AREA'].includes(this.tagName)) {
|
||||||
@ -237,7 +239,7 @@ EventHandler.on(document, EVENT_CLICK_DATA_API, SELECTOR_DATA_TOGGLE, function (
|
|||||||
data.toggle(this)
|
data.toggle(this)
|
||||||
})
|
})
|
||||||
|
|
||||||
EventHandler.on(window, EVENT_LOAD_DATA_API, () => {
|
EventHandler.on(getWindow(), EVENT_LOAD_DATA_API, () => {
|
||||||
for (const selector of SelectorEngine.find(OPEN_SELECTOR)) {
|
for (const selector of SelectorEngine.find(OPEN_SELECTOR)) {
|
||||||
Offcanvas.getOrCreateInstance(selector).show()
|
Offcanvas.getOrCreateInstance(selector).show()
|
||||||
}
|
}
|
||||||
|
@ -5,7 +5,12 @@
|
|||||||
* --------------------------------------------------------------------------
|
* --------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { defineJQueryPlugin, getElement, getSelectorFromElement } from './util/index'
|
import {
|
||||||
|
defineJQueryPlugin,
|
||||||
|
getElement,
|
||||||
|
getSelectorFromElement,
|
||||||
|
getWindow
|
||||||
|
} from './util/index'
|
||||||
import EventHandler from './dom/event-handler'
|
import EventHandler from './dom/event-handler'
|
||||||
import Manipulator from './dom/manipulator'
|
import Manipulator from './dom/manipulator'
|
||||||
import SelectorEngine from './dom/selector-engine'
|
import SelectorEngine from './dom/selector-engine'
|
||||||
@ -58,7 +63,7 @@ const DefaultType = {
|
|||||||
class ScrollSpy extends BaseComponent {
|
class ScrollSpy extends BaseComponent {
|
||||||
constructor(element, config) {
|
constructor(element, config) {
|
||||||
super(element, config)
|
super(element, config)
|
||||||
this._scrollElement = this._element.tagName === 'BODY' ? window : this._element
|
this._scrollElement = this._element.tagName === 'BODY' ? this._window : this._element
|
||||||
this._offsets = []
|
this._offsets = []
|
||||||
this._targets = []
|
this._targets = []
|
||||||
this._activeTarget = null
|
this._activeTarget = null
|
||||||
@ -137,14 +142,14 @@ class ScrollSpy extends BaseComponent {
|
|||||||
|
|
||||||
_getScrollHeight() {
|
_getScrollHeight() {
|
||||||
return this._scrollElement.scrollHeight || Math.max(
|
return this._scrollElement.scrollHeight || Math.max(
|
||||||
document.body.scrollHeight,
|
this._document.body.scrollHeight,
|
||||||
document.documentElement.scrollHeight
|
this._document.documentElement.scrollHeight
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
_getOffsetHeight() {
|
_getOffsetHeight() {
|
||||||
return this._scrollElement === window ?
|
return this._scrollElement === window ?
|
||||||
window.innerHeight :
|
this._window.innerHeight :
|
||||||
this._scrollElement.getBoundingClientRect().height
|
this._scrollElement.getBoundingClientRect().height
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -251,7 +256,7 @@ class ScrollSpy extends BaseComponent {
|
|||||||
* Data API implementation
|
* Data API implementation
|
||||||
*/
|
*/
|
||||||
|
|
||||||
EventHandler.on(window, EVENT_LOAD_DATA_API, () => {
|
EventHandler.on(getWindow(), EVENT_LOAD_DATA_API, () => {
|
||||||
for (const spy of SelectorEngine.find(SELECTOR_DATA_SPY)) {
|
for (const spy of SelectorEngine.find(SELECTOR_DATA_SPY)) {
|
||||||
new ScrollSpy(spy) // eslint-disable-line no-new
|
new ScrollSpy(spy) // eslint-disable-line no-new
|
||||||
}
|
}
|
||||||
|
@ -5,7 +5,13 @@
|
|||||||
* --------------------------------------------------------------------------
|
* --------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { defineJQueryPlugin, getElementFromSelector, isDisabled, reflow } from './util/index'
|
import {
|
||||||
|
defineJQueryPlugin,
|
||||||
|
getDocument,
|
||||||
|
getElementFromSelector,
|
||||||
|
isDisabled,
|
||||||
|
reflow
|
||||||
|
} from './util/index'
|
||||||
import EventHandler from './dom/event-handler'
|
import EventHandler from './dom/event-handler'
|
||||||
import SelectorEngine from './dom/selector-engine'
|
import SelectorEngine from './dom/selector-engine'
|
||||||
import BaseComponent from './base-component'
|
import BaseComponent from './base-component'
|
||||||
@ -177,7 +183,7 @@ class Tab extends BaseComponent {
|
|||||||
* Data API implementation
|
* Data API implementation
|
||||||
*/
|
*/
|
||||||
|
|
||||||
EventHandler.on(document, EVENT_CLICK_DATA_API, SELECTOR_DATA_TOGGLE, function (event) {
|
EventHandler.on(getDocument(), EVENT_CLICK_DATA_API, SELECTOR_DATA_TOGGLE, function (event) {
|
||||||
if (['A', 'AREA'].includes(this.tagName)) {
|
if (['A', 'AREA'].includes(this.tagName)) {
|
||||||
event.preventDefault()
|
event.preventDefault()
|
||||||
}
|
}
|
||||||
|
@ -245,8 +245,8 @@ class Tooltip extends BaseComponent {
|
|||||||
// empty mouseover listeners to the body's immediate children;
|
// empty mouseover listeners to the body's immediate children;
|
||||||
// only needed because of broken event delegation on iOS
|
// only needed because of broken event delegation on iOS
|
||||||
// https://www.quirksmode.org/blog/archives/2014/02/mouse_event_bub.html
|
// https://www.quirksmode.org/blog/archives/2014/02/mouse_event_bub.html
|
||||||
if ('ontouchstart' in document.documentElement) {
|
if ('ontouchstart' in this._document.documentElement) {
|
||||||
for (const element of [].concat(...document.body.children)) {
|
for (const element of [].concat(...this._document.body.children)) {
|
||||||
EventHandler.on(element, 'mouseover', noop)
|
EventHandler.on(element, 'mouseover', noop)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -280,8 +280,8 @@ class Tooltip extends BaseComponent {
|
|||||||
|
|
||||||
// If this is a touch-enabled device we remove the extra
|
// If this is a touch-enabled device we remove the extra
|
||||||
// empty mouseover listeners we added for iOS support
|
// empty mouseover listeners we added for iOS support
|
||||||
if ('ontouchstart' in document.documentElement) {
|
if ('ontouchstart' in this._document.documentElement) {
|
||||||
for (const element of [].concat(...document.body.children)) {
|
for (const element of [].concat(...this._document.body.children)) {
|
||||||
EventHandler.off(element, 'mouseover', noop)
|
EventHandler.off(element, 'mouseover', noop)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -6,13 +6,13 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import EventHandler from '../dom/event-handler'
|
import EventHandler from '../dom/event-handler'
|
||||||
import { getElementFromSelector, isDisabled } from './index'
|
import { getElementFromSelector, isDisabled, getDocument } from './index'
|
||||||
|
|
||||||
const enableDismissTrigger = (component, method = 'hide') => {
|
const enableDismissTrigger = (component, method = 'hide') => {
|
||||||
const clickEvent = `click.dismiss${component.EVENT_KEY}`
|
const clickEvent = `click.dismiss${component.EVENT_KEY}`
|
||||||
const name = component.NAME
|
const name = component.NAME
|
||||||
|
|
||||||
EventHandler.on(document, clickEvent, `[data-bs-dismiss="${name}"]`, function (event) {
|
EventHandler.on(getDocument(), clickEvent, `[data-bs-dismiss="${name}"]`, function (event) {
|
||||||
if (['A', 'AREA'].includes(this.tagName)) {
|
if (['A', 'AREA'].includes(this.tagName)) {
|
||||||
event.preventDefault()
|
event.preventDefault()
|
||||||
}
|
}
|
||||||
|
@ -7,6 +7,7 @@
|
|||||||
|
|
||||||
import EventHandler from '../dom/event-handler'
|
import EventHandler from '../dom/event-handler'
|
||||||
import SelectorEngine from '../dom/selector-engine'
|
import SelectorEngine from '../dom/selector-engine'
|
||||||
|
import { getDocument } from './index'
|
||||||
import Config from './config'
|
import Config from './config'
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -43,6 +44,7 @@ class FocusTrap extends Config {
|
|||||||
this._config = this._getConfig(config)
|
this._config = this._getConfig(config)
|
||||||
this._isActive = false
|
this._isActive = false
|
||||||
this._lastTabNavDirection = null
|
this._lastTabNavDirection = null
|
||||||
|
this._document = getDocument()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Getters
|
// Getters
|
||||||
@ -68,9 +70,9 @@ class FocusTrap extends Config {
|
|||||||
this._config.trapElement.focus()
|
this._config.trapElement.focus()
|
||||||
}
|
}
|
||||||
|
|
||||||
EventHandler.off(document, EVENT_KEY) // guard against infinite focus loop
|
EventHandler.off(this._document, EVENT_KEY) // guard against infinite focus loop
|
||||||
EventHandler.on(document, EVENT_FOCUSIN, event => this._handleFocusin(event))
|
EventHandler.on(this._document, EVENT_FOCUSIN, event => this._handleFocusin(event))
|
||||||
EventHandler.on(document, EVENT_KEYDOWN_TAB, event => this._handleKeydown(event))
|
EventHandler.on(this._document, EVENT_KEYDOWN_TAB, event => this._handleKeydown(event))
|
||||||
|
|
||||||
this._isActive = true
|
this._isActive = true
|
||||||
}
|
}
|
||||||
@ -81,14 +83,14 @@ class FocusTrap extends Config {
|
|||||||
}
|
}
|
||||||
|
|
||||||
this._isActive = false
|
this._isActive = false
|
||||||
EventHandler.off(document, EVENT_KEY)
|
EventHandler.off(this._document, EVENT_KEY)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Private
|
// Private
|
||||||
_handleFocusin(event) {
|
_handleFocusin(event) {
|
||||||
const { trapElement } = this._config
|
const { trapElement } = this._config
|
||||||
|
|
||||||
if (event.target === document || event.target === trapElement || trapElement.contains(event.target)) {
|
if (event.target === this._document || event.target === trapElement || trapElement.contains(event.target)) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -25,7 +25,7 @@ const toType = object => {
|
|||||||
const getUID = prefix => {
|
const getUID = prefix => {
|
||||||
do {
|
do {
|
||||||
prefix += Math.floor(Math.random() * MAX_UID)
|
prefix += Math.floor(Math.random() * MAX_UID)
|
||||||
} while (document.getElementById(prefix))
|
} while (getDocument().getElementById(prefix))
|
||||||
|
|
||||||
return prefix
|
return prefix
|
||||||
}
|
}
|
||||||
@ -59,7 +59,7 @@ const getSelectorFromElement = element => {
|
|||||||
const selector = getSelector(element)
|
const selector = getSelector(element)
|
||||||
|
|
||||||
if (selector) {
|
if (selector) {
|
||||||
return document.querySelector(selector) ? selector : null
|
return getDocument().querySelector(selector) ? selector : null
|
||||||
}
|
}
|
||||||
|
|
||||||
return null
|
return null
|
||||||
@ -68,7 +68,7 @@ const getSelectorFromElement = element => {
|
|||||||
const getElementFromSelector = element => {
|
const getElementFromSelector = element => {
|
||||||
const selector = getSelector(element)
|
const selector = getSelector(element)
|
||||||
|
|
||||||
return selector ? document.querySelector(selector) : null
|
return selector ? getDocument().querySelector(selector) : null
|
||||||
}
|
}
|
||||||
|
|
||||||
const getTransitionDurationFromElement = element => {
|
const getTransitionDurationFromElement = element => {
|
||||||
@ -77,7 +77,7 @@ const getTransitionDurationFromElement = element => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Get transition-duration of the element
|
// Get transition-duration of the element
|
||||||
let { transitionDuration, transitionDelay } = window.getComputedStyle(element)
|
let { transitionDuration, transitionDelay } = getWindow().getComputedStyle(element)
|
||||||
|
|
||||||
const floatTransitionDuration = Number.parseFloat(transitionDuration)
|
const floatTransitionDuration = Number.parseFloat(transitionDuration)
|
||||||
const floatTransitionDelay = Number.parseFloat(transitionDelay)
|
const floatTransitionDelay = Number.parseFloat(transitionDelay)
|
||||||
@ -167,7 +167,7 @@ const isDisabled = element => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const findShadowRoot = element => {
|
const findShadowRoot = element => {
|
||||||
if (!document.documentElement.attachShadow) {
|
if (!getDocument().documentElement.attachShadow) {
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -200,11 +200,12 @@ const noop = () => {}
|
|||||||
* @see https://www.charistheo.io/blog/2021/02/restart-a-css-animation-with-javascript/#restarting-a-css-animation
|
* @see https://www.charistheo.io/blog/2021/02/restart-a-css-animation-with-javascript/#restarting-a-css-animation
|
||||||
*/
|
*/
|
||||||
const reflow = element => {
|
const reflow = element => {
|
||||||
element.offsetHeight // eslint-disable-line no-unused-expressions
|
// eslint-disable-next-line no-unused-expressions
|
||||||
|
element.offsetHeight
|
||||||
}
|
}
|
||||||
|
|
||||||
const getjQuery = () => {
|
const getjQuery = () => {
|
||||||
if (window.jQuery && !document.body.hasAttribute('data-bs-no-jquery')) {
|
if (getWindow().jQuery && !getDocument().body.hasAttribute('data-bs-no-jquery')) {
|
||||||
return window.jQuery
|
return window.jQuery
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -214,10 +215,11 @@ const getjQuery = () => {
|
|||||||
const DOMContentLoadedCallbacks = []
|
const DOMContentLoadedCallbacks = []
|
||||||
|
|
||||||
const onDOMContentLoaded = callback => {
|
const onDOMContentLoaded = callback => {
|
||||||
if (document.readyState === 'loading') {
|
const documentRef = getDocument()
|
||||||
|
if (documentRef.readyState === 'loading') {
|
||||||
// add listener on the first call when the document is in loading state
|
// add listener on the first call when the document is in loading state
|
||||||
if (!DOMContentLoadedCallbacks.length) {
|
if (!DOMContentLoadedCallbacks.length) {
|
||||||
document.addEventListener('DOMContentLoaded', () => {
|
documentRef.addEventListener('DOMContentLoaded', () => {
|
||||||
for (const callback of DOMContentLoadedCallbacks) {
|
for (const callback of DOMContentLoadedCallbacks) {
|
||||||
callback()
|
callback()
|
||||||
}
|
}
|
||||||
@ -230,7 +232,7 @@ const onDOMContentLoaded = callback => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const isRTL = () => document.documentElement.dir === 'rtl'
|
const isRTL = () => getDocument().documentElement.dir === 'rtl'
|
||||||
|
|
||||||
const defineJQueryPlugin = plugin => {
|
const defineJQueryPlugin = plugin => {
|
||||||
onDOMContentLoaded(() => {
|
onDOMContentLoaded(() => {
|
||||||
@ -312,11 +314,26 @@ const getNextActiveElement = (list, activeElement, shouldGetNext, isCycleAllowed
|
|||||||
return list[Math.max(0, Math.min(index, listLength - 1))]
|
return list[Math.max(0, Math.min(index, listLength - 1))]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return {window|{}} The proper element
|
||||||
|
*/
|
||||||
|
const getWindow = () => {
|
||||||
|
return typeof window !== 'undefined' ? window : {}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return {document|{}} The proper element
|
||||||
|
*/
|
||||||
|
const getDocument = () => {
|
||||||
|
return typeof document !== 'undefined' ? document : {}
|
||||||
|
}
|
||||||
|
|
||||||
export {
|
export {
|
||||||
defineJQueryPlugin,
|
defineJQueryPlugin,
|
||||||
execute,
|
execute,
|
||||||
executeAfterTransition,
|
executeAfterTransition,
|
||||||
findShadowRoot,
|
findShadowRoot,
|
||||||
|
getDocument,
|
||||||
getElement,
|
getElement,
|
||||||
getElementFromSelector,
|
getElementFromSelector,
|
||||||
getjQuery,
|
getjQuery,
|
||||||
@ -324,6 +341,7 @@ export {
|
|||||||
getSelectorFromElement,
|
getSelectorFromElement,
|
||||||
getTransitionDurationFromElement,
|
getTransitionDurationFromElement,
|
||||||
getUID,
|
getUID,
|
||||||
|
getWindow,
|
||||||
isDisabled,
|
isDisabled,
|
||||||
isElement,
|
isElement,
|
||||||
isRTL,
|
isRTL,
|
||||||
|
@ -5,6 +5,8 @@
|
|||||||
* --------------------------------------------------------------------------
|
* --------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
import { getWindow } from './index'
|
||||||
|
|
||||||
const uriAttributes = new Set([
|
const uriAttributes = new Set([
|
||||||
'background',
|
'background',
|
||||||
'cite',
|
'cite',
|
||||||
@ -91,7 +93,8 @@ export function sanitizeHtml(unsafeHtml, allowList, sanitizeFunction) {
|
|||||||
return sanitizeFunction(unsafeHtml)
|
return sanitizeFunction(unsafeHtml)
|
||||||
}
|
}
|
||||||
|
|
||||||
const domParser = new window.DOMParser()
|
const windowRef = getWindow()
|
||||||
|
const domParser = new windowRef.DOMParser()
|
||||||
const createdDocument = domParser.parseFromString(unsafeHtml, 'text/html')
|
const createdDocument = domParser.parseFromString(unsafeHtml, 'text/html')
|
||||||
const elements = [].concat(...createdDocument.body.querySelectorAll('*'))
|
const elements = [].concat(...createdDocument.body.querySelectorAll('*'))
|
||||||
|
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
|
|
||||||
import SelectorEngine from '../dom/selector-engine'
|
import SelectorEngine from '../dom/selector-engine'
|
||||||
import Manipulator from '../dom/manipulator'
|
import Manipulator from '../dom/manipulator'
|
||||||
import { isElement } from './index'
|
import { isElement, getDocument, getWindow } from './index'
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constants
|
* Constants
|
||||||
@ -24,14 +24,15 @@ const PROPERTY_MARGIN = 'margin-right'
|
|||||||
|
|
||||||
class ScrollBarHelper {
|
class ScrollBarHelper {
|
||||||
constructor() {
|
constructor() {
|
||||||
this._element = document.body
|
this._element = getDocument().body
|
||||||
|
this._window = getWindow()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Public
|
// Public
|
||||||
getWidth() {
|
getWidth() {
|
||||||
// https://developer.mozilla.org/en-US/docs/Web/API/Window/innerWidth#usage_notes
|
// https://developer.mozilla.org/en-US/docs/Web/API/Window/innerWidth#usage_notes
|
||||||
const documentWidth = document.documentElement.clientWidth
|
const documentWidth = document.documentElement.clientWidth
|
||||||
return Math.abs(window.innerWidth - documentWidth)
|
return Math.abs(this._window.innerWidth - documentWidth)
|
||||||
}
|
}
|
||||||
|
|
||||||
hide() {
|
hide() {
|
||||||
@ -64,12 +65,12 @@ class ScrollBarHelper {
|
|||||||
_setElementAttributes(selector, styleProperty, callback) {
|
_setElementAttributes(selector, styleProperty, callback) {
|
||||||
const scrollbarWidth = this.getWidth()
|
const scrollbarWidth = this.getWidth()
|
||||||
const manipulationCallBack = element => {
|
const manipulationCallBack = element => {
|
||||||
if (element !== this._element && window.innerWidth > element.clientWidth + scrollbarWidth) {
|
if (element !== this._element && this._window.innerWidth > element.clientWidth + scrollbarWidth) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
this._saveInitialAttribute(element, styleProperty)
|
this._saveInitialAttribute(element, styleProperty)
|
||||||
const calculatedValue = window.getComputedStyle(element).getPropertyValue(styleProperty)
|
const calculatedValue = this._window.getComputedStyle(element).getPropertyValue(styleProperty)
|
||||||
element.style.setProperty(styleProperty, `${callback(Number.parseFloat(calculatedValue))}px`)
|
element.style.setProperty(styleProperty, `${callback(Number.parseFloat(calculatedValue))}px`)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
|
|
||||||
import Config from './config'
|
import Config from './config'
|
||||||
import EventHandler from '../dom/event-handler'
|
import EventHandler from '../dom/event-handler'
|
||||||
import { execute } from './index'
|
import { execute, getDocument, getWindow } from './index'
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constants
|
* Constants
|
||||||
@ -52,7 +52,7 @@ class Swipe extends Config {
|
|||||||
|
|
||||||
this._config = this._getConfig(config)
|
this._config = this._getConfig(config)
|
||||||
this._deltaX = 0
|
this._deltaX = 0
|
||||||
this._supportPointerEvents = Boolean(window.PointerEvent)
|
this._supportPointerEvents = Boolean(getWindow().PointerEvent)
|
||||||
this._initEvents()
|
this._initEvents()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -139,7 +139,7 @@ class Swipe extends Config {
|
|||||||
|
|
||||||
// Static
|
// Static
|
||||||
static isSupported() {
|
static isSupported() {
|
||||||
return 'ontouchstart' in document.documentElement || navigator.maxTouchPoints > 0
|
return 'ontouchstart' in getDocument().documentElement || navigator.maxTouchPoints > 0
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
import Tooltip from '../../dist/tooltip'
|
import Tooltip from '../../dist/tooltip'
|
||||||
import '../../dist/carousel'
|
import '../../dist/carousel'
|
||||||
|
|
||||||
|
// eslint-disable-next-line ssr-friendly/no-dom-globals-in-module-scope
|
||||||
window.addEventListener('load', () => {
|
window.addEventListener('load', () => {
|
||||||
[].concat(...document.querySelectorAll('[data-bs-toggle="tooltip"]'))
|
[].concat(...document.querySelectorAll('[data-bs-toggle="tooltip"]'))
|
||||||
.map(tooltipNode => new Tooltip(tooltipNode))
|
.map(tooltipNode => new Tooltip(tooltipNode))
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
import { Tooltip } from '../../../dist/js/bootstrap.esm.js'
|
import { Tooltip } from '../../../dist/js/bootstrap.esm.js'
|
||||||
|
|
||||||
|
// eslint-disable-next-line ssr-friendly/no-dom-globals-in-module-scope
|
||||||
window.addEventListener('load', () => {
|
window.addEventListener('load', () => {
|
||||||
[].concat(...document.querySelectorAll('[data-bs-toggle="tooltip"]'))
|
[].concat(...document.querySelectorAll('[data-bs-toggle="tooltip"]'))
|
||||||
.map(tooltipNode => new Tooltip(tooltipNode))
|
.map(tooltipNode => new Tooltip(tooltipNode))
|
||||||
|
66
package-lock.json
generated
66
package-lock.json
generated
@ -24,6 +24,7 @@
|
|||||||
"eslint": "^8.8.0",
|
"eslint": "^8.8.0",
|
||||||
"eslint-config-xo": "^0.39.0",
|
"eslint-config-xo": "^0.39.0",
|
||||||
"eslint-plugin-import": "^2.25.4",
|
"eslint-plugin-import": "^2.25.4",
|
||||||
|
"eslint-plugin-ssr-friendly": "^1.0.5",
|
||||||
"eslint-plugin-unicorn": "^40.1.0",
|
"eslint-plugin-unicorn": "^40.1.0",
|
||||||
"find-unused-sass-variables": "^3.1.0",
|
"find-unused-sass-variables": "^3.1.0",
|
||||||
"globby": "^11.0.4",
|
"globby": "^11.0.4",
|
||||||
@ -4319,6 +4320,45 @@
|
|||||||
"integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=",
|
"integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"node_modules/eslint-plugin-ssr-friendly": {
|
||||||
|
"version": "1.0.5",
|
||||||
|
"resolved": "https://registry.npmjs.org/eslint-plugin-ssr-friendly/-/eslint-plugin-ssr-friendly-1.0.5.tgz",
|
||||||
|
"integrity": "sha512-F1vKfzhOnrIXhcx91Y3r1x8vjJAoCex25PUgYErOe6q95T4KuCTz6+LgGQ4TTvhBdCfNqu1U0krAHe3UNuEOqg==",
|
||||||
|
"dev": true,
|
||||||
|
"dependencies": {
|
||||||
|
"globals": "^13.2.0"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"eslint": ">=0.8.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/eslint-plugin-ssr-friendly/node_modules/globals": {
|
||||||
|
"version": "13.12.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/globals/-/globals-13.12.0.tgz",
|
||||||
|
"integrity": "sha512-uS8X6lSKN2JumVoXrbUz+uG4BYG+eiawqm3qFcT7ammfbUHeCBoJMlHcec/S3krSk73/AE/f0szYFmgAA3kYZg==",
|
||||||
|
"dev": true,
|
||||||
|
"dependencies": {
|
||||||
|
"type-fest": "^0.20.2"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=8"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/sindresorhus"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/eslint-plugin-ssr-friendly/node_modules/type-fest": {
|
||||||
|
"version": "0.20.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz",
|
||||||
|
"integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==",
|
||||||
|
"dev": true,
|
||||||
|
"engines": {
|
||||||
|
"node": ">=10"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/sindresorhus"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/eslint-plugin-unicorn": {
|
"node_modules/eslint-plugin-unicorn": {
|
||||||
"version": "40.1.0",
|
"version": "40.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/eslint-plugin-unicorn/-/eslint-plugin-unicorn-40.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/eslint-plugin-unicorn/-/eslint-plugin-unicorn-40.1.0.tgz",
|
||||||
@ -14030,6 +14070,32 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"eslint-plugin-ssr-friendly": {
|
||||||
|
"version": "1.0.5",
|
||||||
|
"resolved": "https://registry.npmjs.org/eslint-plugin-ssr-friendly/-/eslint-plugin-ssr-friendly-1.0.5.tgz",
|
||||||
|
"integrity": "sha512-F1vKfzhOnrIXhcx91Y3r1x8vjJAoCex25PUgYErOe6q95T4KuCTz6+LgGQ4TTvhBdCfNqu1U0krAHe3UNuEOqg==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"globals": "^13.2.0"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"globals": {
|
||||||
|
"version": "13.12.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/globals/-/globals-13.12.0.tgz",
|
||||||
|
"integrity": "sha512-uS8X6lSKN2JumVoXrbUz+uG4BYG+eiawqm3qFcT7ammfbUHeCBoJMlHcec/S3krSk73/AE/f0szYFmgAA3kYZg==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"type-fest": "^0.20.2"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"type-fest": {
|
||||||
|
"version": "0.20.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz",
|
||||||
|
"integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==",
|
||||||
|
"dev": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"eslint-plugin-unicorn": {
|
"eslint-plugin-unicorn": {
|
||||||
"version": "40.1.0",
|
"version": "40.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/eslint-plugin-unicorn/-/eslint-plugin-unicorn-40.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/eslint-plugin-unicorn/-/eslint-plugin-unicorn-40.1.0.tgz",
|
||||||
|
@ -113,6 +113,7 @@
|
|||||||
"eslint": "^8.8.0",
|
"eslint": "^8.8.0",
|
||||||
"eslint-config-xo": "^0.39.0",
|
"eslint-config-xo": "^0.39.0",
|
||||||
"eslint-plugin-import": "^2.25.4",
|
"eslint-plugin-import": "^2.25.4",
|
||||||
|
"eslint-plugin-ssr-friendly": "^1.0.5",
|
||||||
"eslint-plugin-unicorn": "^40.1.0",
|
"eslint-plugin-unicorn": "^40.1.0",
|
||||||
"find-unused-sass-variables": "^3.1.0",
|
"find-unused-sass-variables": "^3.1.0",
|
||||||
"globby": "^11.0.4",
|
"globby": "^11.0.4",
|
||||||
|
Loading…
x
Reference in New Issue
Block a user