1import { createModal } from '../../ui/modal.js'; 2 3const initContactModal = () => { 4 const root = document.querySelector('[data-contact-modal]'); 5 if (!root) return; 6 7 if (root.dataset.initialized === 'true') return; 8 root.dataset.initialized = 'true'; 9 10 const overlay = root.querySelector('[data-contact-overlay]'); 11 const panel = root.querySelector('[role="dialog"]'); 12 const closeButton = root.querySelector('[data-modal-close]'); 13 const emailLink = root.querySelector('[data-contact-email-link]'); 14 15 const syncTriggerState = (isOpen) => { 16 document.querySelectorAll('[data-contact-trigger]').forEach((trigger) => { 17 trigger.setAttribute('aria-expanded', String(isOpen)); 18 }); 19 }; 20 21 const syncEmailLink = () => { 22 if (!emailLink) { 23 return; 24 } 25 const email = window.SERVER_DATA?.hostInfo?.supportEmail; 26 if (!email) { 27 return; 28 } 29 emailLink.setAttribute('href', `mailto:${email}`); 30 }; 31 32 syncEmailLink(); 33 syncTriggerState(false); 34 35 const modal = createModal({ 36 root, 37 panel, 38 overlay, 39 openTriggerSelector: '[data-contact-trigger]', 40 closeOnOverlay: true, 41 closeOnEsc: true, 42 trapFocus: true, 43 restoreFocus: true, 44 initialFocus: () => emailLink || closeButton, 45 onOpen: () => { 46 syncEmailLink(); 47 syncTriggerState(true); 48 }, 49 onClose: () => syncTriggerState(false), 50 }); 51 52 if (!modal) return; 53 54 // Close handled by shared modal close trigger. 55}; 56 57initContactModal();
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.