@unlk/keymaster 1.4.6 → 1.4.7
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 +10 -0
- package/dist/css/keymaster.css +1 -1
- package/dist/css/keymaster.css.map +1 -1
- package/dist/css/keymaster.min.css +1 -1
- 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/_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) {
|
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.7" !default;
|