@openeuropa/bcl-theme-default 1.10.0 → 1.10.2

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.
Files changed (37) hide show
  1. package/css/oe-bcl-ckeditor5.min.css +1 -1
  2. package/css/oe-bcl-ckeditor5.min.css.map +1 -1
  3. package/css/oe-bcl-default.css +1034 -124
  4. package/css/oe-bcl-default.css.map +1 -1
  5. package/css/oe-bcl-default.min.css +1 -1
  6. package/css/oe-bcl-default.min.css.map +1 -1
  7. package/js/oe-bcl-default.bundle.js +124 -74
  8. package/js/oe-bcl-default.bundle.js.map +1 -1
  9. package/js/oe-bcl-default.bundle.min.js +1 -1
  10. package/js/oe-bcl-default.bundle.min.js.map +1 -1
  11. package/js/oe-bcl-default.esm.js +124 -74
  12. package/js/oe-bcl-default.esm.js.map +1 -1
  13. package/js/oe-bcl-default.esm.min.js +1 -1
  14. package/js/oe-bcl-default.esm.min.js.map +1 -1
  15. package/js/oe-bcl-default.umd.js +124 -74
  16. package/js/oe-bcl-default.umd.js.map +1 -1
  17. package/js/oe-bcl-default.umd.min.js +1 -1
  18. package/js/oe-bcl-default.umd.min.js.map +1 -1
  19. package/package.json +8 -7
  20. package/src/js/accessible-toggle/accessible-toggle.js +11 -3
  21. package/src/js/gallery/gallery.js +118 -62
  22. package/src/scss/_accordion.scss +4 -0
  23. package/src/scss/_inpage-navigation.scss +7 -0
  24. package/src/scss/_multiselect-2.scss +1 -1
  25. package/src/scss/_multiselect.scss +21 -0
  26. package/src/scss/_timeline.scss +2 -0
  27. package/src/scss/base/_layout.scss +6 -3
  28. package/src/scss/base/_variables.scss +2 -3
  29. package/templates/bcl-accordion/accordion.html.twig +8 -3
  30. package/templates/bcl-dropdown/dropdown.html.twig +1 -1
  31. package/templates/bcl-file/file-translations.html.twig +2 -2
  32. package/templates/bcl-gallery/gallery-item.html.twig +1 -0
  33. package/templates/bcl-gallery/gallery.html.twig +2 -2
  34. package/templates/bcl-inpage-navigation/inpage-navigation.html.twig +14 -10
  35. package/templates/bcl-language-switcher/language-switcher.html.twig +2 -2
  36. package/templates/bcl-modal/modal.html.twig +2 -2
  37. package/templates/bcl-timeline/timeline.html.twig +2 -2
@@ -196,7 +196,7 @@ const noop = () => {};
196
196
  * @param {HTMLElement} element
197
197
  * @return void
198
198
  *
199
- * @see https://www.charistheo.io/blog/2021/02/restart-a-css-animation-with-javascript/#restarting-a-css-animation
199
+ * @see https://www.harrytheo.com/blog/2021/02/restart-a-css-animation-with-javascript/#restarting-a-css-animation
200
200
  */
201
201
  const reflow = element => {
202
202
  element.offsetHeight; // eslint-disable-line no-unused-expressions
@@ -241,7 +241,7 @@ const defineJQueryPlugin$1 = plugin => {
241
241
  });
242
242
  };
243
243
  const execute = (possibleCallback, args = [], defaultValue = possibleCallback) => {
244
- return typeof possibleCallback === 'function' ? possibleCallback(...args) : defaultValue;
244
+ return typeof possibleCallback === 'function' ? possibleCallback.call(...args) : defaultValue;
245
245
  };
246
246
  const executeAfterTransition = (callback, transitionElement, waitForTransition = true) => {
247
247
  if (!waitForTransition) {
@@ -563,7 +563,7 @@ const Manipulator$1 = {
563
563
  const bsKeys = Object.keys(element.dataset).filter(key => key.startsWith('bs') && !key.startsWith('bsConfig'));
564
564
  for (const key of bsKeys) {
565
565
  let pureKey = key.replace(/^bs/, '');
566
- pureKey = pureKey.charAt(0).toLowerCase() + pureKey.slice(1, pureKey.length);
566
+ pureKey = pureKey.charAt(0).toLowerCase() + pureKey.slice(1);
567
567
  attributes[pureKey] = normalizeData$1(element.dataset[key]);
568
568
  }
569
569
  return attributes;
@@ -638,7 +638,7 @@ class Config {
638
638
  * Constants
639
639
  */
640
640
 
641
- const VERSION = '5.3.3';
641
+ const VERSION = '5.3.6';
642
642
 
643
643
  /**
644
644
  * Class definition
@@ -664,6 +664,8 @@ class BaseComponent extends Config {
664
664
  this[propertyName] = null;
665
665
  }
666
666
  }
667
+
668
+ // Private
667
669
  _queueCallback(callback, element, isAnimated = true) {
668
670
  executeAfterTransition(callback, element, isAnimated);
669
671
  }
@@ -1595,11 +1597,11 @@ class Collapse extends BaseComponent {
1595
1597
  this._element.style[dimension] = '';
1596
1598
  this._queueCallback(complete, this._element, true);
1597
1599
  }
1600
+
1601
+ // Private
1598
1602
  _isShown(element = this._element) {
1599
1603
  return element.classList.contains(CLASS_NAME_SHOW$7);
1600
1604
  }
1601
-
1602
- // Private
1603
1605
  _configAfterMerge(config) {
1604
1606
  config.toggle = Boolean(config.toggle); // Coerce string values
1605
1607
  config.parent = getElement$1(config.parent);
@@ -1702,7 +1704,7 @@ const EVENT_HIDDEN$5 = `hidden${EVENT_KEY$8}`;
1702
1704
  const EVENT_SHOW$5 = `show${EVENT_KEY$8}`;
1703
1705
  const EVENT_SHOWN$5 = `shown${EVENT_KEY$8}`;
1704
1706
  const EVENT_CLICK_DATA_API$4 = `click${EVENT_KEY$8}${DATA_API_KEY$5}`;
1705
- const EVENT_KEYDOWN_DATA_API = `keydown${EVENT_KEY$8}${DATA_API_KEY$5}`;
1707
+ const EVENT_KEYDOWN_DATA_API$1 = `keydown${EVENT_KEY$8}${DATA_API_KEY$5}`;
1706
1708
  const EVENT_KEYUP_DATA_API = `keyup${EVENT_KEY$8}${DATA_API_KEY$5}`;
1707
1709
  const CLASS_NAME_SHOW$6 = 'show';
1708
1710
  const CLASS_NAME_DROPUP = 'dropup';
@@ -1842,6 +1844,9 @@ class Dropdown extends BaseComponent {
1842
1844
  this._element.setAttribute('aria-expanded', 'false');
1843
1845
  Manipulator$1.removeDataAttribute(this._menu, 'popper');
1844
1846
  EventHandler.trigger(this._element, EVENT_HIDDEN$5, relatedTarget);
1847
+
1848
+ // Explicitly return focus to the trigger element
1849
+ this._element.focus();
1845
1850
  }
1846
1851
  _getConfig(config) {
1847
1852
  config = super._getConfig(config);
@@ -1853,7 +1858,7 @@ class Dropdown extends BaseComponent {
1853
1858
  }
1854
1859
  _createPopper() {
1855
1860
  if (typeof Popper === 'undefined') {
1856
- throw new TypeError('Bootstrap\'s dropdowns require Popper (https://popper.js.org)');
1861
+ throw new TypeError('Bootstrap\'s dropdowns require Popper (https://popper.js.org/docs/v2/)');
1857
1862
  }
1858
1863
  let referenceElement = this._element;
1859
1864
  if (this._config.reference === 'parent') {
@@ -1932,7 +1937,7 @@ class Dropdown extends BaseComponent {
1932
1937
  }
1933
1938
  return {
1934
1939
  ...defaultBsPopperConfig,
1935
- ...execute(this._config.popperConfig, [defaultBsPopperConfig])
1940
+ ...execute(this._config.popperConfig, [undefined, defaultBsPopperConfig])
1936
1941
  };
1937
1942
  }
1938
1943
  _selectMenuItem({
@@ -2028,8 +2033,8 @@ class Dropdown extends BaseComponent {
2028
2033
  * Data API implementation
2029
2034
  */
2030
2035
 
2031
- EventHandler.on(document, EVENT_KEYDOWN_DATA_API, SELECTOR_DATA_TOGGLE$3, Dropdown.dataApiKeydownHandler);
2032
- EventHandler.on(document, EVENT_KEYDOWN_DATA_API, SELECTOR_MENU, Dropdown.dataApiKeydownHandler);
2036
+ EventHandler.on(document, EVENT_KEYDOWN_DATA_API$1, SELECTOR_DATA_TOGGLE$3, Dropdown.dataApiKeydownHandler);
2037
+ EventHandler.on(document, EVENT_KEYDOWN_DATA_API$1, SELECTOR_MENU, Dropdown.dataApiKeydownHandler);
2033
2038
  EventHandler.on(document, EVENT_CLICK_DATA_API$4, Dropdown.clearMenus);
2034
2039
  EventHandler.on(document, EVENT_KEYUP_DATA_API, Dropdown.clearMenus);
2035
2040
  EventHandler.on(document, EVENT_CLICK_DATA_API$4, SELECTOR_DATA_TOGGLE$3, function (event) {
@@ -3119,7 +3124,7 @@ class TemplateFactory extends Config {
3119
3124
  return this._config.sanitize ? sanitizeHtml(arg, this._config.allowList, this._config.sanitizeFn) : arg;
3120
3125
  }
3121
3126
  _resolvePossibleFunction(arg) {
3122
- return execute(arg, [this]);
3127
+ return execute(arg, [undefined, this]);
3123
3128
  }
3124
3129
  _putElementInTemplate(element, templateElement) {
3125
3130
  if (this._config.html) {
@@ -3218,7 +3223,7 @@ const DefaultType$3 = {
3218
3223
  class Tooltip extends BaseComponent {
3219
3224
  constructor(element, config) {
3220
3225
  if (typeof Popper === 'undefined') {
3221
- throw new TypeError('Bootstrap\'s tooltips require Popper (https://popper.js.org)');
3226
+ throw new TypeError('Bootstrap\'s tooltips require Popper (https://popper.js.org/docs/v2/)');
3222
3227
  }
3223
3228
  super(element, config);
3224
3229
 
@@ -3264,7 +3269,6 @@ class Tooltip extends BaseComponent {
3264
3269
  if (!this._isEnabled) {
3265
3270
  return;
3266
3271
  }
3267
- this._activeTrigger.click = !this._activeTrigger.click;
3268
3272
  if (this._isShown()) {
3269
3273
  this._leave();
3270
3274
  return;
@@ -3452,7 +3456,7 @@ class Tooltip extends BaseComponent {
3452
3456
  return offset;
3453
3457
  }
3454
3458
  _resolvePossibleFunction(arg) {
3455
- return execute(arg, [this._element]);
3459
+ return execute(arg, [this._element, this._element]);
3456
3460
  }
3457
3461
  _getPopperConfig(attachment) {
3458
3462
  const defaultBsPopperConfig = {
@@ -3490,7 +3494,7 @@ class Tooltip extends BaseComponent {
3490
3494
  };
3491
3495
  return {
3492
3496
  ...defaultBsPopperConfig,
3493
- ...execute(this._config.popperConfig, [defaultBsPopperConfig])
3497
+ ...execute(this._config.popperConfig, [undefined, defaultBsPopperConfig])
3494
3498
  };
3495
3499
  }
3496
3500
  _setListeners() {
@@ -4726,7 +4730,6 @@ class Toast extends BaseComponent {
4726
4730
  }
4727
4731
 
4728
4732
  // Private
4729
-
4730
4733
  _maybeScheduleHide() {
4731
4734
  if (!this._config.autohide) {
4732
4735
  return;
@@ -4802,23 +4805,16 @@ defineJQueryPlugin$1(Toast);
4802
4805
 
4803
4806
  /**
4804
4807
  * --------------------------------------------------------------------------
4805
- * Bootstrap (v5.1.3): gallery.js
4808
+ * Bootstrap (v5.1.3): gallery.js (Refactored)
4806
4809
  * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
4807
4810
  * --------------------------------------------------------------------------
4808
4811
  */
4809
4812
 
4810
-
4811
- /**
4812
- * ------------------------------------------------------------------------
4813
- * Constants
4814
- * ------------------------------------------------------------------------
4815
- */
4816
-
4817
- const Default = {};
4818
4813
  const NAME = 'gallery';
4819
4814
  const DATA_KEY = 'bs.gallery';
4820
4815
  const EVENT_KEY = `.${DATA_KEY}`;
4821
4816
  const DATA_API_KEY = '.data-api';
4817
+ const Default = {};
4822
4818
  const CAROUSEL_SELECTOR = '.carousel';
4823
4819
  const CAROUSEL_PAGER_SELECTOR = '.carousel-pager span';
4824
4820
  const CAROUSEL_ACTIVE_SELECTOR = '.carousel-item.active';
@@ -4828,72 +4824,115 @@ const MODAL_SELECTOR = '.modal';
4828
4824
  const EVENT_MODAL_HIDE = 'hide.bs.modal';
4829
4825
  const CAROUSEL_EVENT = 'slide.bs.carousel';
4830
4826
  const EVENT_CLICK_DATA_API = `click${EVENT_KEY}${DATA_API_KEY}`;
4831
-
4832
- /**
4833
- * ------------------------------------------------------------------------
4834
- * Class Definition
4835
- * ------------------------------------------------------------------------
4836
- */
4837
-
4827
+ const EVENT_KEYDOWN_DATA_API = `keydown${EVENT_KEY}${DATA_API_KEY}`;
4838
4828
  class Gallery extends BaseComponent {
4839
4829
  constructor(element, config) {
4840
4830
  super(element, config);
4841
- /* eslint no-underscore-dangle: ["error", { "allow": ["_element"] }] */
4842
4831
  this.carousel = SelectorEngine.findOne(CAROUSEL_SELECTOR, this._element);
4843
4832
  this.carouselPager = SelectorEngine.findOne(CAROUSEL_PAGER_SELECTOR, this._element);
4844
- this.carouselStartIndex = element.getAttribute('data-gallery-start');
4845
- this.carouselActiveItem = SelectorEngine.find(CAROUSEL_ITEM_SELECTOR, this.carousel)[this.carouselStartIndex];
4846
- this.carouselPager.textContent = Number(this.carouselStartIndex) + 1;
4847
4833
  this.modal = SelectorEngine.findOne(MODAL_SELECTOR, this._element);
4848
- this.addEventListeners();
4849
- this.carouselLazyLoad(this.carouselActiveItem);
4834
+ this.carouselStartIndex = element.getAttribute('data-gallery-start') || 0;
4835
+ const allCarouselItems = SelectorEngine.find(CAROUSEL_ITEM_SELECTOR, this.carousel);
4836
+ const startIndexNum = Math.max(0, Math.min(Number(this.carouselStartIndex), allCarouselItems.length - 1));
4837
+ this.carouselPager.textContent = startIndexNum + 1;
4838
+ this.carouselActiveItem = allCarouselItems[startIndexNum];
4839
+ this._carouselLazyLoad(this.carouselActiveItem);
4840
+ EventHandler.on(this.carousel, CAROUSEL_EVENT, event => this._handleCarouselSlide(event));
4841
+ EventHandler.on(this.modal, EVENT_MODAL_HIDE, () => this._stopSlide());
4850
4842
  }
4851
4843
 
4852
4844
  // Getters
4853
4845
  static get NAME() {
4854
4846
  return NAME;
4855
4847
  }
4848
+ static get Default() {
4849
+ return Default;
4850
+ }
4856
4851
 
4857
- // Public
4858
- setSlide(event) {
4859
- const slideFrom = SelectorEngine.findOne(CAROUSEL_ACTIVE_SELECTOR, this.carousel);
4860
- const slideTo = event.relatedTarget;
4861
- this.carouselLazyLoad(slideTo);
4852
+ /**
4853
+ * Handle the carousel "slide.bs.carousel" event
4854
+ * @param {Event} event
4855
+ */
4856
+ _handleCarouselSlide(event) {
4857
+ const previousSlide = SelectorEngine.findOne(CAROUSEL_ACTIVE_SELECTOR, this.carousel);
4858
+ const currentSlide = event.relatedTarget;
4859
+ this._carouselLazyLoad(currentSlide);
4862
4860
  this.carouselPager.textContent = event.to + 1;
4863
- this.stopVideo(slideFrom);
4861
+ this._stopVideo(previousSlide);
4864
4862
  }
4865
- stopSlide() {
4863
+
4864
+ /**
4865
+ * Stop the current carousel slide (when modal hides or component is disposed)
4866
+ */
4867
+ _stopSlide() {
4866
4868
  const currentSlide = SelectorEngine.findOne(CAROUSEL_ACTIVE_SELECTOR, this.carousel);
4867
- this.stopVideo(currentSlide);
4869
+ this._stopVideo(currentSlide);
4868
4870
  }
4869
- stopVideo(slide) {
4871
+
4872
+ /**
4873
+ * Stop any video or iframe in the given slide
4874
+ * @param {HTMLElement} slide
4875
+ */
4876
+ _stopVideo(slide) {
4877
+ if (!slide) {
4878
+ return;
4879
+ }
4870
4880
  const iframe = SelectorEngine.findOne('iframe', slide);
4871
4881
  const video = SelectorEngine.findOne('video', slide);
4872
- if (iframe) {
4882
+ if (iframe && iframe.dataset.src) {
4873
4883
  iframe.src = iframe.dataset.src;
4874
4884
  } else if (video) {
4875
4885
  video.pause();
4876
4886
  }
4877
4887
  }
4878
4888
 
4879
- // Private
4880
- carouselLazyLoad(slide) {
4889
+ /**
4890
+ * Lazy load media (img, iframe, video, etc.) by copying data-src into src
4891
+ * @param {HTMLElement} slide
4892
+ */
4893
+ _carouselLazyLoad(slide) {
4894
+ if (!slide) {
4895
+ return;
4896
+ }
4881
4897
  const media = SelectorEngine.findOne('[data-src]', slide);
4882
4898
  if (media && !media.src) {
4883
4899
  media.src = media.dataset.src;
4884
4900
  }
4885
4901
  }
4886
- addEventListeners() {
4887
- EventHandler.on(this.carousel, CAROUSEL_EVENT, event => this.setSlide(event));
4888
- EventHandler.on(this.modal, EVENT_MODAL_HIDE, event => this.stopSlide(event));
4889
- }
4890
4902
 
4891
- // Static
4892
- static get Default() {
4893
- return Default;
4903
+ /**
4904
+ * Internal helper to open the modal and jump to a specific slide
4905
+ * @param {HTMLElement} gallery
4906
+ * @param {HTMLElement} targetLink
4907
+ */
4908
+ static _openModalAndShowSlide(gallery, targetLink) {
4909
+ if (!gallery || !targetLink) {
4910
+ return;
4911
+ }
4912
+ const firstSlide = Number(targetLink.getAttribute('data-bs-slide-to') || 0);
4913
+ gallery.dataset.galleryStart = firstSlide;
4914
+ const instance = Gallery.getOrCreateInstance(gallery);
4915
+ const overlay = SelectorEngine.findOne('.bcl-gallery__item-overlay', targetLink);
4916
+ if (overlay) {
4917
+ const modalId = overlay.getAttribute('data-bs-target');
4918
+ const modalElement = document.querySelector(modalId);
4919
+ if (modalElement) {
4920
+ const modal = bootstrap.Modal.getOrCreateInstance(modalElement);
4921
+ modal.show();
4922
+ }
4923
+ }
4924
+ setTimeout(() => {
4925
+ const carousel = SelectorEngine.findOne(CAROUSEL_SELECTOR, instance._element);
4926
+ const carouselInstance = bootstrap.Carousel.getOrCreateInstance(carousel);
4927
+ carouselInstance.to(firstSlide);
4928
+ const pager = SelectorEngine.findOne(CAROUSEL_PAGER_SELECTOR, instance._element);
4929
+ if (pager) {
4930
+ pager.textContent = firstSlide + 1;
4931
+ }
4932
+ }, 50);
4894
4933
  }
4895
4934
  static jQueryInterface(config) {
4896
- return this.each(function jInterface() {
4935
+ return this.each(function () {
4897
4936
  const data = Gallery.getOrCreateInstance(this);
4898
4937
  if (typeof config !== 'string') {
4899
4938
  return;
@@ -4908,24 +4947,28 @@ class Gallery extends BaseComponent {
4908
4947
 
4909
4948
  /**
4910
4949
  * ------------------------------------------------------------------------
4911
- * Data Api implementation
4950
+ * Data API implementation
4912
4951
  * ------------------------------------------------------------------------
4913
4952
  */
4914
4953
 
4954
+ const isEnterOrSpace = event => {
4955
+ return event.key === 'Enter' || event.key === ' ';
4956
+ };
4915
4957
  EventHandler.on(document, EVENT_CLICK_DATA_API, THUMBNAIL_SELECTOR, event => {
4958
+ event.preventDefault();
4959
+ const targetLink = event.target.closest('a');
4916
4960
  const gallery = event.target.closest('div.bcl-gallery');
4917
- const firstSlide = event.target.parentNode.getAttribute('data-bs-slide-to');
4918
- gallery.dataset.galleryStart = firstSlide;
4919
- Gallery.getOrCreateInstance(gallery);
4961
+ Gallery._openModalAndShowSlide(gallery, targetLink);
4962
+ });
4963
+ EventHandler.on(document, EVENT_KEYDOWN_DATA_API, THUMBNAIL_SELECTOR, event => {
4964
+ if (!isEnterOrSpace(event)) {
4965
+ return;
4966
+ }
4967
+ event.preventDefault();
4968
+ const targetLink = event.target.closest('a');
4969
+ const gallery = event.target.closest('div.bcl-gallery');
4970
+ Gallery._openModalAndShowSlide(gallery, targetLink);
4920
4971
  });
4921
-
4922
- /**
4923
- * ------------------------------------------------------------------------
4924
- * jQuery
4925
- * ------------------------------------------------------------------------
4926
- * add .gallery to jQuery only if jQuery is present
4927
- */
4928
-
4929
4972
  defineJQueryPlugin$1(Gallery);
4930
4973
 
4931
4974
  class AccordionToggle {
@@ -4993,9 +5036,16 @@ class AccessibleToggle {
4993
5036
  this.addEventListeners();
4994
5037
  }
4995
5038
  addAriaAttributes() {
4996
- if (this.triggerElement) {
4997
- this.triggerElement.setAttribute("aria-haspopup", "true");
4998
- this.triggerElement.setAttribute("aria-expanded", "false");
5039
+ if (this.type === 'modal') {
5040
+ if (this.triggerElement) {
5041
+ this.triggerElement.setAttribute('aria-haspopup', 'dialog');
5042
+ }
5043
+ }
5044
+ if (this.type === 'offcanvas') {
5045
+ if (this.triggerElement) {
5046
+ this.triggerElement.setAttribute('aria-haspopup', 'dialog');
5047
+ this.triggerElement.setAttribute('aria-expanded', 'false');
5048
+ }
4999
5049
  }
5000
5050
  }
5001
5051
  addEventListeners() {