Monorepo for Aesthetic.Computer aesthetic.computer
4
fork

Configure Feed

Select the types of activity you want to include in your feed.

at main 225 lines 7.0 kB view raw
1(function initACMediaModal(global) { 2 if (global.ACMediaModal) return; 3 4 function ensureStyles() { 5 if (document.getElementById("ac-media-modal-styles")) return; 6 const style = document.createElement("style"); 7 style.id = "ac-media-modal-styles"; 8 style.textContent = ` 9 .ac-media-modal { 10 position: fixed; 11 inset: 0; 12 z-index: 9999; 13 display: none; 14 } 15 .ac-media-modal.active { 16 display: block; 17 } 18 .ac-media-modal-backdrop { 19 position: absolute; 20 inset: 0; 21 background: rgba(0, 0, 0, 0.75); 22 } 23 .ac-media-modal-panel { 24 position: relative; 25 z-index: 1; 26 width: min(1000px, calc(100vw - 2rem)); 27 max-height: calc(100vh - 2rem); 28 margin: 1rem auto; 29 overflow: hidden; 30 background: #fff; 31 color: #000; 32 border: 2px solid rgba(205, 92, 155, 0.55); 33 border-radius: 8px; 34 display: flex; 35 flex-direction: column; 36 box-shadow: 0 24px 80px rgba(0, 0, 0, 0.5); 37 } 38 .ac-media-modal-header { 39 padding: 0.9rem 1rem; 40 border-bottom: 1px solid rgba(205, 92, 155, 0.25); 41 background: rgba(205, 92, 155, 0.1); 42 } 43 .ac-media-modal-title { 44 margin: 0; 45 font-size: 1rem; 46 line-height: 1.3; 47 } 48 .ac-media-modal-subtitle { 49 margin-top: 0.3rem; 50 opacity: 0.7; 51 font-size: 0.8rem; 52 } 53 .ac-media-modal-close { 54 position: absolute; 55 top: 0.45rem; 56 right: 0.55rem; 57 border: 1px solid rgba(205, 92, 155, 0.45); 58 border-radius: 4px; 59 background: #fff; 60 color: rgb(205, 92, 155); 61 font-family: monospace; 62 font-size: 0.8rem; 63 cursor: pointer; 64 padding: 0.25rem 0.5rem; 65 } 66 .ac-media-modal-main { 67 padding: 0.9rem 1rem 1rem; 68 overflow: auto; 69 display: grid; 70 gap: 0.8rem; 71 } 72 .ac-media-modal-body { 73 font-size: 0.85rem; 74 line-height: 1.5; 75 } 76 .ac-media-modal-iframe-wrap { 77 border: 1px solid rgba(205, 92, 155, 0.25); 78 border-radius: 6px; 79 overflow: hidden; 80 min-height: 320px; 81 } 82 .ac-media-modal-iframe { 83 width: 100%; 84 height: min(60vh, 560px); 85 border: none; 86 display: block; 87 background: #fff; 88 } 89 .ac-media-modal-actions { 90 display: flex; 91 flex-wrap: wrap; 92 gap: 0.5rem; 93 } 94 .ac-media-modal-action { 95 display: inline-block; 96 padding: 0.38rem 0.65rem; 97 border-radius: 4px; 98 border: 1px solid rgba(205, 92, 155, 0.45); 99 background: rgba(205, 92, 155, 0.12); 100 color: rgb(205, 92, 155); 101 text-decoration: none; 102 font-size: 0.78rem; 103 font-family: monospace; 104 } 105 .ac-media-modal-action:hover { 106 background: rgba(205, 92, 155, 0.2); 107 } 108 @media (prefers-color-scheme: dark) { 109 .ac-media-modal-panel { 110 background: rgb(42, 37, 50); 111 color: rgba(255, 255, 255, 0.92); 112 border-color: rgba(205, 92, 155, 0.6); 113 } 114 .ac-media-modal-header { 115 background: rgba(205, 92, 155, 0.15); 116 } 117 .ac-media-modal-close { 118 background: rgba(255, 255, 255, 0.08); 119 } 120 .ac-media-modal-iframe-wrap { 121 border-color: rgba(255, 255, 255, 0.12); 122 } 123 } 124 `; 125 document.head.appendChild(style); 126 } 127 128 function ensureModal() { 129 let modal = document.getElementById("ac-media-modal"); 130 if (modal) return modal; 131 132 modal = document.createElement("div"); 133 modal.id = "ac-media-modal"; 134 modal.className = "ac-media-modal"; 135 modal.innerHTML = ` 136 <div class="ac-media-modal-backdrop"></div> 137 <div class="ac-media-modal-panel" role="dialog" aria-modal="true"> 138 <button class="ac-media-modal-close" type="button" aria-label="Close">Close</button> 139 <div class="ac-media-modal-header"> 140 <h3 class="ac-media-modal-title"></h3> 141 <div class="ac-media-modal-subtitle"></div> 142 </div> 143 <div class="ac-media-modal-main"> 144 <div class="ac-media-modal-body"></div> 145 <div class="ac-media-modal-iframe-wrap" hidden> 146 <iframe class="ac-media-modal-iframe" loading="lazy" referrerpolicy="no-referrer"></iframe> 147 </div> 148 <div class="ac-media-modal-actions"></div> 149 </div> 150 </div> 151 `; 152 153 const close = function close() { 154 modal.classList.remove("active"); 155 const iframe = modal.querySelector(".ac-media-modal-iframe"); 156 if (iframe) iframe.src = ""; 157 document.body.style.overflow = ""; 158 document.removeEventListener("keydown", onEscape); 159 }; 160 161 const onEscape = function onEscape(event) { 162 if (event.key === "Escape") close(); 163 }; 164 165 modal.querySelector(".ac-media-modal-close").addEventListener("click", close); 166 modal 167 .querySelector(".ac-media-modal-backdrop") 168 .addEventListener("click", close); 169 170 modal.__acClose = close; 171 modal.__acOnEscape = onEscape; 172 173 document.body.appendChild(modal); 174 return modal; 175 } 176 177 function open(options) { 178 const opts = options || {}; 179 ensureStyles(); 180 const modal = ensureModal(); 181 182 const titleEl = modal.querySelector(".ac-media-modal-title"); 183 const subtitleEl = modal.querySelector(".ac-media-modal-subtitle"); 184 const bodyEl = modal.querySelector(".ac-media-modal-body"); 185 const iframeWrap = modal.querySelector(".ac-media-modal-iframe-wrap"); 186 const iframeEl = modal.querySelector(".ac-media-modal-iframe"); 187 const actionsEl = modal.querySelector(".ac-media-modal-actions"); 188 189 titleEl.textContent = opts.title || "Media"; 190 subtitleEl.textContent = opts.subtitle || ""; 191 bodyEl.innerHTML = opts.bodyHtml || ""; 192 193 const iframeUrl = typeof opts.iframeUrl === "string" ? opts.iframeUrl : ""; 194 if (iframeUrl) { 195 iframeEl.src = iframeUrl; 196 iframeWrap.hidden = false; 197 } else { 198 iframeEl.src = ""; 199 iframeWrap.hidden = true; 200 } 201 202 const actions = Array.isArray(opts.actions) ? opts.actions : []; 203 actionsEl.innerHTML = actions 204 .filter((action) => action && typeof action.url === "string" && action.url) 205 .map((action) => { 206 const label = String(action.label || "Open"); 207 const href = String(action.url); 208 return `<a class="ac-media-modal-action" href="${href}" target="_blank" rel="noopener noreferrer">${label}</a>`; 209 }) 210 .join(""); 211 212 modal.classList.add("active"); 213 document.body.style.overflow = "hidden"; 214 document.removeEventListener("keydown", modal.__acOnEscape); 215 document.addEventListener("keydown", modal.__acOnEscape); 216 } 217 218 function close() { 219 const modal = document.getElementById("ac-media-modal"); 220 if (!modal || !modal.__acClose) return; 221 modal.__acClose(); 222 } 223 224 global.ACMediaModal = { open, close }; 225})(window);