1// Bridges clicks on statically rendered product cards into the interactive 2// ShopItemModalHost island. 3// 4// The cards are plain SSR HTML so they cannot use @onclick. The island imports 5// this same module URL and registers itself; ES modules are cached by the 6// browser, so both sides share one instance and no window global is needed. 7 8let dotNetRef = null; 9let pendingId = null; 10 11export function registerModalHost(ref) { 12 dotNetRef = ref; 13 14 // A card may have been clicked before the circuit finished connecting. 15 if (pendingId !== null) { 16 const id = pendingId; 17 pendingId = null; 18 dotNetRef.invokeMethodAsync('OpenProductAsync', id); 19 } 20} 21 22export function unregisterModalHost() { 23 dotNetRef = null; 24} 25 26function activate(e) { 27 const card = e.target.closest('.gh-shop-card'); 28 if (!card) { 29 return; 30 } 31 32 if (e.type === 'keydown' && e.key !== 'Enter' && e.key !== ' ') { 33 return; 34 } 35 36 e.preventDefault(); 37 38 const id = parseInt(card.dataset.ghProductId, 10); 39 if (Number.isNaN(id)) { 40 return; 41 } 42 43 if (dotNetRef) { 44 dotNetRef.invokeMethodAsync('OpenProductAsync', id); 45 } else { 46 pendingId = id; 47 } 48} 49 50// Delegated so the handlers survive enhanced navigation replacing the grid. 51document.addEventListener('click', activate); 52document.addEventListener('keydown', activate);
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.