@unlk/keymaster 1.4.6 → 1.4.8
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/CHANGELOG.md +15 -0
- package/dist/css/keymaster.css +63 -26
- package/dist/css/keymaster.css.map +1 -1
- package/dist/css/keymaster.min.css +2 -2
- package/dist/css/keymaster.min.css.map +1 -1
- package/dist/js/keymaster.js +59 -9
- package/dist/js/keymaster.js.map +1 -1
- package/dist/js/keymaster.min.js +14 -14
- package/dist/js/keymaster.min.js.map +1 -1
- package/js/accordion-scroll.js +43 -0
- package/js/bootstrap.js +1 -0
- package/js/video-modal.js +14 -0
- package/package.json +1 -1
- package/react/index.js +1 -0
- package/react/use-accordion-scroll.js +36 -0
- package/react/use-video-modal.js +17 -6
- package/scss/theme/_accordion.scss +38 -7
- package/scss/theme/_variables-overrides.scss +11 -9
- package/scss/theme/_variables.scss +7 -6
- package/scss/theme/_version.scss +1 -1
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import BaseComponent from 'bootstrap/js/src/base-component.js';
|
|
2
|
+
import EventHandler from 'bootstrap/js/src/dom/event-handler.js';
|
|
3
|
+
import SelectorEngine from 'bootstrap/js/src/dom/selector-engine.js';
|
|
4
|
+
import { defineJQueryPlugin } from 'bootstrap/js/src/util/index.js';
|
|
5
|
+
|
|
6
|
+
const NAME = 'accordionScroll';
|
|
7
|
+
const EVENT_SHOWN = 'shown.bs.collapse';
|
|
8
|
+
const SELECTOR_ACCORDION = '.accordion';
|
|
9
|
+
const SELECTOR_ITEM = '.accordion-item';
|
|
10
|
+
const SELECTOR_HEADER = '.accordion-header';
|
|
11
|
+
|
|
12
|
+
class AccordionScroll extends BaseComponent {
|
|
13
|
+
_onShown(e) {
|
|
14
|
+
const item = e.target.closest(SELECTOR_ITEM);
|
|
15
|
+
if (!item) return;
|
|
16
|
+
|
|
17
|
+
const header = SelectorEngine.findOne(SELECTOR_HEADER, item);
|
|
18
|
+
if (!header) return;
|
|
19
|
+
|
|
20
|
+
const rect = header.getBoundingClientRect();
|
|
21
|
+
if (rect.top < 0) {
|
|
22
|
+
header.scrollIntoView({ behavior: 'smooth', block: 'start' });
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
static get NAME() {
|
|
27
|
+
return NAME;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
static jQueryInterface(config) {
|
|
31
|
+
return this.each(function () {
|
|
32
|
+
AccordionScroll.getOrCreateInstance(this, config);
|
|
33
|
+
});
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
EventHandler.on(document, EVENT_SHOWN, SELECTOR_ACCORDION, function (e) {
|
|
38
|
+
AccordionScroll.getOrCreateInstance(this)._onShown(e);
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
defineJQueryPlugin(AccordionScroll);
|
|
42
|
+
|
|
43
|
+
export default AccordionScroll;
|
package/js/bootstrap.js
CHANGED
|
@@ -14,3 +14,4 @@ export { default as Datepicker } from './datepicker';
|
|
|
14
14
|
export { default as CarouselCaption } from './carousel-caption';
|
|
15
15
|
export { default as CarouselHeight } from './carousel-height';
|
|
16
16
|
export { default as VideoModal } from './video-modal';
|
|
17
|
+
export { default as AccordionScroll } from './accordion-scroll';
|
package/js/video-modal.js
CHANGED
|
@@ -84,6 +84,13 @@ class VideoModal extends BaseComponent {
|
|
|
84
84
|
this._element.dataset.vimeoId = String(vimeoId);
|
|
85
85
|
this._element.__unlkVimeoPlayer = this._vimeoPlayer;
|
|
86
86
|
|
|
87
|
+
this._element.dispatchEvent(
|
|
88
|
+
new CustomEvent('videomodal.ready', {
|
|
89
|
+
bubbles: true,
|
|
90
|
+
detail: { provider: 'vimeo', player: this._vimeoPlayer, videoId: vimeoId }
|
|
91
|
+
})
|
|
92
|
+
);
|
|
93
|
+
|
|
87
94
|
return;
|
|
88
95
|
}
|
|
89
96
|
|
|
@@ -99,6 +106,13 @@ class VideoModal extends BaseComponent {
|
|
|
99
106
|
|
|
100
107
|
this._element.dataset.ytId = youtubeId;
|
|
101
108
|
this._element.__unlkYtPlayer = this._youtubePlayer;
|
|
109
|
+
|
|
110
|
+
this._element.dispatchEvent(
|
|
111
|
+
new CustomEvent('videomodal.ready', {
|
|
112
|
+
bubbles: true,
|
|
113
|
+
detail: { provider: 'youtube', player: this._youtubePlayer, videoId: youtubeId }
|
|
114
|
+
})
|
|
115
|
+
);
|
|
102
116
|
}
|
|
103
117
|
}
|
|
104
118
|
|
package/package.json
CHANGED
package/react/index.js
CHANGED
|
@@ -2,3 +2,4 @@ export { useDatepicker } from './use-datepicker.js';
|
|
|
2
2
|
export { useCarouselCaption } from './use-carousel-caption.js';
|
|
3
3
|
export { useCarouselHeight } from './use-carousel-height.js';
|
|
4
4
|
export { useVideoModal } from './use-video-modal.js';
|
|
5
|
+
export { useAccordionScroll } from './use-accordion-scroll.js';
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { useCallback } from 'react';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Replicates accordion-scroll.js behaviour in React.
|
|
5
|
+
*
|
|
6
|
+
* After an accordion panel finishes opening, scrolls its header into view
|
|
7
|
+
* if it has been pushed above the viewport, replacing the Bootstrap
|
|
8
|
+
* shown.bs.collapse event listener.
|
|
9
|
+
*
|
|
10
|
+
* Usage:
|
|
11
|
+
* const { onEntered } = useAccordionScroll();
|
|
12
|
+
* <Accordion>
|
|
13
|
+
* <Accordion.Item eventKey="0">
|
|
14
|
+
* <Accordion.Header>Header</Accordion.Header>
|
|
15
|
+
* <Accordion.Collapse eventKey="0" onEntered={onEntered}>
|
|
16
|
+
* <Accordion.Body>Content</Accordion.Body>
|
|
17
|
+
* </Accordion.Collapse>
|
|
18
|
+
* </Accordion.Item>
|
|
19
|
+
* </Accordion>
|
|
20
|
+
*/
|
|
21
|
+
export function useAccordionScroll() {
|
|
22
|
+
const onEntered = useCallback((node) => {
|
|
23
|
+
const item = node.closest('.accordion-item');
|
|
24
|
+
if (!item) return;
|
|
25
|
+
|
|
26
|
+
const header = item.querySelector('.accordion-header');
|
|
27
|
+
if (!header) return;
|
|
28
|
+
|
|
29
|
+
const rect = header.getBoundingClientRect();
|
|
30
|
+
if (rect.top < 0) {
|
|
31
|
+
header.scrollIntoView({ behavior: 'smooth', block: 'start' });
|
|
32
|
+
}
|
|
33
|
+
}, []);
|
|
34
|
+
|
|
35
|
+
return { onEntered };
|
|
36
|
+
}
|
package/react/use-video-modal.js
CHANGED
|
@@ -73,8 +73,9 @@ function getVimeoId(url) {
|
|
|
73
73
|
* show.bs.modal / hidden.bs.modal event listeners.
|
|
74
74
|
*
|
|
75
75
|
* @param {object} options
|
|
76
|
-
* @param {string}
|
|
77
|
-
* @param {string}
|
|
76
|
+
* @param {string} [options.youtubeSrc] - YouTube video URL
|
|
77
|
+
* @param {string} [options.vimeoUrl] - Vimeo video URL
|
|
78
|
+
* @param {function} [options.onReady] - Called with { provider, player, videoId } when the player is ready
|
|
78
79
|
*
|
|
79
80
|
* Usage:
|
|
80
81
|
* const { containerRef, onShow, onHide } = useVideoModal({ youtubeSrc: '...' });
|
|
@@ -84,7 +85,7 @@ function getVimeoId(url) {
|
|
|
84
85
|
* </div>
|
|
85
86
|
* </Modal>
|
|
86
87
|
*/
|
|
87
|
-
export function useVideoModal({ youtubeSrc, vimeoUrl } = {}) {
|
|
88
|
+
export function useVideoModal({ youtubeSrc, vimeoUrl, onReady } = {}) {
|
|
88
89
|
const containerRef = useRef(null);
|
|
89
90
|
const players = useRef({ youtube: null, vimeo: null });
|
|
90
91
|
|
|
@@ -95,26 +96,36 @@ export function useVideoModal({ youtubeSrc, vimeoUrl } = {}) {
|
|
|
95
96
|
|
|
96
97
|
if (vimeoUrl) {
|
|
97
98
|
await loadVimeoAPI();
|
|
99
|
+
const vimeoId = getVimeoId(vimeoUrl);
|
|
98
100
|
|
|
99
101
|
players.current.vimeo = new globalThis.Vimeo.Player(container, {
|
|
100
|
-
id:
|
|
102
|
+
id: vimeoId,
|
|
101
103
|
autoplay: true,
|
|
102
104
|
});
|
|
103
105
|
|
|
106
|
+
if (onReady) {
|
|
107
|
+
onReady({ provider: 'vimeo', player: players.current.vimeo, videoId: vimeoId });
|
|
108
|
+
}
|
|
109
|
+
|
|
104
110
|
return;
|
|
105
111
|
}
|
|
106
112
|
|
|
107
113
|
if (youtubeSrc) {
|
|
108
114
|
await loadYouTubeAPI();
|
|
115
|
+
const youtubeId = getYouTubeId(youtubeSrc);
|
|
109
116
|
|
|
110
117
|
const playerDiv = container.querySelector('[data-yt-player]');
|
|
111
118
|
|
|
112
119
|
players.current.youtube = new globalThis.YT.Player(playerDiv, {
|
|
113
|
-
videoId:
|
|
120
|
+
videoId: youtubeId,
|
|
114
121
|
playerVars: { autoplay: 1, rel: 0 },
|
|
115
122
|
});
|
|
123
|
+
|
|
124
|
+
if (onReady) {
|
|
125
|
+
onReady({ provider: 'youtube', player: players.current.youtube, videoId: youtubeId });
|
|
126
|
+
}
|
|
116
127
|
}
|
|
117
|
-
}, [youtubeSrc, vimeoUrl]);
|
|
128
|
+
}, [youtubeSrc, vimeoUrl, onReady]);
|
|
118
129
|
|
|
119
130
|
const onHide = useCallback(() => {
|
|
120
131
|
if (players.current.vimeo) {
|
|
@@ -1,17 +1,38 @@
|
|
|
1
1
|
.accordion {
|
|
2
|
-
--#{$prefix}accordion-box-shadow: #{$accordion-box-shadow};
|
|
3
2
|
@include border-radius(var(--#{$prefix}accordion-border-radius));
|
|
4
|
-
|
|
5
|
-
.accordion-button
|
|
3
|
+
border: 0;
|
|
4
|
+
.accordion-button {
|
|
5
|
+
font-weight: $font-weight-medium;
|
|
6
|
+
&:not(.collapsed) {
|
|
7
|
+
box-shadow: none;
|
|
8
|
+
}
|
|
9
|
+
}
|
|
6
10
|
.accordion-body {
|
|
7
|
-
|
|
11
|
+
padding-top: 0;
|
|
12
|
+
@extend .fs-4;
|
|
13
|
+
}
|
|
14
|
+
.accordion-item {
|
|
15
|
+
border-top: 0;
|
|
16
|
+
border-right: 0;
|
|
17
|
+
border-left: 0;
|
|
18
|
+
}
|
|
19
|
+
:not(.accordion-alt) .accordion-item:last-child {
|
|
20
|
+
border-bottom: 0;
|
|
8
21
|
}
|
|
9
22
|
}
|
|
10
23
|
|
|
24
|
+
.accordion-flush {
|
|
25
|
+
--#{$prefix}accordion-box-shadow: #{$accordion-box-shadow};
|
|
26
|
+
@include box-shadow(var(--#{$prefix}accordion-box-shadow));
|
|
27
|
+
@include padding(0 $spacer 0);
|
|
28
|
+
@include border-radius($border-radius);
|
|
29
|
+
}
|
|
30
|
+
|
|
11
31
|
.accordion-alt {
|
|
12
32
|
--#{$prefix}accordion-alt-bg: #{$accordion-alt-bg};
|
|
13
33
|
--#{$prefix}accordion-alt-btn-bg: #{$accordion-alt-button-bg};
|
|
14
34
|
--#{$prefix}accordion-alt-border-width: #{$accordion-alt-border-width};
|
|
35
|
+
--#{$prefix}accordion-alt-border-active-width: #{$accordion-alt-border-active-width};
|
|
15
36
|
--#{$prefix}accordion-alt-border-color: #{$accordion-alt-border-color};
|
|
16
37
|
--#{$prefix}accordion-alt-border-radius: #{$accordion-alt-border-radius};
|
|
17
38
|
--#{$prefix}accordion-alt-btn-icon-width: #{$accordion-alt-icon-width};
|
|
@@ -23,7 +44,7 @@
|
|
|
23
44
|
|
|
24
45
|
.accordion-button {
|
|
25
46
|
margin-bottom: 0;
|
|
26
|
-
background-color:
|
|
47
|
+
background-color: transparent;
|
|
27
48
|
@include box-shadow(none);
|
|
28
49
|
|
|
29
50
|
i {
|
|
@@ -34,7 +55,6 @@
|
|
|
34
55
|
|
|
35
56
|
&:not(.collapsed) {
|
|
36
57
|
@include box-shadow(none);
|
|
37
|
-
color: var(--#{$prefix}accordion-alt-active-color);
|
|
38
58
|
|
|
39
59
|
&::after {
|
|
40
60
|
background-image: var(--#{$prefix}accordion-alt-btn-active-icon);
|
|
@@ -51,8 +71,19 @@
|
|
|
51
71
|
|
|
52
72
|
> .accordion-item {
|
|
53
73
|
background-color: var(--#{$prefix}accordion-alt-bg);
|
|
54
|
-
border: var(--#{$prefix}accordion-alt-border-width) solid
|
|
74
|
+
border: var(--#{$prefix}accordion-alt-border-width) solid transparent;
|
|
55
75
|
@include border-radius(var(--#{$prefix}accordion-alt-border-radius));
|
|
76
|
+
@include transition(var(--#{$prefix}accordion-transition));
|
|
77
|
+
&:hover {
|
|
78
|
+
border-color: var(--#{$prefix}accordion-alt-border-color);
|
|
79
|
+
}
|
|
80
|
+
&:has(.accordion-collapse.show),
|
|
81
|
+
&:has(.accordion-collapse.collapsing) {
|
|
82
|
+
background-color: $white;
|
|
83
|
+
border-color: var(--#{$prefix}accordion-alt-border-color);
|
|
84
|
+
//stylelint-disable-next-line function-disallowed-list
|
|
85
|
+
box-shadow: 0 0 0 calc(var(--#{$prefix}accordion-alt-border-active-width) - var(--#{$prefix}accordion-alt-border-width)) var(--#{$prefix}accordion-alt-border-color);
|
|
86
|
+
}
|
|
56
87
|
|
|
57
88
|
&:not(:last-child) {
|
|
58
89
|
@include margin-bottom($spacer);
|
|
@@ -393,15 +393,17 @@ $border-radius-xxl: 1.5rem !default;
|
|
|
393
393
|
$blockquote-font-size: $font-size-base * 3.5 !default;
|
|
394
394
|
|
|
395
395
|
// Accordion
|
|
396
|
-
$accordion-bg:
|
|
397
|
-
$accordion-border-
|
|
398
|
-
$accordion-
|
|
399
|
-
$accordion-button-
|
|
400
|
-
$accordion-button-active-
|
|
401
|
-
$accordion-
|
|
402
|
-
$accordion-icon-
|
|
403
|
-
$accordion-
|
|
404
|
-
$accordion-button-
|
|
396
|
+
$accordion-bg: transparent !default;
|
|
397
|
+
$accordion-border-width: .0625rem !default;
|
|
398
|
+
$accordion-border-radius: 0 !default;
|
|
399
|
+
$accordion-button-bg: transparent !default;
|
|
400
|
+
$accordion-button-active-bg: transparent !default;
|
|
401
|
+
$accordion-button-active-color: $body-color !default;
|
|
402
|
+
$accordion-icon-color: $action !default;
|
|
403
|
+
$accordion-icon-active-color: $action !default;
|
|
404
|
+
$accordion-button-icon: url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 22 22' fill='#{$accordion-icon-color}'><path d='M12.6923 1.69231C12.6923 0.75625 11.9361 0 11 0C10.0639 0 9.30769 0.75625 9.30769 1.69231V9.30769H1.69231C0.75625 9.30769 0 10.0639 0 11C0 11.9361 0.75625 12.6923 1.69231 12.6923H9.30769V20.3077C9.30769 21.2438 10.0639 22 11 22C11.9361 22 12.6923 21.2438 12.6923 20.3077V12.6923H20.3077C21.2438 12.6923 22 11.9361 22 11C22 10.0639 21.2438 9.30769 20.3077 9.30769H12.6923V1.69231Z'/></svg>") !default;
|
|
405
|
+
$accordion-button-active-icon: url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 22 25' fill='#{$accordion-icon-color}'><path d='M21.2143 12.5C21.2143 13.3643 20.512 14.0625 19.6428 14.0625H2.35713C1.48794 14.0625 0.785706 13.3643 0.785706 12.5C0.785706 11.6357 1.48794 10.9375 2.35713 10.9375H19.6428C20.512 10.9375 21.2143 11.6357 21.2143 12.5Z'/></svg>") !default;
|
|
406
|
+
$accordion-icon-width: 1rem !default;
|
|
405
407
|
$accordion-button-focus-box-shadow: none !default;
|
|
406
408
|
|
|
407
409
|
// Badges
|
|
@@ -8,13 +8,14 @@ $border-radius-xs: rfs-value(4px) !default;
|
|
|
8
8
|
|
|
9
9
|
// scss-docs-start accordion-variables
|
|
10
10
|
$accordion-box-shadow: $box-shadow !default;
|
|
11
|
-
$accordion-alt-bg: $
|
|
12
|
-
$accordion-alt-border-width: .
|
|
13
|
-
$accordion-alt-border-
|
|
14
|
-
$accordion-alt-
|
|
15
|
-
$accordion-alt-
|
|
11
|
+
$accordion-alt-bg: $action-50 !default;
|
|
12
|
+
$accordion-alt-border-width: .09375rem !default;
|
|
13
|
+
$accordion-alt-border-active-width: .125rem !default;
|
|
14
|
+
$accordion-alt-border-color: $action !default;
|
|
15
|
+
$accordion-alt-button-bg: $action-50 !default;
|
|
16
|
+
$accordion-alt-icon-width: 1rem !default;
|
|
16
17
|
$accordion-alt-border-radius: var(--#{$prefix}border-radius-lg) !default;
|
|
17
|
-
$accordion-alt-button-active-color: var(--#{$prefix}
|
|
18
|
+
$accordion-alt-button-active-color: var(--#{$prefix}action) !default;
|
|
18
19
|
$accordion-alt-button-icon: url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 22 22' fill='#{$accordion-icon-color}'><path d='M12.6923 1.69231C12.6923 0.75625 11.9361 0 11 0C10.0639 0 9.30769 0.75625 9.30769 1.69231V9.30769H1.69231C0.75625 9.30769 0 10.0639 0 11C0 11.9361 0.75625 12.6923 1.69231 12.6923H9.30769V20.3077C9.30769 21.2438 10.0639 22 11 22C11.9361 22 12.6923 21.2438 12.6923 20.3077V12.6923H20.3077C21.2438 12.6923 22 11.9361 22 11C22 10.0639 21.2438 9.30769 20.3077 9.30769H12.6923V1.69231Z'/></svg>") !default;
|
|
19
20
|
$accordion-alt-button-active-icon: url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 22 25' fill='#{$accordion-icon-color}'><path d='M21.2143 12.5C21.2143 13.3643 20.512 14.0625 19.6428 14.0625H2.35713C1.48794 14.0625 0.785706 13.3643 0.785706 12.5C0.785706 11.6357 1.48794 10.9375 2.35713 10.9375H19.6428C20.512 10.9375 21.2143 11.6357 21.2143 12.5Z'/></svg>") !default;
|
|
20
21
|
// scss-docs-end accordion-variables
|
package/scss/theme/_version.scss
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
// GENERATED FILE – do not edit manually
|
|
2
|
-
$km-version: "1.4.
|
|
2
|
+
$km-version: "1.4.8" !default;
|