@coreui/coreui 4.0.2 → 4.1.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.md +5 -8
- package/dist/css/coreui-grid.css +255 -206
- package/dist/css/coreui-grid.css.map +1 -1
- package/dist/css/coreui-grid.min.css +2 -2
- package/dist/css/coreui-grid.min.css.map +1 -1
- package/dist/css/coreui-grid.rtl.css +256 -207
- package/dist/css/coreui-grid.rtl.css.map +1 -1
- package/dist/css/coreui-grid.rtl.min.css +3 -3
- package/dist/css/coreui-grid.rtl.min.css.map +1 -1
- package/dist/css/coreui-reboot.css +63 -8
- package/dist/css/coreui-reboot.css.map +1 -1
- package/dist/css/coreui-reboot.min.css +2 -2
- package/dist/css/coreui-reboot.min.css.map +1 -1
- package/dist/css/coreui-reboot.rtl.css +64 -9
- package/dist/css/coreui-reboot.rtl.css.map +1 -1
- package/dist/css/coreui-reboot.rtl.min.css +3 -3
- package/dist/css/coreui-reboot.rtl.min.css.map +1 -1
- package/dist/css/coreui-utilities.css +181 -81
- package/dist/css/coreui-utilities.css.map +1 -1
- package/dist/css/coreui-utilities.min.css +2 -2
- package/dist/css/coreui-utilities.min.css.map +1 -1
- package/dist/css/coreui-utilities.rtl.css +182 -82
- package/dist/css/coreui-utilities.rtl.css.map +1 -1
- package/dist/css/coreui-utilities.rtl.min.css +3 -3
- package/dist/css/coreui-utilities.rtl.min.css.map +1 -1
- package/dist/css/coreui.css +725 -350
- package/dist/css/coreui.css.map +1 -1
- package/dist/css/coreui.min.css +2 -2
- package/dist/css/coreui.min.css.map +1 -1
- package/dist/css/coreui.rtl.css +733 -373
- package/dist/css/coreui.rtl.css.map +1 -1
- package/dist/css/coreui.rtl.min.css +3 -3
- package/dist/css/coreui.rtl.min.css.map +1 -1
- package/dist/js/coreui.bundle.js +782 -704
- package/dist/js/coreui.bundle.js.map +1 -1
- package/dist/js/coreui.bundle.min.js +2 -2
- package/dist/js/coreui.bundle.min.js.map +1 -1
- package/dist/js/coreui.esm.js +663 -611
- package/dist/js/coreui.esm.js.map +1 -1
- package/dist/js/coreui.esm.min.js +2 -2
- package/dist/js/coreui.esm.min.js.map +1 -1
- package/dist/js/coreui.js +673 -623
- package/dist/js/coreui.js.map +1 -1
- package/dist/js/coreui.min.js +2 -2
- package/dist/js/coreui.min.js.map +1 -1
- package/js/dist/alert.js +81 -48
- package/js/dist/alert.js.map +1 -1
- package/js/dist/base-component.js +25 -17
- package/js/dist/base-component.js.map +1 -1
- package/js/dist/button.js +22 -12
- package/js/dist/button.js.map +1 -1
- package/js/dist/carousel.js +69 -44
- package/js/dist/carousel.js.map +1 -1
- package/js/dist/collapse.js +117 -131
- package/js/dist/collapse.js.map +1 -1
- package/js/dist/dom/data.js +5 -5
- package/js/dist/dom/data.js.map +1 -1
- package/js/dist/dom/event-handler.js +14 -5
- package/js/dist/dom/event-handler.js.map +1 -1
- package/js/dist/dom/manipulator.js +6 -6
- package/js/dist/dom/manipulator.js.map +1 -1
- package/js/dist/dom/selector-engine.js +53 -8
- package/js/dist/dom/selector-engine.js.map +1 -1
- package/js/dist/dropdown.js +99 -106
- package/js/dist/dropdown.js.map +1 -1
- package/js/dist/modal.js +244 -87
- package/js/dist/modal.js.map +1 -1
- package/js/dist/offcanvas.js +205 -56
- package/js/dist/offcanvas.js.map +1 -1
- package/js/dist/popover.js +28 -58
- package/js/dist/popover.js.map +1 -1
- package/js/dist/scrollspy.js +40 -30
- package/js/dist/scrollspy.js.map +1 -1
- package/js/dist/tab.js +44 -22
- package/js/dist/tab.js.map +1 -1
- package/js/dist/toast.js +127 -29
- package/js/dist/toast.js.map +1 -1
- package/js/dist/tooltip.js +122 -104
- package/js/dist/tooltip.js.map +1 -1
- package/js/src/alert.js +21 -47
- package/js/src/base-component.js +3 -3
- package/js/src/button.js +1 -1
- package/js/src/carousel.js +9 -4
- package/js/src/collapse.js +66 -119
- package/js/src/dom/data.js +1 -1
- package/js/src/dom/event-handler.js +1 -2
- package/js/src/dom/manipulator.js +3 -3
- package/js/src/dom/selector-engine.js +18 -1
- package/js/src/dropdown.js +53 -68
- package/js/src/modal.js +24 -35
- package/js/src/navigation.js +6 -4
- package/js/src/offcanvas.js +16 -18
- package/js/src/popover.js +7 -49
- package/js/src/scrollspy.js +1 -1
- package/js/src/sidebar.js +6 -4
- package/js/src/tab.js +1 -1
- package/js/src/toast.js +11 -11
- package/js/src/tooltip.js +66 -50
- package/js/src/util/backdrop.js +6 -5
- package/js/src/util/component-functions.js +34 -0
- package/js/src/util/focustrap.js +105 -0
- package/js/src/util/index.js +14 -5
- package/js/src/util/sanitizer.js +21 -22
- package/js/src/util/scrollbar.js +1 -1
- package/package.json +47 -44
- package/scss/_buttons.scss +1 -2
- package/scss/_card.scss +2 -1
- package/scss/_dropdown.scss +1 -1
- package/scss/_functions.scss +51 -12
- package/scss/_grid.scss +0 -23
- package/scss/_helpers.scss +2 -0
- package/scss/_mixins.scss +1 -0
- package/scss/_modal.scss +1 -11
- package/scss/_navbar.scss +30 -1
- package/scss/_offcanvas.scss +6 -2
- package/scss/_placeholders.scss +51 -0
- package/scss/_reboot.scss +12 -8
- package/scss/_root.scss +36 -7
- package/scss/_tables.scss +9 -5
- package/scss/_toasts.scss +2 -2
- package/scss/_transitions.scss +6 -0
- package/scss/_utilities.scss +31 -8
- package/scss/_variables.scss +184 -12
- package/scss/coreui-grid.rtl.scss +1 -1
- package/scss/coreui-grid.scss +3 -1
- package/scss/coreui-reboot.rtl.scss +1 -1
- package/scss/coreui-reboot.scss +2 -4
- package/scss/coreui-utilities.rtl.scss +1 -1
- package/scss/coreui-utilities.scss +1 -1
- package/scss/coreui.rtl.scss +1 -1
- package/scss/coreui.scss +2 -1
- package/scss/forms/_form-control.scss +1 -1
- package/scss/forms/_form-select.scss +2 -0
- package/scss/helpers/_stacks.scss +15 -0
- package/scss/helpers/_vr.scss +8 -0
- package/scss/mixins/_backdrop.scss +14 -0
- package/scss/mixins/_grid.scss +29 -10
- package/scss/mixins/_ltr-rtl.scss +21 -0
- package/scss/mixins/_utilities.scss +26 -26
- package/scss/mixins/_visually-hidden.scss +1 -1
- package/scss/sidebar/_sidebar.scss +22 -16
package/js/src/tooltip.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* --------------------------------------------------------------------------
|
|
3
|
-
* CoreUI (v4.0
|
|
3
|
+
* CoreUI (v4.1.0): tooltip.js
|
|
4
4
|
* Licensed under MIT (https://coreui.io/license)
|
|
5
5
|
*
|
|
6
6
|
* This component is a modified version of the Bootstrap's tooltip.js
|
|
@@ -20,10 +20,7 @@ import {
|
|
|
20
20
|
noop,
|
|
21
21
|
typeCheckConfig
|
|
22
22
|
} from './util/index'
|
|
23
|
-
import {
|
|
24
|
-
DefaultAllowlist,
|
|
25
|
-
sanitizeHtml
|
|
26
|
-
} from './util/sanitizer'
|
|
23
|
+
import { DefaultAllowlist, sanitizeHtml } from './util/sanitizer'
|
|
27
24
|
import Data from './dom/data'
|
|
28
25
|
import EventHandler from './dom/event-handler'
|
|
29
26
|
import Manipulator from './dom/manipulator'
|
|
@@ -40,7 +37,6 @@ const NAME = 'tooltip'
|
|
|
40
37
|
const DATA_KEY = 'coreui.tooltip'
|
|
41
38
|
const EVENT_KEY = `.${DATA_KEY}`
|
|
42
39
|
const CLASS_PREFIX = 'bs-tooltip'
|
|
43
|
-
const BSCLS_PREFIX_REGEX = new RegExp(`(^|\\s)${CLASS_PREFIX}\\S+`, 'g')
|
|
44
40
|
const DISALLOWED_ATTRIBUTES = new Set(['sanitize', 'allowList', 'sanitizeFn'])
|
|
45
41
|
|
|
46
42
|
const DefaultType = {
|
|
@@ -115,6 +111,9 @@ const HOVER_STATE_SHOW = 'show'
|
|
|
115
111
|
const HOVER_STATE_OUT = 'out'
|
|
116
112
|
|
|
117
113
|
const SELECTOR_TOOLTIP_INNER = '.tooltip-inner'
|
|
114
|
+
const SELECTOR_MODAL = `.${CLASS_NAME_MODAL}`
|
|
115
|
+
|
|
116
|
+
const EVENT_MODAL_HIDE = 'hide.coreui.modal'
|
|
118
117
|
|
|
119
118
|
const TRIGGER_HOVER = 'hover'
|
|
120
119
|
const TRIGGER_FOCUS = 'focus'
|
|
@@ -209,16 +208,13 @@ class Tooltip extends BaseComponent {
|
|
|
209
208
|
dispose() {
|
|
210
209
|
clearTimeout(this._timeout)
|
|
211
210
|
|
|
212
|
-
EventHandler.off(this._element.closest(
|
|
211
|
+
EventHandler.off(this._element.closest(SELECTOR_MODAL), EVENT_MODAL_HIDE, this._hideModalHandler)
|
|
213
212
|
|
|
214
213
|
if (this.tip) {
|
|
215
214
|
this.tip.remove()
|
|
216
215
|
}
|
|
217
216
|
|
|
218
|
-
|
|
219
|
-
this._popper.destroy()
|
|
220
|
-
}
|
|
221
|
-
|
|
217
|
+
this._disposePopper()
|
|
222
218
|
super.dispose()
|
|
223
219
|
}
|
|
224
220
|
|
|
@@ -241,14 +237,20 @@ class Tooltip extends BaseComponent {
|
|
|
241
237
|
return
|
|
242
238
|
}
|
|
243
239
|
|
|
240
|
+
// A trick to recreate a tooltip in case a new title is given by using the NOT documented `data-coreui-original-title`
|
|
241
|
+
// This will be removed later in favor of a `setContent` method
|
|
242
|
+
if (this.constructor.NAME === 'tooltip' && this.tip && this.getTitle() !== this.tip.querySelector(SELECTOR_TOOLTIP_INNER).innerHTML) {
|
|
243
|
+
this._disposePopper()
|
|
244
|
+
this.tip.remove()
|
|
245
|
+
this.tip = null
|
|
246
|
+
}
|
|
247
|
+
|
|
244
248
|
const tip = this.getTipElement()
|
|
245
249
|
const tipId = getUID(this.constructor.NAME)
|
|
246
250
|
|
|
247
251
|
tip.setAttribute('id', tipId)
|
|
248
252
|
this._element.setAttribute('aria-describedby', tipId)
|
|
249
253
|
|
|
250
|
-
this.setContent()
|
|
251
|
-
|
|
252
254
|
if (this._config.animation) {
|
|
253
255
|
tip.classList.add(CLASS_NAME_FADE)
|
|
254
256
|
}
|
|
@@ -264,7 +266,7 @@ class Tooltip extends BaseComponent {
|
|
|
264
266
|
Data.set(tip, this.constructor.DATA_KEY, this)
|
|
265
267
|
|
|
266
268
|
if (!this._element.ownerDocument.documentElement.contains(this.tip)) {
|
|
267
|
-
container.
|
|
269
|
+
container.append(tip)
|
|
268
270
|
EventHandler.trigger(this._element, this.constructor.Event.INSERTED)
|
|
269
271
|
}
|
|
270
272
|
|
|
@@ -276,7 +278,7 @@ class Tooltip extends BaseComponent {
|
|
|
276
278
|
|
|
277
279
|
tip.classList.add(CLASS_NAME_SHOW)
|
|
278
280
|
|
|
279
|
-
const customClass =
|
|
281
|
+
const customClass = this._resolvePossibleFunction(this._config.customClass)
|
|
280
282
|
if (customClass) {
|
|
281
283
|
tip.classList.add(...customClass.split(' '))
|
|
282
284
|
}
|
|
@@ -325,10 +327,7 @@ class Tooltip extends BaseComponent {
|
|
|
325
327
|
this._element.removeAttribute('aria-describedby')
|
|
326
328
|
EventHandler.trigger(this._element, this.constructor.Event.HIDDEN)
|
|
327
329
|
|
|
328
|
-
|
|
329
|
-
this._popper.destroy()
|
|
330
|
-
this._popper = null
|
|
331
|
-
}
|
|
330
|
+
this._disposePopper()
|
|
332
331
|
}
|
|
333
332
|
|
|
334
333
|
const hideEvent = EventHandler.trigger(this._element, this.constructor.Event.HIDE)
|
|
@@ -374,14 +373,28 @@ class Tooltip extends BaseComponent {
|
|
|
374
373
|
const element = document.createElement('div')
|
|
375
374
|
element.innerHTML = this._config.template
|
|
376
375
|
|
|
377
|
-
|
|
376
|
+
const tip = element.children[0]
|
|
377
|
+
this.setContent(tip)
|
|
378
|
+
tip.classList.remove(CLASS_NAME_FADE, CLASS_NAME_SHOW)
|
|
379
|
+
|
|
380
|
+
this.tip = tip
|
|
378
381
|
return this.tip
|
|
379
382
|
}
|
|
380
383
|
|
|
381
|
-
setContent() {
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
384
|
+
setContent(tip) {
|
|
385
|
+
this._sanitizeAndSetContent(tip, this.getTitle(), SELECTOR_TOOLTIP_INNER)
|
|
386
|
+
}
|
|
387
|
+
|
|
388
|
+
_sanitizeAndSetContent(template, content, selector) {
|
|
389
|
+
const templateElement = SelectorEngine.findOne(selector, template)
|
|
390
|
+
|
|
391
|
+
if (!content && templateElement) {
|
|
392
|
+
templateElement.remove()
|
|
393
|
+
return
|
|
394
|
+
}
|
|
395
|
+
|
|
396
|
+
// we use append for html objects to maintain js events
|
|
397
|
+
this.setElementContent(templateElement, content)
|
|
385
398
|
}
|
|
386
399
|
|
|
387
400
|
setElementContent(element, content) {
|
|
@@ -396,7 +409,7 @@ class Tooltip extends BaseComponent {
|
|
|
396
409
|
if (this._config.html) {
|
|
397
410
|
if (content.parentNode !== element) {
|
|
398
411
|
element.innerHTML = ''
|
|
399
|
-
element.
|
|
412
|
+
element.append(content)
|
|
400
413
|
}
|
|
401
414
|
} else {
|
|
402
415
|
element.textContent = content.textContent
|
|
@@ -417,15 +430,9 @@ class Tooltip extends BaseComponent {
|
|
|
417
430
|
}
|
|
418
431
|
|
|
419
432
|
getTitle() {
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
if (!title) {
|
|
423
|
-
title = typeof this._config.title === 'function' ?
|
|
424
|
-
this._config.title.call(this._element) :
|
|
425
|
-
this._config.title
|
|
426
|
-
}
|
|
433
|
+
const title = this._element.getAttribute('data-coreui-original-title') || this._config.title
|
|
427
434
|
|
|
428
|
-
return title
|
|
435
|
+
return this._resolvePossibleFunction(title)
|
|
429
436
|
}
|
|
430
437
|
|
|
431
438
|
updateAttachment(attachment) {
|
|
@@ -443,15 +450,7 @@ class Tooltip extends BaseComponent {
|
|
|
443
450
|
// Private
|
|
444
451
|
|
|
445
452
|
_initializeOnDelegatedTarget(event, context) {
|
|
446
|
-
|
|
447
|
-
context = context || Data.get(event.delegateTarget, dataKey)
|
|
448
|
-
|
|
449
|
-
if (!context) {
|
|
450
|
-
context = new this.constructor(event.delegateTarget, this._getDelegateConfig())
|
|
451
|
-
Data.set(event.delegateTarget, dataKey, context)
|
|
452
|
-
}
|
|
453
|
-
|
|
454
|
-
return context
|
|
453
|
+
return context || this.constructor.getOrCreateInstance(event.delegateTarget, this._getDelegateConfig())
|
|
455
454
|
}
|
|
456
455
|
|
|
457
456
|
_getOffset() {
|
|
@@ -468,6 +467,10 @@ class Tooltip extends BaseComponent {
|
|
|
468
467
|
return offset
|
|
469
468
|
}
|
|
470
469
|
|
|
470
|
+
_resolvePossibleFunction(content) {
|
|
471
|
+
return typeof content === 'function' ? content.call(this._element) : content
|
|
472
|
+
}
|
|
473
|
+
|
|
471
474
|
_getPopperConfig(attachment) {
|
|
472
475
|
const defaultBsPopperConfig = {
|
|
473
476
|
placement: attachment,
|
|
@@ -517,7 +520,7 @@ class Tooltip extends BaseComponent {
|
|
|
517
520
|
}
|
|
518
521
|
|
|
519
522
|
_addAttachmentClass(attachment) {
|
|
520
|
-
this.getTipElement().classList.add(`${
|
|
523
|
+
this.getTipElement().classList.add(`${this._getBasicClassPrefix()}-${this.updateAttachment(attachment)}`)
|
|
521
524
|
}
|
|
522
525
|
|
|
523
526
|
_getAttachment(placement) {
|
|
@@ -549,7 +552,7 @@ class Tooltip extends BaseComponent {
|
|
|
549
552
|
}
|
|
550
553
|
}
|
|
551
554
|
|
|
552
|
-
EventHandler.on(this._element.closest(
|
|
555
|
+
EventHandler.on(this._element.closest(SELECTOR_MODAL), EVENT_MODAL_HIDE, this._hideModalHandler)
|
|
553
556
|
|
|
554
557
|
if (this._config.selector) {
|
|
555
558
|
this._config = {
|
|
@@ -689,26 +692,32 @@ class Tooltip extends BaseComponent {
|
|
|
689
692
|
_getDelegateConfig() {
|
|
690
693
|
const config = {}
|
|
691
694
|
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
config[key] = this._config[key]
|
|
696
|
-
}
|
|
695
|
+
for (const key in this._config) {
|
|
696
|
+
if (this.constructor.Default[key] !== this._config[key]) {
|
|
697
|
+
config[key] = this._config[key]
|
|
697
698
|
}
|
|
698
699
|
}
|
|
699
700
|
|
|
701
|
+
// In the future can be replaced with:
|
|
702
|
+
// const keysWithDifferentValues = Object.entries(this._config).filter(entry => this.constructor.Default[entry[0]] !== this._config[entry[0]])
|
|
703
|
+
// `Object.fromEntries(keysWithDifferentValues)`
|
|
700
704
|
return config
|
|
701
705
|
}
|
|
702
706
|
|
|
703
707
|
_cleanTipClass() {
|
|
704
708
|
const tip = this.getTipElement()
|
|
705
|
-
const
|
|
709
|
+
const basicClassPrefixRegex = new RegExp(`(^|\\s)${this._getBasicClassPrefix()}\\S+`, 'g')
|
|
710
|
+
const tabClass = tip.getAttribute('class').match(basicClassPrefixRegex)
|
|
706
711
|
if (tabClass !== null && tabClass.length > 0) {
|
|
707
712
|
tabClass.map(token => token.trim())
|
|
708
713
|
.forEach(tClass => tip.classList.remove(tClass))
|
|
709
714
|
}
|
|
710
715
|
}
|
|
711
716
|
|
|
717
|
+
_getBasicClassPrefix() {
|
|
718
|
+
return CLASS_PREFIX
|
|
719
|
+
}
|
|
720
|
+
|
|
712
721
|
_handlePopperPlacementChange(popperData) {
|
|
713
722
|
const { state } = popperData
|
|
714
723
|
|
|
@@ -721,6 +730,13 @@ class Tooltip extends BaseComponent {
|
|
|
721
730
|
this._addAttachmentClass(this._getAttachment(state.placement))
|
|
722
731
|
}
|
|
723
732
|
|
|
733
|
+
_disposePopper() {
|
|
734
|
+
if (this._popper) {
|
|
735
|
+
this._popper.destroy()
|
|
736
|
+
this._popper = null
|
|
737
|
+
}
|
|
738
|
+
}
|
|
739
|
+
|
|
724
740
|
// Static
|
|
725
741
|
|
|
726
742
|
static jQueryInterface(config) {
|
package/js/src/util/backdrop.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* --------------------------------------------------------------------------
|
|
3
|
-
* Bootstrap (v5.
|
|
4
|
-
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/
|
|
3
|
+
* Bootstrap (v5.1.3): util/backdrop.js
|
|
4
|
+
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
|
|
5
5
|
* --------------------------------------------------------------------------
|
|
6
6
|
*/
|
|
7
7
|
|
|
@@ -9,6 +9,7 @@ import EventHandler from '../dom/event-handler'
|
|
|
9
9
|
import { execute, executeAfterTransition, getElement, reflow, typeCheckConfig } from './index'
|
|
10
10
|
|
|
11
11
|
const Default = {
|
|
12
|
+
className: 'modal-backdrop',
|
|
12
13
|
isVisible: true, // if false, we use the backdrop helper without adding any element to the dom
|
|
13
14
|
isAnimated: false,
|
|
14
15
|
rootElement: 'body', // give the choice to place backdrop under different elements
|
|
@@ -16,13 +17,13 @@ const Default = {
|
|
|
16
17
|
}
|
|
17
18
|
|
|
18
19
|
const DefaultType = {
|
|
20
|
+
className: 'string',
|
|
19
21
|
isVisible: 'boolean',
|
|
20
22
|
isAnimated: 'boolean',
|
|
21
23
|
rootElement: '(element|string)',
|
|
22
24
|
clickCallback: '(function|null)'
|
|
23
25
|
}
|
|
24
26
|
const NAME = 'backdrop'
|
|
25
|
-
const CLASS_NAME_BACKDROP = 'modal-backdrop'
|
|
26
27
|
const CLASS_NAME_FADE = 'fade'
|
|
27
28
|
const CLASS_NAME_SHOW = 'show'
|
|
28
29
|
|
|
@@ -73,7 +74,7 @@ class Backdrop {
|
|
|
73
74
|
_getElement() {
|
|
74
75
|
if (!this._element) {
|
|
75
76
|
const backdrop = document.createElement('div')
|
|
76
|
-
backdrop.className =
|
|
77
|
+
backdrop.className = this._config.className
|
|
77
78
|
if (this._config.isAnimated) {
|
|
78
79
|
backdrop.classList.add(CLASS_NAME_FADE)
|
|
79
80
|
}
|
|
@@ -101,7 +102,7 @@ class Backdrop {
|
|
|
101
102
|
return
|
|
102
103
|
}
|
|
103
104
|
|
|
104
|
-
this._config.rootElement.
|
|
105
|
+
this._config.rootElement.append(this._getElement())
|
|
105
106
|
|
|
106
107
|
EventHandler.on(this._getElement(), EVENT_MOUSEDOWN, () => {
|
|
107
108
|
execute(this._config.clickCallback)
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* --------------------------------------------------------------------------
|
|
3
|
+
* Bootstrap (v5.1.3): util/component-functions.js
|
|
4
|
+
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
|
|
5
|
+
* --------------------------------------------------------------------------
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import EventHandler from '../dom/event-handler'
|
|
9
|
+
import { getElementFromSelector, isDisabled } from './index'
|
|
10
|
+
|
|
11
|
+
const enableDismissTrigger = (component, method = 'hide') => {
|
|
12
|
+
const clickEvent = `click.dismiss${component.EVENT_KEY}`
|
|
13
|
+
const name = component.NAME
|
|
14
|
+
|
|
15
|
+
EventHandler.on(document, clickEvent, `[data-coreui-dismiss="${name}"]`, function (event) {
|
|
16
|
+
if (['A', 'AREA'].includes(this.tagName)) {
|
|
17
|
+
event.preventDefault()
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
if (isDisabled(this)) {
|
|
21
|
+
return
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
const target = getElementFromSelector(this) || this.closest(`.${name}`)
|
|
25
|
+
const instance = component.getOrCreateInstance(target)
|
|
26
|
+
|
|
27
|
+
// Method argument is left, for Alert and only, as it doesn't implement the 'hide' method
|
|
28
|
+
instance[method]()
|
|
29
|
+
})
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export {
|
|
33
|
+
enableDismissTrigger
|
|
34
|
+
}
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* --------------------------------------------------------------------------
|
|
3
|
+
* Bootstrap (v5.1.3): util/focustrap.js
|
|
4
|
+
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
|
|
5
|
+
* --------------------------------------------------------------------------
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import EventHandler from '../dom/event-handler'
|
|
9
|
+
import SelectorEngine from '../dom/selector-engine'
|
|
10
|
+
import { typeCheckConfig } from './index'
|
|
11
|
+
|
|
12
|
+
const Default = {
|
|
13
|
+
trapElement: null, // The element to trap focus inside of
|
|
14
|
+
autofocus: true
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
const DefaultType = {
|
|
18
|
+
trapElement: 'element',
|
|
19
|
+
autofocus: 'boolean'
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
const NAME = 'focustrap'
|
|
23
|
+
const DATA_KEY = 'coreui.focustrap'
|
|
24
|
+
const EVENT_KEY = `.${DATA_KEY}`
|
|
25
|
+
const EVENT_FOCUSIN = `focusin${EVENT_KEY}`
|
|
26
|
+
const EVENT_KEYDOWN_TAB = `keydown.tab${EVENT_KEY}`
|
|
27
|
+
|
|
28
|
+
const TAB_KEY = 'Tab'
|
|
29
|
+
const TAB_NAV_FORWARD = 'forward'
|
|
30
|
+
const TAB_NAV_BACKWARD = 'backward'
|
|
31
|
+
|
|
32
|
+
class FocusTrap {
|
|
33
|
+
constructor(config) {
|
|
34
|
+
this._config = this._getConfig(config)
|
|
35
|
+
this._isActive = false
|
|
36
|
+
this._lastTabNavDirection = null
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
activate() {
|
|
40
|
+
const { trapElement, autofocus } = this._config
|
|
41
|
+
|
|
42
|
+
if (this._isActive) {
|
|
43
|
+
return
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
if (autofocus) {
|
|
47
|
+
trapElement.focus()
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
EventHandler.off(document, EVENT_KEY) // guard against infinite focus loop
|
|
51
|
+
EventHandler.on(document, EVENT_FOCUSIN, event => this._handleFocusin(event))
|
|
52
|
+
EventHandler.on(document, EVENT_KEYDOWN_TAB, event => this._handleKeydown(event))
|
|
53
|
+
|
|
54
|
+
this._isActive = true
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
deactivate() {
|
|
58
|
+
if (!this._isActive) {
|
|
59
|
+
return
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
this._isActive = false
|
|
63
|
+
EventHandler.off(document, EVENT_KEY)
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
// Private
|
|
67
|
+
|
|
68
|
+
_handleFocusin(event) {
|
|
69
|
+
const { target } = event
|
|
70
|
+
const { trapElement } = this._config
|
|
71
|
+
|
|
72
|
+
if (target === document || target === trapElement || trapElement.contains(target)) {
|
|
73
|
+
return
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
const elements = SelectorEngine.focusableChildren(trapElement)
|
|
77
|
+
|
|
78
|
+
if (elements.length === 0) {
|
|
79
|
+
trapElement.focus()
|
|
80
|
+
} else if (this._lastTabNavDirection === TAB_NAV_BACKWARD) {
|
|
81
|
+
elements[elements.length - 1].focus()
|
|
82
|
+
} else {
|
|
83
|
+
elements[0].focus()
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
_handleKeydown(event) {
|
|
88
|
+
if (event.key !== TAB_KEY) {
|
|
89
|
+
return
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
this._lastTabNavDirection = event.shiftKey ? TAB_NAV_BACKWARD : TAB_NAV_FORWARD
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
_getConfig(config) {
|
|
96
|
+
config = {
|
|
97
|
+
...Default,
|
|
98
|
+
...(typeof config === 'object' ? config : {})
|
|
99
|
+
}
|
|
100
|
+
typeCheckConfig(NAME, config, DefaultType)
|
|
101
|
+
return config
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
export default FocusTrap
|
package/js/src/util/index.js
CHANGED
|
@@ -1,8 +1,6 @@
|
|
|
1
|
-
import SelectorEngine from '../dom/selector-engine'
|
|
2
|
-
|
|
3
1
|
/**
|
|
4
2
|
* --------------------------------------------------------------------------
|
|
5
|
-
* CoreUI (v4.0
|
|
3
|
+
* CoreUI (v4.1.0): alert.js
|
|
6
4
|
* Licensed under MIT (https://coreui.io/license)
|
|
7
5
|
*
|
|
8
6
|
* This component is a modified version of the Bootstrap's util/index.js
|
|
@@ -123,7 +121,7 @@ const getElement = obj => {
|
|
|
123
121
|
}
|
|
124
122
|
|
|
125
123
|
if (typeof obj === 'string' && obj.length > 0) {
|
|
126
|
-
return
|
|
124
|
+
return document.querySelector(obj)
|
|
127
125
|
}
|
|
128
126
|
|
|
129
127
|
return null
|
|
@@ -192,7 +190,18 @@ const findShadowRoot = element => {
|
|
|
192
190
|
|
|
193
191
|
const noop = () => {}
|
|
194
192
|
|
|
195
|
-
|
|
193
|
+
/**
|
|
194
|
+
* Trick to restart an element's animation
|
|
195
|
+
*
|
|
196
|
+
* @param {HTMLElement} element
|
|
197
|
+
* @return void
|
|
198
|
+
*
|
|
199
|
+
* @see https://www.charistheo.io/blog/2021/02/restart-a-css-animation-with-javascript/#restarting-a-css-animation
|
|
200
|
+
*/
|
|
201
|
+
const reflow = element => {
|
|
202
|
+
// eslint-disable-next-line no-unused-expressions
|
|
203
|
+
element.offsetHeight
|
|
204
|
+
}
|
|
196
205
|
|
|
197
206
|
const getjQuery = () => {
|
|
198
207
|
const { jQuery } = window
|
package/js/src/util/sanitizer.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* --------------------------------------------------------------------------
|
|
3
|
-
* CoreUI (v4.0
|
|
3
|
+
* CoreUI (v4.1.0): alert.js
|
|
4
4
|
* Licensed under MIT (https://coreui.io/license)
|
|
5
5
|
*
|
|
6
6
|
* This component is a modified version of the Bootstrap's util/sanitizer.js
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
* --------------------------------------------------------------------------
|
|
9
9
|
*/
|
|
10
10
|
|
|
11
|
-
const
|
|
11
|
+
const uriAttributes = new Set([
|
|
12
12
|
'background',
|
|
13
13
|
'cite',
|
|
14
14
|
'href',
|
|
@@ -24,33 +24,33 @@ const ARIA_ATTRIBUTE_PATTERN = /^aria-[\w-]*$/i
|
|
|
24
24
|
/**
|
|
25
25
|
* A pattern that recognizes a commonly useful subset of URLs that are safe.
|
|
26
26
|
*
|
|
27
|
-
* Shoutout to Angular
|
|
27
|
+
* Shoutout to Angular https://github.com/angular/angular/blob/12.2.x/packages/core/src/sanitization/url_sanitizer.ts
|
|
28
28
|
*/
|
|
29
|
-
const SAFE_URL_PATTERN = /^(?:(?:https?|mailto|ftp|tel|file):|[^#&/:?]*(?:[#/?]|$))/i
|
|
29
|
+
const SAFE_URL_PATTERN = /^(?:(?:https?|mailto|ftp|tel|file|sms):|[^#&/:?]*(?:[#/?]|$))/i
|
|
30
30
|
|
|
31
31
|
/**
|
|
32
32
|
* A pattern that matches safe data URLs. Only matches image, video and audio types.
|
|
33
33
|
*
|
|
34
|
-
* Shoutout to Angular
|
|
34
|
+
* Shoutout to Angular https://github.com/angular/angular/blob/12.2.x/packages/core/src/sanitization/url_sanitizer.ts
|
|
35
35
|
*/
|
|
36
36
|
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
|
|
37
37
|
|
|
38
|
-
const allowedAttribute = (
|
|
39
|
-
const
|
|
38
|
+
const allowedAttribute = (attribute, allowedAttributeList) => {
|
|
39
|
+
const attributeName = attribute.nodeName.toLowerCase()
|
|
40
40
|
|
|
41
|
-
if (allowedAttributeList.includes(
|
|
42
|
-
if (
|
|
43
|
-
return Boolean(SAFE_URL_PATTERN.test(
|
|
41
|
+
if (allowedAttributeList.includes(attributeName)) {
|
|
42
|
+
if (uriAttributes.has(attributeName)) {
|
|
43
|
+
return Boolean(SAFE_URL_PATTERN.test(attribute.nodeValue) || DATA_URL_PATTERN.test(attribute.nodeValue))
|
|
44
44
|
}
|
|
45
45
|
|
|
46
46
|
return true
|
|
47
47
|
}
|
|
48
48
|
|
|
49
|
-
const regExp = allowedAttributeList.filter(
|
|
49
|
+
const regExp = allowedAttributeList.filter(attributeRegex => attributeRegex instanceof RegExp)
|
|
50
50
|
|
|
51
51
|
// Check if a regular expression validates the attribute.
|
|
52
52
|
for (let i = 0, len = regExp.length; i < len; i++) {
|
|
53
|
-
if (regExp[i].test(
|
|
53
|
+
if (regExp[i].test(attributeName)) {
|
|
54
54
|
return true
|
|
55
55
|
}
|
|
56
56
|
}
|
|
@@ -103,25 +103,24 @@ export function sanitizeHtml(unsafeHtml, allowList, sanitizeFn) {
|
|
|
103
103
|
|
|
104
104
|
const domParser = new window.DOMParser()
|
|
105
105
|
const createdDocument = domParser.parseFromString(unsafeHtml, 'text/html')
|
|
106
|
-
const allowlistKeys = Object.keys(allowList)
|
|
107
106
|
const elements = [].concat(...createdDocument.body.querySelectorAll('*'))
|
|
108
107
|
|
|
109
108
|
for (let i = 0, len = elements.length; i < len; i++) {
|
|
110
|
-
const
|
|
111
|
-
const
|
|
109
|
+
const element = elements[i]
|
|
110
|
+
const elementName = element.nodeName.toLowerCase()
|
|
112
111
|
|
|
113
|
-
if (!
|
|
114
|
-
|
|
112
|
+
if (!Object.keys(allowList).includes(elementName)) {
|
|
113
|
+
element.remove()
|
|
115
114
|
|
|
116
115
|
continue
|
|
117
116
|
}
|
|
118
117
|
|
|
119
|
-
const attributeList = [].concat(...
|
|
120
|
-
const allowedAttributes = [].concat(allowList['*'] || [], allowList[
|
|
118
|
+
const attributeList = [].concat(...element.attributes)
|
|
119
|
+
const allowedAttributes = [].concat(allowList['*'] || [], allowList[elementName] || [])
|
|
121
120
|
|
|
122
|
-
attributeList.forEach(
|
|
123
|
-
if (!allowedAttribute(
|
|
124
|
-
|
|
121
|
+
attributeList.forEach(attribute => {
|
|
122
|
+
if (!allowedAttribute(attribute, allowedAttributes)) {
|
|
123
|
+
element.removeAttribute(attribute.nodeName)
|
|
125
124
|
}
|
|
126
125
|
})
|
|
127
126
|
}
|
package/js/src/util/scrollbar.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* --------------------------------------------------------------------------
|
|
3
|
-
* Bootstrap (v5.
|
|
3
|
+
* Bootstrap (v5.1.3): util/scrollBar.js
|
|
4
4
|
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
|
|
5
5
|
* --------------------------------------------------------------------------
|
|
6
6
|
*/
|