@unlk/keymaster 1.0.5 → 1.0.6

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.
@@ -1,39 +1,66 @@
1
- import { Carousel } from 'bootstrap';
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';
2
5
 
3
- class CarouselCaption {
4
- constructor(carouselEl) {
5
- if (!carouselEl) {
6
+ const NAME = 'carouselCaption';
7
+ const DATA_KEY = 'bs.carouselCaption';
8
+ const EVENT_SLID = 'slid.bs.carousel';
9
+ const SELECTOR_CAROUSEL = '.carousel';
10
+ const SELECTOR_CAPTION = '.carousel-caption-container p';
11
+
12
+ class CarouselCaption extends BaseComponent {
13
+ constructor(element) {
14
+ super(element);
15
+
16
+ this._captionEl = this._findCaptionEl();
17
+ if (!this._captionEl) {
6
18
  return;
7
19
  }
8
20
 
9
- this.carouselEl = carouselEl;
10
- this.carousel = Carousel.getOrCreateInstance(carouselEl);
11
- this.captionEl = carouselEl
12
- .closest('.carousel-wrapper')
13
- ?.previousElementSibling?.querySelector('.carousel-caption-container');
14
-
21
+ this._updateCaption(); // Initialize
15
22
  this._bindEvents();
16
- this._updateCaption();
23
+ }
24
+
25
+ dispose() {
26
+ EventHandler.off(this._element, EVENT_SLID);
27
+ super.dispose();
17
28
  }
18
29
 
19
30
  _bindEvents() {
20
- this.carouselEl.addEventListener('slide.bs.carousel', () => this._updateCaption());
31
+ EventHandler.on(this._element, EVENT_SLID, () => this._updateCaption());
21
32
  }
22
33
 
23
34
  _updateCaption() {
24
- const active = this.carouselEl.querySelector('.carousel-item.active');
25
- const captionText = active?.getAttribute('data-caption');
26
- if (this.captionEl && captionText) {
27
- this.captionEl.querySelector('p').textContent = captionText;
35
+ const activeItem = SelectorEngine.findOne('.carousel-item.active', this._element);
36
+ const newCaption = activeItem?.getAttribute('data-caption');
37
+ if (this._captionEl && newCaption) {
38
+ this._captionEl.textContent = newCaption;
28
39
  }
29
40
  }
30
41
 
31
- static initAll() {
32
- for (const el of document.querySelectorAll('.carousel')) {
33
- // eslint-disable-next-line no-new
34
- new CarouselCaption(el);
35
- }
42
+ _findCaptionEl() {
43
+ return this._element.querySelector(SELECTOR_CAPTION) || null;
44
+ }
45
+
46
+ static get NAME() {
47
+ return NAME;
48
+ }
49
+
50
+ static jQueryInterface(config) {
51
+ return this.each(function () {
52
+ CarouselCaption.getOrCreateInstance(this, config);
53
+ });
36
54
  }
37
55
  }
38
56
 
57
+ // Auto-init on DOMContentLoaded
58
+ document.addEventListener('DOMContentLoaded', () => {
59
+ for (const el of SelectorEngine.find(SELECTOR_CAROUSEL)) {
60
+ CarouselCaption.getOrCreateInstance(el);
61
+ }
62
+ });
63
+
64
+ defineJQueryPlugin(CarouselCaption);
65
+
39
66
  export default CarouselCaption;
package/js/video-modal.js CHANGED
@@ -1,4 +1,15 @@
1
- // Load YouTube API
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 = 'videoModal';
7
+ const DATA_KEY = 'bs.videoModal';
8
+ const EVENT_SHOW = 'show.bs.modal';
9
+ const EVENT_HIDDEN = 'hidden.bs.modal';
10
+ const SELECTOR_DIALOG = '.modal-dialog-media';
11
+ const SELECTOR_RATIO = '.ratio';
12
+
2
13
  // eslint-disable-next-line no-unused-vars
3
14
  let youTubeAPIReady = false;
4
15
  const youTubeAPIInitPromise = new Promise((resolve) => {
@@ -11,13 +22,12 @@ const youTubeAPIInitPromise = new Promise((resolve) => {
11
22
  resolve();
12
23
  };
13
24
 
14
- const ytScript = document.createElement('script');
15
- ytScript.src = 'https://www.youtube.com/iframe_api';
16
- document.head.append(ytScript);
25
+ const script = document.createElement('script');
26
+ script.src = 'https://www.youtube.com/iframe_api';
27
+ document.head.append(script);
17
28
  }
18
29
  });
19
30
 
20
- // Load Vimeo API
21
31
  // eslint-disable-next-line no-unused-vars
22
32
  let vimeoAPIReady = false;
23
33
  const vimeoAPIInitPromise = new Promise((resolve) => {
@@ -25,99 +35,112 @@ const vimeoAPIInitPromise = new Promise((resolve) => {
25
35
  vimeoAPIReady = true;
26
36
  resolve();
27
37
  } else {
28
- const vimeoScript = document.createElement('script');
29
- vimeoScript.src = 'https://player.vimeo.com/api/player.js';
30
- vimeoScript.addEventListener('load', () => {
38
+ const script = document.createElement('script');
39
+ script.src = 'https://player.vimeo.com/api/player.js';
40
+ script.addEventListener('load', () => {
31
41
  vimeoAPIReady = true;
32
42
  resolve();
33
43
  });
34
44
 
35
- document.head.append(vimeoScript);
45
+ document.head.append(script);
36
46
  }
37
47
  });
38
48
 
39
- class VideoModal {
40
- constructor(modal) {
41
- this.modal = modal;
42
- this.dialog = modal.querySelector('.modal-dialog-media');
43
- this.container = modal.querySelector('.ratio');
44
- if (!this.dialog || !this.container) {
49
+ class VideoModal extends BaseComponent {
50
+ constructor(element) {
51
+ super(element);
52
+
53
+ this._dialog = SelectorEngine.findOne(SELECTOR_DIALOG, this._element);
54
+ this._container = SelectorEngine.findOne(SELECTOR_RATIO, this._element);
55
+
56
+ if (!this._dialog || !this._container) {
45
57
  return;
46
58
  }
47
59
 
48
- this.modalId = modal.id;
49
- this.youtubeSrc = this.container.getAttribute('data-src');
50
- this.vimeoUrl = this.container.getAttribute('data-vimeo-url');
51
- this.vimeoPlayer = null;
52
- this.youtubePlayer = null;
60
+ this._youtubeSrc = this._container.getAttribute('data-src');
61
+ this._vimeoUrl = this._container.getAttribute('data-vimeo-url');
62
+ this._youtubePlayer = null;
63
+ this._vimeoPlayer = null;
64
+
65
+ EventHandler.on(this._element, EVENT_SHOW, () => this._onShow());
66
+ EventHandler.on(this._element, EVENT_HIDDEN, () => this._onHide());
67
+ }
53
68
 
54
- modal.addEventListener('show.bs.modal', () => this.onShow());
55
- modal.addEventListener('hidden.bs.modal', () => this.onHide());
69
+ dispose() {
70
+ this._onHide();
71
+ super.dispose();
56
72
  }
57
73
 
58
- async onShow() {
59
- const playerClass = `${this.modalId}-youtube-player`;
74
+ async _onShow() {
75
+ const { id } = this._element;
76
+ const playerClass = `${id}-youtube-player`;
60
77
 
61
- if (this.vimeoUrl) {
62
- const vimeoId = this.getVimeoId(this.vimeoUrl);
78
+ if (this._vimeoUrl) {
63
79
  await vimeoAPIInitPromise;
64
-
65
- this.vimeoPlayer = new window.Vimeo.Player(this.container, {
80
+ const vimeoId = this._getVimeoId(this._vimeoUrl);
81
+ this._vimeoPlayer = new window.Vimeo.Player(this._container, {
66
82
  id: vimeoId,
67
83
  autoplay: true
68
84
  });
69
85
  }
70
86
 
71
- if (this.youtubeSrc) {
72
- const youtubeId = this.getYouTubeId(this.youtubeSrc);
87
+ if (this._youtubeSrc) {
73
88
  await youTubeAPIInitPromise;
74
-
75
- // Dynamically insert YouTube div
76
- this.container.innerHTML = `<div class="${playerClass} w-100 h-100"></div>`;
77
- const playerDiv = this.container.querySelector(`.${playerClass}`);
78
-
79
- // eslint-disable-next-line no-undef
80
- this.youtubePlayer = new YT.Player(playerDiv, {
89
+ const youtubeId = this._getYouTubeId(this._youtubeSrc);
90
+ this._container.innerHTML = `<div class="${playerClass} w-100 h-100"></div>`;
91
+ const playerDiv = this._container.querySelector(`.${playerClass}`);
92
+ this._youtubePlayer = new window.YT.Player(playerDiv, {
81
93
  videoId: youtubeId,
82
94
  playerVars: { autoplay: 1, rel: 0 }
83
95
  });
84
96
  }
85
97
  }
86
98
 
87
- onHide() {
88
- if (this.vimeoPlayer) {
89
- this.vimeoPlayer.unload().catch(() => {});
90
- this.vimeoPlayer = null;
99
+ _onHide() {
100
+ if (this._vimeoPlayer) {
101
+ this._vimeoPlayer.unload().catch(() => {});
102
+ this._vimeoPlayer = null;
91
103
  }
92
104
 
93
- if (this.youtubePlayer) {
94
- this.youtubePlayer.destroy();
95
- this.youtubePlayer = null;
105
+ if (this._youtubePlayer) {
106
+ this._youtubePlayer.destroy();
107
+ this._youtubePlayer = null;
96
108
  }
97
109
  }
98
110
 
99
- getYouTubeId(url) {
111
+ _getYouTubeId(url) {
100
112
  const match = url.match(/(?:v=|youtu\.be\/)([\w-]{11})/);
101
113
  return match ? match[1] : '';
102
114
  }
103
115
 
104
- getVimeoId(url) {
116
+ _getVimeoId(url) {
105
117
  const match = url.match(/vimeo\.com\/(\d+)/);
106
118
  return match ? match[1] : '';
107
119
  }
120
+
121
+ static get NAME() {
122
+ return NAME;
123
+ }
124
+
125
+ static jQueryInterface(config) {
126
+ return this.each(function () {
127
+ VideoModal.getOrCreateInstance(this, config);
128
+ });
129
+ }
108
130
  }
109
131
 
110
- // Auto-init for all triggered modals with dialog-media
132
+ // Auto-init
111
133
  document.addEventListener('DOMContentLoaded', () => {
112
- for (const button of document.querySelectorAll('[data-bs-toggle="modal"][data-bs-target]')) {
113
- const targetSelector = button.getAttribute('data-bs-target');
134
+ const modals = SelectorEngine.find('[data-bs-toggle="modal"][data-bs-target]');
135
+ for (const btn of modals) {
136
+ const targetSelector = btn.getAttribute('data-bs-target');
114
137
  const modal = document.querySelector(targetSelector);
115
-
116
- if (modal?.querySelector('.modal-dialog-media')) {
117
- // eslint-disable-next-line no-new
118
- new VideoModal(modal);
138
+ if (modal?.querySelector(SELECTOR_DIALOG)) {
139
+ VideoModal.getOrCreateInstance(modal);
119
140
  }
120
141
  }
121
142
  });
122
143
 
144
+ defineJQueryPlugin(VideoModal);
145
+
123
146
  export default VideoModal;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@unlk/keymaster",
3
- "version": "1.0.5",
3
+ "version": "1.0.6",
4
4
  "publishConfig": {
5
5
  "access": "public"
6
6
  },
@@ -14,6 +14,7 @@
14
14
  .accordion-button {
15
15
  margin-bottom: 0;
16
16
  background-color: var(--#{$prefix}accordion-alt-btn-bg);
17
+ @include box-shadow(none);
17
18
 
18
19
  i {
19
20
  width: var(--#{$prefix}accordion-alt-btn-icon-width);
@@ -22,8 +23,8 @@
22
23
  }
23
24
 
24
25
  &:not(.collapsed) {
25
- color: var(--#{$prefix}accordion-alt-active-color);
26
26
  @include box-shadow(none);
27
+ color: var(--#{$prefix}accordion-alt-active-color);
27
28
 
28
29
  &::after {
29
30
  background-image: var(--#{$prefix}accordion-alt-btn-active-icon);
@@ -12,14 +12,20 @@
12
12
  @each $state, $value in $theme-colors {
13
13
  $alert-border: var(--#{$prefix}#{$state}-border-subtle);
14
14
  $alert-color: var(--#{$prefix}#{$state}-text-emphasis);
15
+ $alert-bg: var(--#{$prefix}#{$state}-bg-subtle);
15
16
  @if $state == "tertiary" {
16
17
  $alert-border: $gray-400;
17
18
  $alert-color: $foundation-500;
18
19
  }
20
+ @else if $state == "danger" {
21
+ $alert-bg: $danger-25;
22
+ } @else if $state == "success" {
23
+ $alert-bg: $success-50;
24
+ }
19
25
 
20
26
  .alert-#{$state} {
21
27
  --#{$prefix}alert-color: #{$alert-color};
22
- --#{$prefix}alert-bg: var(--#{$prefix}#{$state}-bg-subtle);
28
+ --#{$prefix}alert-bg: #{$alert-bg};
23
29
  --#{$prefix}alert-border-color: #{$alert-border};
24
30
  --#{$prefix}alert-link-color: var(--#{$prefix}#{$state}-text-emphasis);
25
31
  }
@@ -4,12 +4,12 @@
4
4
  @import "../assets/bootstrap5/utilities";
5
5
  @import "../assets/bootstrap5/vendor/rfs";
6
6
 
7
- $box-shadow-sm: 0 rfs-value(1px) rfs-value(4px) rgba($foundation-500, .1);
8
- $box-shadow: 0 rfs-value(4px) rfs-value(10px) rgba($foundation-500, .12);
9
- $box-shadow-lg: 0 rfs-value(8px) rfs-value(35px) rgba($foundation-500, .16);
10
- $box-shadow-inset: 0 rfs-value(1px) rfs-value(2px) rgba($foundation-500, .1) inset;
7
+ $box-shadow-sm: 0 rfs-value(1px) rfs-value(4px) rgba($foundation-500, .1) !default;
8
+ $box-shadow: 0 rfs-value(4px) rfs-value(10px) rgba($foundation-500, .12) !default;
9
+ $box-shadow-lg: 0 rfs-value(8px) rfs-value(35px) rgba($foundation-500, .16) !default;
10
+ $box-shadow-inset: 0 rfs-value(1px) rfs-value(2px) rgba($foundation-500, .1) inset !default;
11
11
 
12
- $all-colors: map-merge-multiple($foundations, $blueprints, $entryways, $turnkeys, $sunglows, $warnings, $grays, $successs, $dangers);
12
+ $all-colors: map-merge-multiple($foundations, $blueprints, $entryways, $turnkeys, $sunglows, $warnings, $grays, $successs, $dangers) !default;
13
13
 
14
14
  $utilities: map-merge(
15
15
  $utilities,