diff --git a/components/NotionPage.tsx b/components/NotionPage.tsx
index 47a655dd9a..629d3ce248 100644
--- a/components/NotionPage.tsx
+++ b/components/NotionPage.tsx
@@ -7,8 +7,12 @@ import { type PageBlock } from 'notion-types'
import { formatDate, getBlockTitle, getPageProperty } from 'notion-utils'
import * as React from 'react'
import BodyClassName from 'react-body-classname'
-import { type NotionComponents, NotionRenderer } from 'react-notion-x'
-import TweetEmbed from 'react-tweet-embed'
+import {
+ type NotionComponents,
+ NotionRenderer,
+ useNotionContext
+} from 'react-notion-x'
+import { EmbeddedTweet, TweetNotFound, TweetSkeleton } from 'react-tweet'
import { useSearchParam } from 'react-use'
import type * as types from '@/lib/types'
@@ -97,7 +101,14 @@ const Modal = dynamic(
)
function Tweet({ id }: { id: string }) {
- return
+ const { recordMap } = useNotionContext()
+ const tweet = (recordMap as types.ExtendedTweetRecordMap)?.tweets?.[id]
+
+ return (
+ }>
+ {tweet ? : }
+
+ )
}
const propertyLastEditedTimeValue = (
diff --git a/lib/get-tweets.ts b/lib/get-tweets.ts
new file mode 100644
index 0000000000..9618266e3e
--- /dev/null
+++ b/lib/get-tweets.ts
@@ -0,0 +1,62 @@
+import { type ExtendedRecordMap } from 'notion-types'
+import { getPageTweetIds } from 'notion-utils'
+import pMap from 'p-map'
+import pMemoize from 'p-memoize'
+import { getTweet as getTweetData } from 'react-tweet/api'
+
+import type { ExtendedTweetRecordMap } from './types'
+import { db } from './db'
+
+export async function getTweetsMap(
+ recordMap: ExtendedRecordMap
+): Promise {
+ const tweetIds = getPageTweetIds(recordMap)
+
+ const tweetsMap = Object.fromEntries(
+ await pMap(
+ tweetIds,
+ async (tweetId: string) => {
+ return [tweetId, await getTweet(tweetId)]
+ },
+ {
+ concurrency: 8
+ }
+ )
+ )
+
+ ;(recordMap as ExtendedTweetRecordMap).tweets = tweetsMap
+}
+
+async function getTweetImpl(tweetId: string): Promise {
+ if (!tweetId) return null
+
+ const cacheKey = `tweet:${tweetId}`
+
+ try {
+ try {
+ const cachedTweet = await db.get(cacheKey)
+ if (cachedTweet) {
+ return cachedTweet
+ }
+ } catch (err) {
+ // ignore redis errors
+ console.warn(`redis error get "${cacheKey}"`, err.message)
+ }
+
+ const tweetData = await getTweetData(tweetId)
+
+ try {
+ await db.set(cacheKey, tweetData)
+ } catch (err) {
+ // ignore redis errors
+ console.warn(`redis error set "${cacheKey}"`, err.message)
+ }
+
+ return tweetData
+ } catch (err: any) {
+ console.warn('failed to get tweet', tweetId, err.message)
+ return null
+ }
+}
+
+export const getTweet = pMemoize(getTweetImpl)
diff --git a/lib/notion.ts b/lib/notion.ts
index d0723556df..35f40001cb 100644
--- a/lib/notion.ts
+++ b/lib/notion.ts
@@ -12,6 +12,7 @@ import {
navigationLinks,
navigationStyle
} from './config'
+import { getTweetsMap } from './get-tweets'
import { notion } from './notion-api'
import { getPreviewImageMap } from './preview-images'
@@ -64,6 +65,8 @@ export async function getPage(pageId: string): Promise {
;(recordMap as any).preview_images = previewImageMap
}
+ await getTweetsMap(recordMap)
+
return recordMap
}
diff --git a/lib/types.ts b/lib/types.ts
index 2972167f86..e1d38d2bec 100644
--- a/lib/types.ts
+++ b/lib/types.ts
@@ -18,6 +18,10 @@ export interface PageProps {
error?: PageError
}
+export interface ExtendedTweetRecordMap extends ExtendedRecordMap {
+ tweets: Record
+}
+
export interface Params extends ParsedUrlQuery {
pageId: string
}
diff --git a/next.config.js b/next.config.js
index 9faccb9f23..33fa61993f 100644
--- a/next.config.js
+++ b/next.config.js
@@ -10,41 +10,12 @@ export default withBundleAnalyzer({
staticPageGenerationTimeout: 300,
images: {
remotePatterns: [
- {
- protocol: 'https',
- hostname: 'www.notion.so',
- pathname: '**'
- },
- {
- protocol: 'https',
- hostname: 'notion.so',
- pathname: '**'
- },
- {
- protocol: 'https',
- hostname: 'images.unsplash.com',
- pathname: '**'
- },
- {
- protocol: 'https',
- hostname: 'pbs.twimg.com',
- pathname: '**'
- },
- {
- protocol: 'https',
- hostname: 'abs.twimg.com',
- pathname: '**'
- },
- {
- protocol: 'https',
- hostname: 's3.us-west-2.amazonaws.com',
- pathname: '**'
- },
- {
- protocol: 'https',
- hostname: 'transitivebullsh.it',
- pathname: '**'
- }
+ { protocol: 'https', hostname: 'www.notion.so' },
+ { protocol: 'https', hostname: 'notion.so' },
+ { protocol: 'https', hostname: 'images.unsplash.com' },
+ { protocol: 'https', hostname: 'abs.twimg.com' },
+ { protocol: 'https', hostname: 'pbs.twimg.com' },
+ { protocol: 'https', hostname: 's3.us-west-2.amazonaws.com' }
],
formats: ['image/avif', 'image/webp'],
dangerouslyAllowSVG: true,
@@ -62,5 +33,8 @@ export default withBundleAnalyzer({
'node_modules/react-dom'
)
return config
- }
+ },
+
+ // See https://react-tweet.vercel.app/next#troubleshooting
+ transpilePackages: ['react-tweet']
})
diff --git a/package.json b/package.json
index e05d3d0388..452b457dfb 100644
--- a/package.json
+++ b/package.json
@@ -40,9 +40,9 @@
"ky": "^1.7.2",
"lqip-modern": "^2.2.1",
"next": "^15.0.3",
- "notion-client": "^7.1.1",
- "notion-types": "^7.1.1",
- "notion-utils": "^7.1.1",
+ "notion-client": "^7.1.3",
+ "notion-types": "^7.1.3",
+ "notion-utils": "^7.1.3",
"p-map": "^7.0.2",
"p-memoize": "^7.1.1",
"posthog-js": "^1.181.0",
@@ -50,8 +50,8 @@
"react": "^18.2.0",
"react-body-classname": "^1.3.1",
"react-dom": "^18.2.0",
- "react-notion-x": "^7.2.1",
- "react-tweet-embed": "^2.0.0",
+ "react-notion-x": "^7.2.3",
+ "react-tweet": "^3.2.1",
"react-use": "^17.4.2",
"rss": "^1.2.2"
},
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index 41495f524a..be02629a53 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -39,14 +39,14 @@ importers:
specifier: ^15.0.3
version: 15.0.3(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
notion-client:
- specifier: ^7.1.1
- version: 7.1.1
+ specifier: ^7.1.3
+ version: 7.1.3
notion-types:
- specifier: ^7.1.1
- version: 7.1.1
+ specifier: ^7.1.3
+ version: 7.1.3
notion-utils:
- specifier: ^7.1.1
- version: 7.1.1
+ specifier: ^7.1.3
+ version: 7.1.3
p-map:
specifier: ^7.0.2
version: 7.0.2
@@ -69,11 +69,11 @@ importers:
specifier: ^18.2.0
version: 18.3.1(react@18.3.1)
react-notion-x:
- specifier: ^7.2.1
- version: 7.2.1(@babel/runtime@7.26.0)(@types/react@18.3.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
- react-tweet-embed:
- specifier: ^2.0.0
- version: 2.0.0(react@18.3.1)
+ specifier: ^7.2.3
+ version: 7.2.3(@babel/runtime@7.26.0)(@types/react@18.3.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
+ react-tweet:
+ specifier: ^3.2.1
+ version: 3.2.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
react-use:
specifier: ^17.4.2
version: 17.5.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
@@ -1627,16 +1627,16 @@ packages:
resolution: {integrity: sha512-IO9QvjUMWxPQQhs60oOu10CRkWCiZzSUkzbXGGV9pviYl1fXYcvkzQ5jV9z8Y6un8ARoVRl4EtC6v6jNqbaJ/w==}
engines: {node: '>=14.16'}
- notion-client@7.1.1:
- resolution: {integrity: sha512-mT/yEOIlbQzIAMsuIoWMX3XQrkoN07NMtSilDYIQQShxYJDdXMYfLuSoOgalEwFmwwsDnETHJqfrdkfe6sF9Rw==}
+ notion-client@7.1.3:
+ resolution: {integrity: sha512-84K4h/pD8fSIth5cKF0qUcHTqGdzzQ6x6hMVErZzbIFcXlOmJvHROd+no5epcMnw1juuIdeDbodN/wT8+U53OA==}
engines: {node: '>=18'}
- notion-types@7.1.1:
- resolution: {integrity: sha512-wsj/mwTi0hZjldvfVoKgtrXrOaBRgEsXic2n1kh6S1Aj7snx9Xo8sA8KtHqmXqKhJ8BFEsavh0Dv3TlyMv8aWg==}
+ notion-types@7.1.3:
+ resolution: {integrity: sha512-kUcMa5SXpzNxmE9PdrSjiP1lmba8ue7+KdMjcmq8QO/wOmdmXCKhr1FHXNqP5Wdxmm2i9sDq87x0S1pA/vJ4kg==}
engines: {node: '>=18'}
- notion-utils@7.1.1:
- resolution: {integrity: sha512-Hks/sipBA7aDZ3TS90CRKuKvCsvs/cW+MXzZPFh/Q1uTjhEt9GynSUl8o11k+Nm4No3+deQJY/hsuv90gyCFjg==}
+ notion-utils@7.1.3:
+ resolution: {integrity: sha512-52dReJMdEBt6O4f/Y9FZqhRNBoDY73p0i1XSqpunaTzxIQW61St6a+8bhZ0HiFPpXvxPUw7HCBfNAqn0CrmF2A==}
engines: {node: '>=18'}
npm-normalize-package-bin@4.0.0:
@@ -1883,8 +1883,8 @@ packages:
react: ^0.14.0 || ^15.0.0 || ^16 || ^17 || ^18
react-dom: ^0.14.0 || ^15.0.0 || ^16 || ^17 || ^18
- react-notion-x@7.2.1:
- resolution: {integrity: sha512-wy/MOp/+pOL/qKUcY3azMvTn/y6AkKqutFboOKn0OUouPe2OaOjUk/VIGFV081UL7+nwCKbWecHgRZ9MuwwHng==}
+ react-notion-x@7.2.3:
+ resolution: {integrity: sha512-eTRkypql15+Uej00MvkG8cWhbt5PDFmj4Zfvyr7582GPblefHFDmtTZOxMiVJhSU7Kv8LZEuGXsYQtFE1cQPqQ==}
engines: {node: '>=18'}
peerDependencies:
react: '>=18'
@@ -1905,10 +1905,11 @@ packages:
peerDependencies:
react: ^16.3.0 || ^17.0.0 || ^18.0.0
- react-tweet-embed@2.0.0:
- resolution: {integrity: sha512-g2kfPjSRTOKeJtaQF5EMuSTmp/q8I0qdDs/pZ2qLXZjCWExDT/JgjxSlyM65NyNzsz8072PDpvlO/sIXwwVpdQ==}
+ react-tweet@3.2.1:
+ resolution: {integrity: sha512-dktP3RMuwRB4pnSDocKpSsW5Hq1IXRW6fONkHhxT5EBIXsKZzdQuI70qtub1XN2dtZdkJWWxfBm/Q+kN+vRYFA==}
peerDependencies:
- react: '>=17'
+ react: '>= 18.0.0'
+ react-dom: '>= 18.0.0'
react-universal-interface@0.6.2:
resolution: {integrity: sha512-dg8yXdcQmvgR13RIlZbTRQOoUrDciFVoSBZILwjE2LFISxZZ8loVJKAkuzswl5js8BHda79bIb2b84ehU8IjXw==}
@@ -2209,6 +2210,11 @@ packages:
resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==}
engines: {node: '>= 0.4'}
+ swr@2.2.5:
+ resolution: {integrity: sha512-QtxqyclFeAsxEUeZIYmsaQ0UjimSq1RZ9Un7I68/0ClKK/U3LoyQunwkQfJZr2fc22DfIXLNDc2wFyTEikCUpg==}
+ peerDependencies:
+ react: ^16.11.0 || ^17.0.0 || ^18.0.0
+
tapable@2.2.1:
resolution: {integrity: sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==}
engines: {node: '>=6'}
@@ -2320,6 +2326,11 @@ packages:
peerDependencies:
react: ^16.8.0 || ^17.0.0
+ use-sync-external-store@1.2.2:
+ resolution: {integrity: sha512-PElTlVMwpblvbNqQ82d2n6RjStvdSoNe9FG28kNfz3WiXilJm4DdNkEzRhCZuIDwY8U08WVihhGR5iRqAwfDiw==}
+ peerDependencies:
+ react: ^16.8.0 || ^17.0.0 || ^18.0.0
+
util-deprecate@1.0.2:
resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==}
@@ -2465,8 +2476,8 @@ snapshots:
'@typescript-eslint/parser': 7.18.0(eslint@8.57.1)(typescript@5.6.3)
'@typescript-eslint/utils': 7.18.0(eslint@8.57.1)(typescript@5.6.3)
eslint-config-prettier: 9.1.0(eslint@8.57.1)
- eslint-import-resolver-typescript: 3.6.3(@typescript-eslint/parser@7.18.0(eslint@8.57.1)(typescript@5.6.3))(eslint-plugin-import@2.31.0)(eslint@8.57.1)
- eslint-plugin-import: 2.31.0(@typescript-eslint/parser@7.18.0(eslint@8.57.1)(typescript@5.6.3))(eslint-import-resolver-typescript@3.6.3)(eslint@8.57.1)
+ eslint-import-resolver-typescript: 3.6.3(@typescript-eslint/parser@7.18.0(eslint@8.57.1)(typescript@5.6.3))(eslint-plugin-import@2.31.0(@typescript-eslint/parser@7.18.0(eslint@8.57.1)(typescript@5.6.3))(eslint@8.57.1))(eslint@8.57.1)
+ eslint-plugin-import: 2.31.0(@typescript-eslint/parser@7.18.0(eslint@8.57.1)(typescript@5.6.3))(eslint-import-resolver-typescript@3.6.3(@typescript-eslint/parser@7.18.0(eslint@8.57.1)(typescript@5.6.3))(eslint-plugin-import@2.31.0(@typescript-eslint/parser@7.18.0(eslint@8.57.1)(typescript@5.6.3))(eslint@8.57.1))(eslint@8.57.1))(eslint@8.57.1)
eslint-plugin-jest: 28.8.3(@typescript-eslint/eslint-plugin@7.18.0(@typescript-eslint/parser@7.18.0(eslint@8.57.1)(typescript@5.6.3))(eslint@8.57.1)(typescript@5.6.3))(eslint@8.57.1)(typescript@5.6.3)
eslint-plugin-jest-dom: 5.4.0(eslint@8.57.1)
eslint-plugin-jsx-a11y: 6.10.2(eslint@8.57.1)
@@ -2980,8 +2991,7 @@ snapshots:
client-only@0.0.1: {}
- clsx@2.1.1:
- optional: true
+ clsx@2.1.1: {}
cluster-key-slot@1.1.2: {}
@@ -3247,37 +3257,37 @@ snapshots:
transitivePeerDependencies:
- supports-color
- eslint-import-resolver-typescript@3.6.3(@typescript-eslint/parser@7.18.0(eslint@8.57.1)(typescript@5.6.3))(eslint-plugin-import@2.31.0)(eslint@8.57.1):
+ eslint-import-resolver-typescript@3.6.3(@typescript-eslint/parser@7.18.0(eslint@8.57.1)(typescript@5.6.3))(eslint-plugin-import@2.31.0(@typescript-eslint/parser@7.18.0(eslint@8.57.1)(typescript@5.6.3))(eslint@8.57.1))(eslint@8.57.1):
dependencies:
'@nolyfill/is-core-module': 1.0.39
debug: 4.3.7
enhanced-resolve: 5.17.1
eslint: 8.57.1
- eslint-module-utils: 2.12.0(@typescript-eslint/parser@7.18.0(eslint@8.57.1)(typescript@5.6.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.3)(eslint@8.57.1)
+ eslint-module-utils: 2.12.0(@typescript-eslint/parser@7.18.0(eslint@8.57.1)(typescript@5.6.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.3(@typescript-eslint/parser@7.18.0(eslint@8.57.1)(typescript@5.6.3))(eslint-plugin-import@2.31.0(@typescript-eslint/parser@7.18.0(eslint@8.57.1)(typescript@5.6.3))(eslint@8.57.1))(eslint@8.57.1))(eslint@8.57.1)
fast-glob: 3.3.2
get-tsconfig: 4.8.1
is-bun-module: 1.2.1
is-glob: 4.0.3
optionalDependencies:
- eslint-plugin-import: 2.31.0(@typescript-eslint/parser@7.18.0(eslint@8.57.1)(typescript@5.6.3))(eslint-import-resolver-typescript@3.6.3)(eslint@8.57.1)
+ eslint-plugin-import: 2.31.0(@typescript-eslint/parser@7.18.0(eslint@8.57.1)(typescript@5.6.3))(eslint-import-resolver-typescript@3.6.3(@typescript-eslint/parser@7.18.0(eslint@8.57.1)(typescript@5.6.3))(eslint-plugin-import@2.31.0(@typescript-eslint/parser@7.18.0(eslint@8.57.1)(typescript@5.6.3))(eslint@8.57.1))(eslint@8.57.1))(eslint@8.57.1)
transitivePeerDependencies:
- '@typescript-eslint/parser'
- eslint-import-resolver-node
- eslint-import-resolver-webpack
- supports-color
- eslint-module-utils@2.12.0(@typescript-eslint/parser@7.18.0(eslint@8.57.1)(typescript@5.6.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.3)(eslint@8.57.1):
+ eslint-module-utils@2.12.0(@typescript-eslint/parser@7.18.0(eslint@8.57.1)(typescript@5.6.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.3(@typescript-eslint/parser@7.18.0(eslint@8.57.1)(typescript@5.6.3))(eslint-plugin-import@2.31.0(@typescript-eslint/parser@7.18.0(eslint@8.57.1)(typescript@5.6.3))(eslint@8.57.1))(eslint@8.57.1))(eslint@8.57.1):
dependencies:
debug: 3.2.7
optionalDependencies:
'@typescript-eslint/parser': 7.18.0(eslint@8.57.1)(typescript@5.6.3)
eslint: 8.57.1
eslint-import-resolver-node: 0.3.9
- eslint-import-resolver-typescript: 3.6.3(@typescript-eslint/parser@7.18.0(eslint@8.57.1)(typescript@5.6.3))(eslint-plugin-import@2.31.0)(eslint@8.57.1)
+ eslint-import-resolver-typescript: 3.6.3(@typescript-eslint/parser@7.18.0(eslint@8.57.1)(typescript@5.6.3))(eslint-plugin-import@2.31.0(@typescript-eslint/parser@7.18.0(eslint@8.57.1)(typescript@5.6.3))(eslint@8.57.1))(eslint@8.57.1)
transitivePeerDependencies:
- supports-color
- eslint-plugin-import@2.31.0(@typescript-eslint/parser@7.18.0(eslint@8.57.1)(typescript@5.6.3))(eslint-import-resolver-typescript@3.6.3)(eslint@8.57.1):
+ eslint-plugin-import@2.31.0(@typescript-eslint/parser@7.18.0(eslint@8.57.1)(typescript@5.6.3))(eslint-import-resolver-typescript@3.6.3(@typescript-eslint/parser@7.18.0(eslint@8.57.1)(typescript@5.6.3))(eslint-plugin-import@2.31.0(@typescript-eslint/parser@7.18.0(eslint@8.57.1)(typescript@5.6.3))(eslint@8.57.1))(eslint@8.57.1))(eslint@8.57.1):
dependencies:
'@rtsao/scc': 1.1.0
array-includes: 3.1.8
@@ -3288,7 +3298,7 @@ snapshots:
doctrine: 2.1.0
eslint: 8.57.1
eslint-import-resolver-node: 0.3.9
- eslint-module-utils: 2.12.0(@typescript-eslint/parser@7.18.0(eslint@8.57.1)(typescript@5.6.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.3)(eslint@8.57.1)
+ eslint-module-utils: 2.12.0(@typescript-eslint/parser@7.18.0(eslint@8.57.1)(typescript@5.6.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.3(@typescript-eslint/parser@7.18.0(eslint@8.57.1)(typescript@5.6.3))(eslint-plugin-import@2.31.0(@typescript-eslint/parser@7.18.0(eslint@8.57.1)(typescript@5.6.3))(eslint@8.57.1))(eslint@8.57.1))(eslint@8.57.1)
hasown: 2.0.2
is-core-module: 2.15.1
is-glob: 4.0.3
@@ -4072,21 +4082,21 @@ snapshots:
normalize-url@8.0.1: {}
- notion-client@7.1.1:
+ notion-client@7.1.3:
dependencies:
ky: 1.7.2
- notion-types: 7.1.1
- notion-utils: 7.1.1
+ notion-types: 7.1.3
+ notion-utils: 7.1.3
p-map: 7.0.2
- notion-types@7.1.1: {}
+ notion-types@7.1.3: {}
- notion-utils@7.1.1:
+ notion-utils@7.1.3:
dependencies:
is-url-superb: 6.1.0
mem: 10.0.0
normalize-url: 8.0.1
- notion-types: 7.1.1
+ notion-types: 7.1.3
p-queue: 8.0.1
npm-normalize-package-bin@4.0.0: {}
@@ -4333,13 +4343,13 @@ snapshots:
react-lifecycles-compat: 3.0.4
warning: 4.0.3
- react-notion-x@7.2.1(@babel/runtime@7.26.0)(@types/react@18.3.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1):
+ react-notion-x@7.2.3(@babel/runtime@7.26.0)(@types/react@18.3.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1):
dependencies:
'@fisch0920/medium-zoom': 1.0.7
'@matejmazur/react-katex': 3.1.3(katex@0.16.11)(react@18.3.1)
katex: 0.16.11
- notion-types: 7.1.1
- notion-utils: 7.1.1
+ notion-types: 7.1.3
+ notion-utils: 7.1.3
prismjs: 1.29.0
react: 18.3.1
react-dom: 18.3.1(react@18.3.1)
@@ -4379,9 +4389,13 @@ snapshots:
dependencies:
react: 18.3.1
- react-tweet-embed@2.0.0(react@18.3.1):
+ react-tweet@3.2.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1):
dependencies:
+ '@swc/helpers': 0.5.13
+ clsx: 2.1.1
react: 18.3.1
+ react-dom: 18.3.1(react@18.3.1)
+ swr: 2.2.5(react@18.3.1)
react-universal-interface@0.6.2(react@18.3.1)(tslib@2.8.1):
dependencies:
@@ -4748,6 +4762,12 @@ snapshots:
supports-preserve-symlinks-flag@1.0.0: {}
+ swr@2.2.5(react@18.3.1):
+ dependencies:
+ client-only: 0.0.1
+ react: 18.3.1
+ use-sync-external-store: 1.2.2(react@18.3.1)
+
tapable@2.2.1: {}
tar@6.2.1:
@@ -4865,6 +4885,10 @@ snapshots:
'@use-it/event-listener': 0.1.7(react@18.3.1)
react: 18.3.1
+ use-sync-external-store@1.2.2(react@18.3.1):
+ dependencies:
+ react: 18.3.1
+
util-deprecate@1.0.2:
optional: true