UNPKG

react-a11y-dialog

Version:

A React component wrapper and React hook around a11y-dialog.

3 lines (2 loc) 6.38 kB
/*! react-a11y-dialog 7.4.1 — © Kitty Giraudel */ "use strict";var e=require("react"),t=require("react-dom");function i(e){var t=Object.create(null);return e&&Object.keys(e).forEach((function(i){if("default"!==i){var n=Object.getOwnPropertyDescriptor(e,i);Object.defineProperty(t,i,n.get?n:{enumerable:!0,get:function(){return e[i]}})}})),t.default=e,Object.freeze(t)}var n=i(e),o=i(t);const s=":not([inert]):not([inert] *)",r=':not([tabindex^="-"])',l=":not(:disabled)";var a=[`a[href]${s}${r}`,`area[href]${s}${r}`,`input:not([type="hidden"]):not([type="radio"])${s}${r}${l}`,`input[type="radio"]${s}${r}${l}`,`select${s}${r}${l}`,`textarea${s}${r}${l}`,`button${s}${r}${l}`,`details${s} > summary:first-of-type${r}`,`iframe${s}${r}`,`audio[controls]${s}${r}`,`video[controls]${s}${r}`,`[contenteditable]${s}${r}`,`[tabindex]${s}${r}`];function d(e){(e.querySelector("[autofocus]")||e).focus()}function u(e,t){if(t&&f(e))return e;if(function(e){return(!e.shadowRoot||"-1"!==e.getAttribute("tabindex"))&&!e.matches(":disabled,[hidden],[inert]")}(e))if(e.shadowRoot){let i=c(e.shadowRoot,t);for(;i;){const e=u(i,t);if(e)return e;i=h(i,t)}}else if("slot"===e.localName){const i=e.assignedElements({flatten:!0});t||i.reverse();for(const e of i){const i=u(e,t);if(i)return i}}else{let i=c(e,t);for(;i;){const e=u(i,t);if(e)return e;i=h(i,t)}}return!t&&f(e)?e:null}function c(e,t){return t?e.firstElementChild:e.lastElementChild}function h(e,t){return t?e.nextElementSibling:e.previousElementSibling}const f=e=>!e.shadowRoot?.delegatesFocus&&(e.matches(a.join(","))&&!(e=>!(!e.matches("details:not([open]) *")||e.matches("details>summary:first-of-type"))||!(e.offsetWidth||e.offsetHeight||e.getClientRects().length))(e));function m(e=document){const t=e.activeElement;return t?t.shadowRoot?m(t.shadowRoot)||document.activeElement:t:null}function $(e,t){const[i,n]=function(e){const t=u(e,!0);return[t,t?u(e,!1)||t:null]}(e);if(!i)return t.preventDefault();const o=m();t.shiftKey&&o===i?(n.focus(),t.preventDefault()):t.shiftKey||o!==n||(i.focus(),t.preventDefault())}function y(e,t){return function t(i){if(!i||i===document||i===window)return null;const n=b(i);return n&&(i=n),i.closest(e)||t(i.getRootNode().host)}(t)}function b(e){return e.assignedSlot||(e.parentNode?b(e.parentNode):null)}const v="data-a11y-dialog";let p=class{$el;id;previouslyFocused;shown;constructor(e){this.$el=e,this.id=this.$el.getAttribute(v)||this.$el.id,this.previouslyFocused=null,this.shown=!1,this.maintainFocus=this.maintainFocus.bind(this),this.bindKeypress=this.bindKeypress.bind(this),this.handleTriggerClicks=this.handleTriggerClicks.bind(this),this.show=this.show.bind(this),this.hide=this.hide.bind(this),this.$el.setAttribute("aria-hidden","true"),this.$el.setAttribute("aria-modal","true"),this.$el.setAttribute("tabindex","-1"),this.$el.hasAttribute("role")||this.$el.setAttribute("role","dialog"),document.addEventListener("click",this.handleTriggerClicks,!0)}destroy(){return this.fire("destroy").defaultPrevented||(this.hide(),document.removeEventListener("click",this.handleTriggerClicks,!0),this.$el.replaceWith(this.$el.cloneNode(!0))),this}show(e){if(this.shown)return this;return this.fire("show",e).defaultPrevented||(this.shown=!0,this.$el.removeAttribute("aria-hidden"),this.previouslyFocused=m(),"BODY"===this.previouslyFocused?.tagName&&e?.target&&(this.previouslyFocused=e.target),"focus"===e?.type?this.maintainFocus():d(this.$el),document.body.addEventListener("focus",this.maintainFocus,!0),this.$el.addEventListener("keydown",this.bindKeypress,!0)),this}hide(e){if(!this.shown)return this;return this.fire("hide",e).defaultPrevented||(this.shown=!1,this.$el.setAttribute("aria-hidden","true"),this.previouslyFocused?.focus?.(),document.body.removeEventListener("focus",this.maintainFocus,!0),this.$el.removeEventListener("keydown",this.bindKeypress,!0)),this}on(e,t,i){return this.$el.addEventListener(e,t,i),this}off(e,t,i){return this.$el.removeEventListener(e,t,i),this}fire(e,t){const i=new CustomEvent(e,{detail:t,cancelable:!0});return this.$el.dispatchEvent(i),i}handleTriggerClicks(e){const t=e.composedPath()[0],i=y(`[${v}-show="${this.id}"]`,t),n=y(`[${v}-hide="${this.id}"]`,t),o=y(`[${v}-hide]`,t)&&y('[aria-modal="true"]',t)===this.$el;i&&this.show(e),(n||o)&&this.hide(e)}bindKeypress(e){if(y('[aria-modal="true"]',m())!==this.$el)return;let t=!1;try{t=!!this.$el.querySelector('[popover]:not([popover="manual"]):popover-open')}catch{}"Escape"!==e.key||"alertdialog"===this.$el.getAttribute("role")||t||(e.preventDefault(),this.hide(e)),"Tab"===e.key&&$(this.$el,e)}maintainFocus(){const e=m();y(`[aria-modal="true"], [${v}-ignore-focus-trap]`,e)||d(this.$el)}};function g(){for(const e of document.querySelectorAll("[data-a11y-dialog]"))new p(e)}"undefined"!=typeof document&&("loading"===document.readyState?document.addEventListener("DOMContentLoaded",g):g());const E=e=>{const{role:t="dialog",id:i,titleId:o=`${i}-title`}=e,[s,r]=(()=>{const[e,t]=n.useState(null);return[e,n.useCallback((e=>{null!==e&&t(new p(e))}),[])]})(),l=n.useCallback((()=>s?.hide()),[s]),a="alertdialog"===t;return n.useEffect((()=>()=>{s&&s.destroy()}),[s]),[s,{container:{id:i,ref:r,role:t,tabIndex:-1,"aria-modal":!0,"aria-hidden":!0,"aria-labelledby":o},overlay:{onClick:a?void 0:l},dialog:{role:"document"},closeButton:{type:"button",onClick:l},title:{role:"heading","aria-level":1,id:o}}]};exports.A11yDialog=e=>{const{role:t="dialog",id:i,titleId:s=`${i}-title`,closeButtonLabel:r="Close this dialog window",closeButtonContent:l="×",closeButtonPosition:a="first",classNames:d={},dialogRef:u=(()=>{}),dialogRoot:c,title:h,children:f}=e,m=(()=>{const[e,t]=n.useState(!1);return n.useEffect((()=>t(!0)),[]),e})(),[$,y]=E({role:t,id:i,titleId:s});if(n.useEffect((()=>($&&u($),()=>{u(void 0)})),[u,$]),!m)return null;const b=(e=>{if(e instanceof Element)return e;if("string"==typeof e){const t=document.querySelector(e);if(t)return t}return document.body})(c),v=n.createElement("button",{...y.closeButton,className:d.closeButton,"aria-label":r,key:"button"},l);return o.createPortal(n.createElement("div",{...y.container,className:d.container},n.createElement("div",{...y.overlay,className:d.overlay}),n.createElement("div",{...y.dialog,className:d.dialog},"first"===a&&v,n.createElement("p",{...y.title,className:d.title},h),f,"last"===a&&v)),b)},exports.useA11yDialog=E;