| [ Index ] |
PHP Cross Reference of WordPress Trunk (Updated Daily) |
[Summary view] [Print] [Text view]
1 // packages/block-library/build-module/image/view.js 2 import { 3 store, 4 getContext, 5 getElement, 6 withSyncEvent, 7 withScope 8 } from "@wordpress/interactivity"; 9 10 // packages/block-library/build-module/image/constants.js 11 var IMAGE_PRELOAD_DELAY = 200; 12 13 // packages/block-library/build-module/image/view.js 14 var isTouching = false; 15 var lastTouchTime = 0; 16 function getImageSrc({ uploadedSrc }) { 17 return uploadedSrc || "data:image/gif;base64,R0lGODlhAQABAAD/ACwAAAAAAQABAAACADs="; 18 } 19 function getImageSrcset({ lightboxSrcset }) { 20 return lightboxSrcset || ""; 21 } 22 var { state, actions, callbacks } = store( 23 "core/image", 24 { 25 state: { 26 currentImageId: null, 27 preloadTimers: /* @__PURE__ */ new Map(), 28 preloadedImageIds: /* @__PURE__ */ new Set(), 29 get currentImage() { 30 return state.metadata[state.currentImageId]; 31 }, 32 get overlayOpened() { 33 return state.currentImageId !== null; 34 }, 35 get roleAttribute() { 36 return state.overlayOpened ? "dialog" : null; 37 }, 38 get ariaModal() { 39 return state.overlayOpened ? "true" : null; 40 }, 41 get enlargedSrc() { 42 return getImageSrc(state.currentImage); 43 }, 44 get enlargedSrcset() { 45 return getImageSrcset(state.currentImage); 46 }, 47 get figureStyles() { 48 return state.overlayOpened && `$state.currentImage.figureStyles?.replace( 49 /margin[^;]*;?/g, 50 "" 51 )};`; 52 }, 53 get imgStyles() { 54 return state.overlayOpened && `$state.currentImage.imgStyles?.replace( 55 /;$/, 56 "" 57 )}; object-fit:cover;`; 58 }, 59 get imageButtonRight() { 60 const { imageId } = getContext(); 61 return state.metadata[imageId].imageButtonRight; 62 }, 63 get imageButtonTop() { 64 const { imageId } = getContext(); 65 return state.metadata[imageId].imageButtonTop; 66 }, 67 get isContentHidden() { 68 const ctx = getContext(); 69 return state.overlayEnabled && state.currentImageId === ctx.imageId; 70 }, 71 get isContentVisible() { 72 const ctx = getContext(); 73 return !state.overlayEnabled && state.currentImageId === ctx.imageId; 74 } 75 }, 76 actions: { 77 showLightbox() { 78 const { imageId } = getContext(); 79 if (!state.metadata[imageId].imageRef?.complete) { 80 return; 81 } 82 state.scrollTopReset = document.documentElement.scrollTop; 83 state.scrollLeftReset = document.documentElement.scrollLeft; 84 state.overlayEnabled = true; 85 state.currentImageId = imageId; 86 callbacks.setOverlayStyles(); 87 }, 88 hideLightbox() { 89 if (state.overlayEnabled) { 90 state.overlayEnabled = false; 91 setTimeout(function() { 92 state.currentImage.buttonRef.focus({ 93 preventScroll: true 94 }); 95 state.currentImageId = null; 96 }, 450); 97 } 98 }, 99 handleKeydown: withSyncEvent((event) => { 100 if (state.overlayEnabled) { 101 if (event.key === "Tab") { 102 event.preventDefault(); 103 const { ref } = getElement(); 104 ref.querySelector("button").focus(); 105 } 106 if (event.key === "Escape") { 107 actions.hideLightbox(); 108 } 109 } 110 }), 111 handleTouchMove: withSyncEvent((event) => { 112 if (state.overlayEnabled) { 113 event.preventDefault(); 114 } 115 }), 116 handleTouchStart() { 117 isTouching = true; 118 }, 119 handleTouchEnd() { 120 lastTouchTime = Date.now(); 121 isTouching = false; 122 }, 123 handleScroll() { 124 if (state.overlayOpened) { 125 if (!isTouching && Date.now() - lastTouchTime > 450) { 126 window.scrollTo( 127 state.scrollLeftReset, 128 state.scrollTopReset 129 ); 130 } 131 } 132 }, 133 preloadImage() { 134 const { imageId } = getContext(); 135 if (state.preloadedImageIds.has(imageId)) { 136 return; 137 } 138 const imageMetadata = state.metadata[imageId]; 139 const imageLink = document.createElement("link"); 140 imageLink.rel = "preload"; 141 imageLink.as = "image"; 142 imageLink.href = getImageSrc(imageMetadata); 143 const srcset = getImageSrcset(imageMetadata); 144 if (srcset) { 145 imageLink.setAttribute("imagesrcset", srcset); 146 imageLink.setAttribute("imagesizes", "100vw"); 147 } 148 document.head.appendChild(imageLink); 149 state.preloadedImageIds.add(imageId); 150 }, 151 preloadImageWithDelay() { 152 const { imageId } = getContext(); 153 actions.cancelPreload(); 154 const timerId = setTimeout( 155 withScope(() => { 156 actions.preloadImage(); 157 state.preloadTimers.delete(imageId); 158 }), 159 IMAGE_PRELOAD_DELAY 160 ); 161 state.preloadTimers.set(imageId, timerId); 162 }, 163 cancelPreload() { 164 const { imageId } = getContext(); 165 if (state.preloadTimers.has(imageId)) { 166 clearTimeout(state.preloadTimers.get(imageId)); 167 state.preloadTimers.delete(imageId); 168 } 169 } 170 }, 171 callbacks: { 172 setOverlayStyles() { 173 if (!state.overlayEnabled) { 174 return; 175 } 176 let { 177 naturalWidth, 178 naturalHeight, 179 offsetWidth: originalWidth, 180 offsetHeight: originalHeight 181 } = state.currentImage.imageRef; 182 let { x: screenPosX, y: screenPosY } = state.currentImage.imageRef.getBoundingClientRect(); 183 const naturalRatio = naturalWidth / naturalHeight; 184 let originalRatio = originalWidth / originalHeight; 185 if (state.currentImage.scaleAttr === "contain") { 186 if (naturalRatio > originalRatio) { 187 const heightWithoutSpace = originalWidth / naturalRatio; 188 screenPosY += (originalHeight - heightWithoutSpace) / 2; 189 originalHeight = heightWithoutSpace; 190 } else { 191 const widthWithoutSpace = originalHeight * naturalRatio; 192 screenPosX += (originalWidth - widthWithoutSpace) / 2; 193 originalWidth = widthWithoutSpace; 194 } 195 } 196 originalRatio = originalWidth / originalHeight; 197 let imgMaxWidth = parseFloat( 198 state.currentImage.targetWidth !== "none" ? state.currentImage.targetWidth : naturalWidth 199 ); 200 let imgMaxHeight = parseFloat( 201 state.currentImage.targetHeight !== "none" ? state.currentImage.targetHeight : naturalHeight 202 ); 203 let imgRatio = imgMaxWidth / imgMaxHeight; 204 let containerMaxWidth = imgMaxWidth; 205 let containerMaxHeight = imgMaxHeight; 206 let containerWidth = imgMaxWidth; 207 let containerHeight = imgMaxHeight; 208 if (naturalRatio.toFixed(2) !== imgRatio.toFixed(2)) { 209 if (naturalRatio > imgRatio) { 210 const reducedHeight = imgMaxWidth / naturalRatio; 211 if (imgMaxHeight - reducedHeight > imgMaxWidth) { 212 imgMaxHeight = reducedHeight; 213 imgMaxWidth = reducedHeight * naturalRatio; 214 } else { 215 imgMaxHeight = imgMaxWidth / naturalRatio; 216 } 217 } else { 218 const reducedWidth = imgMaxHeight * naturalRatio; 219 if (imgMaxWidth - reducedWidth > imgMaxHeight) { 220 imgMaxWidth = reducedWidth; 221 imgMaxHeight = reducedWidth / naturalRatio; 222 } else { 223 imgMaxWidth = imgMaxHeight * naturalRatio; 224 } 225 } 226 containerWidth = imgMaxWidth; 227 containerHeight = imgMaxHeight; 228 imgRatio = imgMaxWidth / imgMaxHeight; 229 if (originalRatio > imgRatio) { 230 containerMaxWidth = imgMaxWidth; 231 containerMaxHeight = containerMaxWidth / originalRatio; 232 } else { 233 containerMaxHeight = imgMaxHeight; 234 containerMaxWidth = containerMaxHeight * originalRatio; 235 } 236 } 237 if (originalWidth > containerWidth || originalHeight > containerHeight) { 238 containerWidth = originalWidth; 239 containerHeight = originalHeight; 240 } 241 let horizontalPadding = 0; 242 if (window.innerWidth > 480) { 243 horizontalPadding = 80; 244 } else if (window.innerWidth > 1920) { 245 horizontalPadding = 160; 246 } 247 const verticalPadding = 80; 248 const targetMaxWidth = Math.min( 249 window.innerWidth - horizontalPadding, 250 containerWidth 251 ); 252 const targetMaxHeight = Math.min( 253 window.innerHeight - verticalPadding, 254 containerHeight 255 ); 256 const targetContainerRatio = targetMaxWidth / targetMaxHeight; 257 if (originalRatio > targetContainerRatio) { 258 containerWidth = targetMaxWidth; 259 containerHeight = containerWidth / originalRatio; 260 } else { 261 containerHeight = targetMaxHeight; 262 containerWidth = containerHeight * originalRatio; 263 } 264 const containerScale = originalWidth / containerWidth; 265 const lightboxImgWidth = imgMaxWidth * (containerWidth / containerMaxWidth); 266 const lightboxImgHeight = imgMaxHeight * (containerHeight / containerMaxHeight); 267 state.overlayStyles = ` 268 --wp--lightbox-initial-top-position: $screenPosY}px; 269 --wp--lightbox-initial-left-position: $screenPosX}px; 270 --wp--lightbox-container-width: $containerWidth + 1}px; 271 --wp--lightbox-container-height: $containerHeight + 1}px; 272 --wp--lightbox-image-width: $lightboxImgWidth}px; 273 --wp--lightbox-image-height: $lightboxImgHeight}px; 274 --wp--lightbox-scale: $containerScale}; 275 --wp--lightbox-scrollbar-width: $window.innerWidth - document.documentElement.clientWidth}px; 276 `; 277 }, 278 setButtonStyles() { 279 const { ref } = getElement(); 280 if (!ref) { 281 return; 282 } 283 const { imageId } = getContext(); 284 state.metadata[imageId].imageRef = ref; 285 state.metadata[imageId].currentSrc = ref.currentSrc; 286 const { 287 naturalWidth, 288 naturalHeight, 289 offsetWidth, 290 offsetHeight 291 } = ref; 292 if (naturalWidth === 0 || naturalHeight === 0) { 293 return; 294 } 295 const figure = ref.parentElement; 296 const figureWidth = ref.parentElement.clientWidth; 297 let figureHeight = ref.parentElement.clientHeight; 298 const caption = figure.querySelector("figcaption"); 299 if (caption) { 300 const captionComputedStyle = window.getComputedStyle(caption); 301 if (!["absolute", "fixed"].includes( 302 captionComputedStyle.position 303 )) { 304 figureHeight = figureHeight - caption.offsetHeight - parseFloat(captionComputedStyle.marginTop) - parseFloat(captionComputedStyle.marginBottom); 305 } 306 } 307 const buttonOffsetTop = figureHeight - offsetHeight; 308 const buttonOffsetRight = figureWidth - offsetWidth; 309 let imageButtonTop = buttonOffsetTop + 16; 310 let imageButtonRight = buttonOffsetRight + 16; 311 if (state.metadata[imageId].scaleAttr === "contain") { 312 const naturalRatio = naturalWidth / naturalHeight; 313 const offsetRatio = offsetWidth / offsetHeight; 314 if (naturalRatio >= offsetRatio) { 315 const referenceHeight = offsetWidth / naturalRatio; 316 imageButtonTop = (offsetHeight - referenceHeight) / 2 + buttonOffsetTop + 16; 317 imageButtonRight = buttonOffsetRight + 16; 318 } else { 319 const referenceWidth = offsetHeight * naturalRatio; 320 imageButtonTop = buttonOffsetTop + 16; 321 imageButtonRight = (offsetWidth - referenceWidth) / 2 + buttonOffsetRight + 16; 322 } 323 } 324 state.metadata[imageId].imageButtonTop = imageButtonTop; 325 state.metadata[imageId].imageButtonRight = imageButtonRight; 326 }, 327 setOverlayFocus() { 328 if (state.overlayEnabled) { 329 const { ref } = getElement(); 330 ref.focus(); 331 } 332 }, 333 initTriggerButton() { 334 const { imageId } = getContext(); 335 const { ref } = getElement(); 336 state.metadata[imageId].buttonRef = ref; 337 } 338 } 339 }, 340 { lock: true } 341 );
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
| Generated : Tue Apr 28 08:20:12 2026 | Cross-referenced by PHPXref |