@idds/js 1.0.79 → 1.0.80

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.
@@ -851,44 +851,112 @@ var InaUI = (() => {
851
851
  }
852
852
 
853
853
  // src/js/components/stateless/modal.js
854
- function initModal(rootSelector = `.${PREFIX}-modal`) {
855
- document.querySelectorAll(rootSelector).forEach((modal) => {
856
- const modalContent = modal.querySelector(`${rootSelector}__content`);
857
- const modalTrigger = modal.querySelector(`${rootSelector}__trigger`);
858
- const modalClose = modal.querySelector(`${rootSelector}__close`);
859
- const modalOverlay = modal.querySelector(`${rootSelector}__overlay`);
860
- modalTrigger.addEventListener("click", () => {
861
- const modalTarget = modalTrigger.getAttribute("data-modal");
862
- const modal2 = document.querySelector(
863
- `.${PREFIX}-modal__content[data-modal="${modalTarget}"]`
864
- );
865
- document.body.style.overflow = "hidden";
866
- modalContent.classList.add(`${PREFIX}-modal__content--show`);
867
- modalOverlay.classList.add(`${PREFIX}-modal__overlay--show`);
868
- });
869
- modalClose.addEventListener("click", () => {
870
- modalContent.classList.remove(`${PREFIX}-modal__content--show`);
871
- modalOverlay.classList.remove(`${PREFIX}-modal__overlay--show`);
872
- setTimeout(() => {
873
- document.body.style.overflow = "";
874
- }, 300);
875
- });
876
- modal.addEventListener("keydown", (event) => {
877
- if (event.key === "Escape") {
878
- modalContent.classList.remove(`${PREFIX}-modal__content--show`);
879
- modalOverlay.classList.remove(`${PREFIX}-modal__overlay--show`);
880
- setTimeout(() => {
881
- document.body.style.overflow = "";
882
- }, 300);
854
+ function trapFocus(element) {
855
+ const focusableEls = element.querySelectorAll(
856
+ 'a[href]:not([disabled]), button:not([disabled]), textarea:not([disabled]), input[type="text"]:not([disabled]), input[type="radio"]:not([disabled]), input[type="checkbox"]:not([disabled]), select:not([disabled]), [tabindex]:not([tabindex="-1"])'
857
+ );
858
+ if (focusableEls.length === 0) return;
859
+ const firstFocusableEl = focusableEls[0];
860
+ const lastFocusableEl = focusableEls[focusableEls.length - 1];
861
+ element.addEventListener("keydown", function(e) {
862
+ if (e.key === "Tab") {
863
+ if (e.shiftKey) {
864
+ if (document.activeElement === firstFocusableEl) {
865
+ e.preventDefault();
866
+ lastFocusableEl.focus();
867
+ }
868
+ } else {
869
+ if (document.activeElement === lastFocusableEl) {
870
+ e.preventDefault();
871
+ firstFocusableEl.focus();
872
+ }
883
873
  }
874
+ }
875
+ });
876
+ const closeBtn = element.querySelector(`.${PREFIX}-modal__close-button`);
877
+ if (closeBtn) {
878
+ closeBtn.focus();
879
+ } else {
880
+ firstFocusableEl.focus();
881
+ }
882
+ }
883
+ function openModal(modalEl) {
884
+ if (!modalEl) return;
885
+ modalEl.style.display = "flex";
886
+ document.body.style.overflow = "hidden";
887
+ modalEl.setAttribute("aria-hidden", "false");
888
+ modalEl.classList.remove(
889
+ `${PREFIX}-modal--exit`,
890
+ `${PREFIX}-modal--exit-active`
891
+ );
892
+ modalEl.classList.add(`${PREFIX}-modal--enter`);
893
+ requestAnimationFrame(() => {
894
+ requestAnimationFrame(() => {
895
+ modalEl.classList.add(`${PREFIX}-modal--enter-active`);
896
+ modalEl.classList.remove(`${PREFIX}-modal--enter`);
897
+ trapFocus(modalEl);
884
898
  });
885
- modalOverlay.addEventListener("click", () => {
886
- modalContent.classList.remove(`${PREFIX}-modal__content--show`);
887
- modalOverlay.classList.remove(`${PREFIX}-modal__overlay--show`);
888
- setTimeout(() => {
889
- document.body.style.overflow = "";
890
- }, 300);
891
- });
899
+ });
900
+ }
901
+ function closeModal(modalEl) {
902
+ if (!modalEl) return;
903
+ modalEl.classList.remove(`${PREFIX}-modal--enter-active`);
904
+ modalEl.classList.add(`${PREFIX}-modal--exit-active`);
905
+ document.body.style.overflow = "";
906
+ modalEl.setAttribute("aria-hidden", "true");
907
+ setTimeout(() => {
908
+ modalEl.style.display = "none";
909
+ modalEl.classList.remove(`${PREFIX}-modal--exit-active`);
910
+ }, 300);
911
+ }
912
+ function initModal(rootSelector = `.${PREFIX}-modal`) {
913
+ document.addEventListener("click", (e) => {
914
+ const trigger = e.target.closest(`[data-toggle="modal"]`);
915
+ if (trigger) {
916
+ e.preventDefault();
917
+ const targetSelector = trigger.getAttribute("data-target") || trigger.getAttribute("href");
918
+ const modal = document.querySelector(targetSelector);
919
+ if (modal) {
920
+ modal._previousActiveElement = trigger;
921
+ openModal(modal);
922
+ }
923
+ }
924
+ const dismissBtn = e.target.closest(`[data-dismiss="modal"]`);
925
+ if (dismissBtn) {
926
+ const modal = dismissBtn.closest(rootSelector);
927
+ if (modal) {
928
+ closeModal(modal);
929
+ if (modal._previousActiveElement) {
930
+ modal._previousActiveElement.focus();
931
+ }
932
+ }
933
+ }
934
+ if (e.target.classList.contains(`${PREFIX}-modal`) || e.target.classList.contains(`${PREFIX}-modal__backdrop`)) {
935
+ const modal = e.target.closest(rootSelector);
936
+ if (modal && modal.getAttribute("data-persistent") !== "true") {
937
+ closeModal(modal);
938
+ }
939
+ }
940
+ });
941
+ document.addEventListener("keydown", (e) => {
942
+ if (e.key === "Escape") {
943
+ const openModalEl = document.querySelector(`${rootSelector}[aria-hidden="false"]`) || document.querySelector(`${rootSelector}[style*="display: flex"]`);
944
+ if (openModalEl && openModalEl.getAttribute("data-persistent") !== "true") {
945
+ closeModal(openModalEl);
946
+ if (openModalEl._previousActiveElement) {
947
+ openModalEl._previousActiveElement.focus();
948
+ }
949
+ }
950
+ }
951
+ });
952
+ document.addEventListener("click", (e) => {
953
+ const closeIconBtn = e.target.closest(`.${PREFIX}-modal__close-button`);
954
+ if (closeIconBtn && !closeIconBtn.hasAttribute("data-dismiss")) {
955
+ const modal = closeIconBtn.closest(rootSelector);
956
+ if (modal) {
957
+ closeModal(modal);
958
+ }
959
+ }
892
960
  });
893
961
  }
894
962
 
package/dist/index.js CHANGED
@@ -846,44 +846,112 @@ function initDatepicker() {
846
846
  }
847
847
 
848
848
  // src/js/components/stateless/modal.js
849
- function initModal(rootSelector = `.${PREFIX}-modal`) {
850
- document.querySelectorAll(rootSelector).forEach((modal) => {
851
- const modalContent = modal.querySelector(`${rootSelector}__content`);
852
- const modalTrigger = modal.querySelector(`${rootSelector}__trigger`);
853
- const modalClose = modal.querySelector(`${rootSelector}__close`);
854
- const modalOverlay = modal.querySelector(`${rootSelector}__overlay`);
855
- modalTrigger.addEventListener("click", () => {
856
- const modalTarget = modalTrigger.getAttribute("data-modal");
857
- const modal2 = document.querySelector(
858
- `.${PREFIX}-modal__content[data-modal="${modalTarget}"]`
859
- );
860
- document.body.style.overflow = "hidden";
861
- modalContent.classList.add(`${PREFIX}-modal__content--show`);
862
- modalOverlay.classList.add(`${PREFIX}-modal__overlay--show`);
863
- });
864
- modalClose.addEventListener("click", () => {
865
- modalContent.classList.remove(`${PREFIX}-modal__content--show`);
866
- modalOverlay.classList.remove(`${PREFIX}-modal__overlay--show`);
867
- setTimeout(() => {
868
- document.body.style.overflow = "";
869
- }, 300);
870
- });
871
- modal.addEventListener("keydown", (event) => {
872
- if (event.key === "Escape") {
873
- modalContent.classList.remove(`${PREFIX}-modal__content--show`);
874
- modalOverlay.classList.remove(`${PREFIX}-modal__overlay--show`);
875
- setTimeout(() => {
876
- document.body.style.overflow = "";
877
- }, 300);
849
+ function trapFocus(element) {
850
+ const focusableEls = element.querySelectorAll(
851
+ 'a[href]:not([disabled]), button:not([disabled]), textarea:not([disabled]), input[type="text"]:not([disabled]), input[type="radio"]:not([disabled]), input[type="checkbox"]:not([disabled]), select:not([disabled]), [tabindex]:not([tabindex="-1"])'
852
+ );
853
+ if (focusableEls.length === 0) return;
854
+ const firstFocusableEl = focusableEls[0];
855
+ const lastFocusableEl = focusableEls[focusableEls.length - 1];
856
+ element.addEventListener("keydown", function(e) {
857
+ if (e.key === "Tab") {
858
+ if (e.shiftKey) {
859
+ if (document.activeElement === firstFocusableEl) {
860
+ e.preventDefault();
861
+ lastFocusableEl.focus();
862
+ }
863
+ } else {
864
+ if (document.activeElement === lastFocusableEl) {
865
+ e.preventDefault();
866
+ firstFocusableEl.focus();
867
+ }
878
868
  }
869
+ }
870
+ });
871
+ const closeBtn = element.querySelector(`.${PREFIX}-modal__close-button`);
872
+ if (closeBtn) {
873
+ closeBtn.focus();
874
+ } else {
875
+ firstFocusableEl.focus();
876
+ }
877
+ }
878
+ function openModal(modalEl) {
879
+ if (!modalEl) return;
880
+ modalEl.style.display = "flex";
881
+ document.body.style.overflow = "hidden";
882
+ modalEl.setAttribute("aria-hidden", "false");
883
+ modalEl.classList.remove(
884
+ `${PREFIX}-modal--exit`,
885
+ `${PREFIX}-modal--exit-active`
886
+ );
887
+ modalEl.classList.add(`${PREFIX}-modal--enter`);
888
+ requestAnimationFrame(() => {
889
+ requestAnimationFrame(() => {
890
+ modalEl.classList.add(`${PREFIX}-modal--enter-active`);
891
+ modalEl.classList.remove(`${PREFIX}-modal--enter`);
892
+ trapFocus(modalEl);
879
893
  });
880
- modalOverlay.addEventListener("click", () => {
881
- modalContent.classList.remove(`${PREFIX}-modal__content--show`);
882
- modalOverlay.classList.remove(`${PREFIX}-modal__overlay--show`);
883
- setTimeout(() => {
884
- document.body.style.overflow = "";
885
- }, 300);
886
- });
894
+ });
895
+ }
896
+ function closeModal(modalEl) {
897
+ if (!modalEl) return;
898
+ modalEl.classList.remove(`${PREFIX}-modal--enter-active`);
899
+ modalEl.classList.add(`${PREFIX}-modal--exit-active`);
900
+ document.body.style.overflow = "";
901
+ modalEl.setAttribute("aria-hidden", "true");
902
+ setTimeout(() => {
903
+ modalEl.style.display = "none";
904
+ modalEl.classList.remove(`${PREFIX}-modal--exit-active`);
905
+ }, 300);
906
+ }
907
+ function initModal(rootSelector = `.${PREFIX}-modal`) {
908
+ document.addEventListener("click", (e) => {
909
+ const trigger = e.target.closest(`[data-toggle="modal"]`);
910
+ if (trigger) {
911
+ e.preventDefault();
912
+ const targetSelector = trigger.getAttribute("data-target") || trigger.getAttribute("href");
913
+ const modal = document.querySelector(targetSelector);
914
+ if (modal) {
915
+ modal._previousActiveElement = trigger;
916
+ openModal(modal);
917
+ }
918
+ }
919
+ const dismissBtn = e.target.closest(`[data-dismiss="modal"]`);
920
+ if (dismissBtn) {
921
+ const modal = dismissBtn.closest(rootSelector);
922
+ if (modal) {
923
+ closeModal(modal);
924
+ if (modal._previousActiveElement) {
925
+ modal._previousActiveElement.focus();
926
+ }
927
+ }
928
+ }
929
+ if (e.target.classList.contains(`${PREFIX}-modal`) || e.target.classList.contains(`${PREFIX}-modal__backdrop`)) {
930
+ const modal = e.target.closest(rootSelector);
931
+ if (modal && modal.getAttribute("data-persistent") !== "true") {
932
+ closeModal(modal);
933
+ }
934
+ }
935
+ });
936
+ document.addEventListener("keydown", (e) => {
937
+ if (e.key === "Escape") {
938
+ const openModalEl = document.querySelector(`${rootSelector}[aria-hidden="false"]`) || document.querySelector(`${rootSelector}[style*="display: flex"]`);
939
+ if (openModalEl && openModalEl.getAttribute("data-persistent") !== "true") {
940
+ closeModal(openModalEl);
941
+ if (openModalEl._previousActiveElement) {
942
+ openModalEl._previousActiveElement.focus();
943
+ }
944
+ }
945
+ }
946
+ });
947
+ document.addEventListener("click", (e) => {
948
+ const closeIconBtn = e.target.closest(`.${PREFIX}-modal__close-button`);
949
+ if (closeIconBtn && !closeIconBtn.hasAttribute("data-dismiss")) {
950
+ const modal = closeIconBtn.closest(rootSelector);
951
+ if (modal) {
952
+ closeModal(modal);
953
+ }
954
+ }
887
955
  });
888
956
  }
889
957
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@idds/js",
3
- "version": "1.0.79",
3
+ "version": "1.0.80",
4
4
  "publishConfig": {
5
5
  "access": "public"
6
6
  },