diff --git a/packages/react-notion-x/package.json b/packages/react-notion-x/package.json index 9cc6c3f37..6cd87f534 100644 --- a/packages/react-notion-x/package.json +++ b/packages/react-notion-x/package.json @@ -64,7 +64,6 @@ "react-fast-compare": "catalog:", "react-hotkeys-hook": "catalog:", "react-image": "catalog:", - "react-lazy-images": "catalog:", "react-modal": "catalog:" }, "devDependencies": { diff --git a/packages/react-notion-x/src/components/lazy-image.tsx b/packages/react-notion-x/src/components/lazy-image.tsx index 7af234d09..768b27170 100644 --- a/packages/react-notion-x/src/components/lazy-image.tsx +++ b/packages/react-notion-x/src/components/lazy-image.tsx @@ -1,6 +1,5 @@ import { normalizeUrl } from 'notion-utils' import React from 'react' -import { ImageState, LazyImageFull } from 'react-lazy-images' import { useNotionContext } from '../context' import { cs } from '../utils' @@ -59,6 +58,23 @@ export function LazyImage({ [zoomable, attachZoom] ) + const [isLazyLoaded, setIsLazyLoaded] = React.useState(false) + const onLoadLazy = React.useCallback(() => { + setIsLazyLoaded(true) + }, []) + + const lazyImageRef = React.useCallback( + (image: HTMLImageElement) => { + attachZoomRef?.(image) + + // if the image is cached, we can trigger the onLoadLazy immediately + if (image.complete) { + onLoadLazy() + } + }, + [attachZoomRef, onLoadLazy] + ) + if (previewImage) { const aspectRatio = previewImage.originalHeight / previewImage.originalWidth @@ -81,60 +97,54 @@ export function LazyImage({ ) } - return ( - // @ts-expect-error LazyImage types are out-of-date. - - {({ imageState, ref }) => { - const isLoaded = imageState === ImageState.LoadSuccess - const wrapperStyle: React.CSSProperties = { - width: '100%' - } - const imgStyle: React.CSSProperties = {} - - if (height) { - wrapperStyle.height = height - } else { - imgStyle.position = 'absolute' - wrapperStyle.paddingBottom = `${aspectRatio * 100}%` - } - - return ( -
- {alt} - - {alt} -
- ) - }} -
- ) + return (() => { + const wrapperStyle: React.CSSProperties = { + width: '100%' + } + const imgStyle: React.CSSProperties = {} + + if (height) { + wrapperStyle.height = height + } else { + imgStyle.position = 'absolute' + wrapperStyle.paddingBottom = `${aspectRatio * 100}%` + } + + return ( +
+ {alt} + + {alt} +
+ ) + })() } else { // TODO: GracefulImage doesn't seem to support refs, but we'd like to prevent // invalid images from loading as error states diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 1b9dbfc19..3b4d0683d 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -120,9 +120,6 @@ catalogs: react-image: specifier: ^4.0.3 version: 4.1.0 - react-lazy-images: - specifier: ^1.1.0 - version: 1.1.0 react-modal: specifier: ^3.16.3 version: 3.16.3 @@ -396,9 +393,6 @@ importers: react-image: specifier: 'catalog:' version: 4.1.0(@babel/runtime@7.27.6)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - react-lazy-images: - specifier: 'catalog:' - version: 1.1.0(react-dom@19.1.0(react@19.1.0))(react@19.1.0) react-modal: specifier: 'catalog:' version: 3.16.3(react-dom@19.1.0(react@19.1.0))(react@19.1.0) @@ -4470,9 +4464,6 @@ packages: resolution: {integrity: sha512-4gd7VpWNQNB4UKKCFFVcp1AVv+FMOgs9NKzjHKusc8jTMhd5eL1NqQqOpE0KzMds804/yHlglp3uxgluOqAPLw==} engines: {node: '>= 0.4'} - invariant@2.2.4: - resolution: {integrity: sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==} - ipaddr.js@1.9.1: resolution: {integrity: sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==} engines: {node: '>= 0.10'} @@ -6238,11 +6229,6 @@ packages: react: '>=16.8' react-dom: '>=16.8' - react-intersection-observer@6.4.2: - resolution: {integrity: sha512-gL6YrkhniA0tIbyDbUterzBwKh61vHR520rsKULel5T37gG4YP07wnWI3WoqOcKK5bKAu0PZB2FHD7/OjawN+w==} - peerDependencies: - react: ^15.0.0 || ^16.0.0 || ^17.0.0 - react-is@16.13.1: resolution: {integrity: sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==} @@ -6252,12 +6238,6 @@ packages: react-is@18.3.1: resolution: {integrity: sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==} - react-lazy-images@1.1.0: - resolution: {integrity: sha512-h5DHFhkMJyh2qsDl3hXWu6d+On10FsgHtRJ+BH7xjgsFOvsqaii9CEwEESqPJrrAiHo1qrN1LgzrV8X3zctHKA==} - peerDependencies: - react: ^15 || ^16 - react-dom: ^15 || ^16 - react-lifecycles-compat@3.0.4: resolution: {integrity: sha512-fBASbA6LnOU9dOU2eW7aQ8xmYBSXUIWr+UmF9b1efZBazGNO+rcXT/icdKnYm2pTwcRylVUYwW7H1PHfLekVzA==} @@ -7230,9 +7210,6 @@ packages: resolution: {integrity: sha512-+QBBXBCvifc56fsbuxZQ6Sic3wqqc3WWaqxs58gvJrcOuN83HGTCwz3oS5phzU9LthRNE9VrJCFCLUgHeeFnfA==} engines: {node: '>=18'} - unionize@2.2.0: - resolution: {integrity: sha512-lHXiL6LPVuRYBGCLOdUd4GMHoAGqM0HtYHAZcA6pUEiwN1nk+LEYlh8bud7saeL0bkFntJzCPEPVVJeFm3Cqsg==} - unique-string@2.0.0: resolution: {integrity: sha512-uNaeirEPvpZWSgzwsPGtU2zVSTrn/8L5q/IexZmH0eH6SA73CmAA5U4GwORTxQAZs95TAXLNqeLoPPNO5gZfWg==} engines: {node: '>=8'} @@ -12349,10 +12326,6 @@ snapshots: hasown: 2.0.2 side-channel: 1.1.0 - invariant@2.2.4: - dependencies: - loose-envify: 1.4.0 - ipaddr.js@1.9.1: {} ipaddr.js@2.2.0: {} @@ -14334,25 +14307,12 @@ snapshots: react: 19.1.0 react-dom: 19.1.0(react@19.1.0) - react-intersection-observer@6.4.2(react@19.1.0): - dependencies: - '@babel/runtime': 7.26.10 - invariant: 2.2.4 - react: 19.1.0 - react-is@16.13.1: {} react-is@17.0.2: {} react-is@18.3.1: {} - react-lazy-images@1.1.0(react-dom@19.1.0(react@19.1.0))(react@19.1.0): - dependencies: - react: 19.1.0 - react-dom: 19.1.0(react@19.1.0) - react-intersection-observer: 6.4.2(react@19.1.0) - unionize: 2.2.0 - react-lifecycles-compat@3.0.4: {} react-modal@3.16.3(react-dom@19.1.0(react@19.1.0))(react@19.1.0): @@ -15572,8 +15532,6 @@ snapshots: unicorn-magic@0.3.0: {} - unionize@2.2.0: {} - unique-string@2.0.0: dependencies: crypto-random-string: 2.0.0 diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml index 05544bd25..7b1d32cd9 100644 --- a/pnpm-workspace.yaml +++ b/pnpm-workspace.yaml @@ -43,7 +43,6 @@ catalog: react-fast-compare: ^3.2.0 react-hotkeys-hook: ^4.5.1 react-image: ^4.0.3 - react-lazy-images: ^1.1.0 react-modal: ^3.16.3 react-scripts: 5.0.1 react-tweet-embed: ^2.0.0