@boyernick/standard-ui-react 0.4.2-canary.53 → 0.4.2-canary.54
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/src/modal.tsx +25 -1
package/package.json
CHANGED
package/src/modal.tsx
CHANGED
|
@@ -174,15 +174,39 @@ const ModalImage = ({
|
|
|
174
174
|
}: Pick<GalleryItem, "src" | "alt" | "imgProps"> & {
|
|
175
175
|
fit?: "viewport" | "contain"
|
|
176
176
|
}) => {
|
|
177
|
-
const { className, ...props } = imgProps ?? {}
|
|
177
|
+
const { className, onLoad, onError, ...props } = imgProps ?? {}
|
|
178
|
+
// Held transparent until decoded, then faded in: a large file otherwise
|
|
179
|
+
// paints in top-down bands inside the lightbox. The ref catches an image the
|
|
180
|
+
// browser already has (a cached file, or the one the trigger just showed)
|
|
181
|
+
// before first paint, so it appears at once with nothing to fade.
|
|
182
|
+
const [loaded, setLoaded] = useState(false)
|
|
183
|
+
const catchLoaded = useCallback((image: HTMLImageElement | null) => {
|
|
184
|
+
if (image?.complete && image.naturalWidth > 0) setLoaded(true)
|
|
185
|
+
}, [])
|
|
178
186
|
|
|
179
187
|
return (
|
|
180
188
|
// eslint-disable-next-line @next/next/no-img-element
|
|
181
189
|
<img
|
|
190
|
+
ref={catchLoaded}
|
|
182
191
|
src={src}
|
|
183
192
|
alt={alt}
|
|
184
193
|
draggable={false}
|
|
194
|
+
onLoad={(event) => {
|
|
195
|
+
onLoad?.(event)
|
|
196
|
+
event.currentTarget
|
|
197
|
+
.decode()
|
|
198
|
+
.catch(() => {})
|
|
199
|
+
.then(() => setLoaded(true))
|
|
200
|
+
}}
|
|
201
|
+
onError={(event) => {
|
|
202
|
+
onError?.(event)
|
|
203
|
+
// Reveal the broken image rather than leave an invisible one.
|
|
204
|
+
setLoaded(true)
|
|
205
|
+
}}
|
|
185
206
|
className={cn(
|
|
207
|
+
// Linear, like every fade in `motion` — see the note there.
|
|
208
|
+
"transition-opacity duration-[var(--duration-lg)] ease-linear motion-reduce:transition-none",
|
|
209
|
+
!loaded && "opacity-0",
|
|
186
210
|
"rounded-lg object-contain shadow-lg select-none",
|
|
187
211
|
fit === "contain"
|
|
188
212
|
? "max-h-full max-w-full"
|