diff --git a/.env.example b/.env.example index e18cda4e55..4aefa33202 100644 --- a/.env.example +++ b/.env.example @@ -16,6 +16,9 @@ EXPO_PUBLIC_LOG_LEVEL=debug # Enable debug logs for specific logger instances EXPO_PUBLIC_LOG_DEBUG=session +# Bluesky appview DID +EXPO_PUBLIC_BLUESKY_PROXY_DID= + # Chat service DID EXPO_PUBLIC_CHAT_PROXY_DID= diff --git a/.eslintrc.js b/.eslintrc.js index 59c1b4eb4f..04914bde64 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -34,6 +34,7 @@ module.exports = { 'P', 'Admonition', 'Admonition.Admonition', + 'Toast.Action', 'AgeAssuranceAdmonition', 'Span', ], @@ -110,6 +111,8 @@ module.exports = { 'bskyembed', 'src/locale/locales/_build/', 'src/locale/locales/**/*.js', + '*.e2e.ts', + '*.e2e.tsx', ], settings: { componentWrapperFunctions: ['observer'], diff --git a/__e2e__/flows/composer-self-label.yml b/__e2e__/flows/composer-self-label.yml index b91ff7507f..4539e1e04e 100644 --- a/__e2e__/flows/composer-self-label.yml +++ b/__e2e__/flows/composer-self-label.yml @@ -3,20 +3,26 @@ appId: xyz.blueskyweb.app - runScript: file: ../setupServer.js env: - SERVER_PATH: ?users + SERVER_PATH: ?users - runFlow: file: ../setupApp.yml - tapOn: id: "e2eSignInAlice" +- extendedWaitUntil: + visible: + id: "viewHeaderHomeFeedPrefsBtn" # Post an image with the porn label - assertVisible: - id: "composeFAB" + id: "composeFAB" - tapOn: id: "composeFAB" - inputText: "Post with an image" - tapOn: - id: "openGalleryBtn" + id: "openMediaBtn" +- extendedWaitUntil: + visible: + id: "selectedPhotosView" - tapOn: "Content warnings" - tapOn: "Porn" - tapOn: diff --git a/__e2e__/flows/composer.yml b/__e2e__/flows/composer.yml index d6cf7dff57..62f195de75 100644 --- a/__e2e__/flows/composer.yml +++ b/__e2e__/flows/composer.yml @@ -3,13 +3,17 @@ appId: xyz.blueskyweb.app - runScript: file: ../setupServer.js env: - SERVER_PATH: ?users + SERVER_PATH: ?users - runFlow: file: ../setupApp.yml - tapOn: id: "e2eSignInAlice" +- extendedWaitUntil: + visible: + id: "viewHeaderHomeFeedPrefsBtn" + - assertVisible: - id: "composeFAB" + id: "composeFAB" - tapOn: id: "composeFAB" - inputText: "Post text only" @@ -21,7 +25,10 @@ appId: xyz.blueskyweb.app id: "composeFAB" - inputText: "Post with an image" - tapOn: - id: "openGalleryBtn" + id: "openMediaBtn" +- extendedWaitUntil: + visible: + id: "selectedPhotosView" - tapOn: id: "composerPublishBtn" - assertVisible: @@ -46,7 +53,10 @@ appId: xyz.blueskyweb.app id: "replyBtn" - inputText: "Reply with an image" - tapOn: - id: "openGalleryBtn" + id: "openMediaBtn" +- extendedWaitUntil: + visible: + id: "selectedPhotosView" - tapOn: id: "composerPublishBtn" - assertVisible: @@ -73,7 +83,10 @@ appId: xyz.blueskyweb.app id: "quoteBtn" - inputText: "QP with an image" - tapOn: - id: "openGalleryBtn" + id: "openMediaBtn" +- extendedWaitUntil: + visible: + id: "selectedPhotosView" - tapOn: id: "composerPublishBtn" - assertVisible: diff --git a/__e2e__/flows/create-account.yml b/__e2e__/flows/create-account.yml index 4d49e9b6a8..1290c94bf0 100644 --- a/__e2e__/flows/create-account.yml +++ b/__e2e__/flows/create-account.yml @@ -32,6 +32,9 @@ appId: xyz.blueskyweb.app text: "Not Now" optional: true - inputText: "e2e-test" +- extendedWaitUntil: + visible: + id: "handleAvailableCheck" - tapOn: id: "nextBtn" - +- assertVisible: "Give your profile a face" diff --git a/__e2e__/flows/curate-lists.yml b/__e2e__/flows/curate-lists.yml index fdb71ae7eb..8fe6a2c44c 100644 --- a/__e2e__/flows/curate-lists.yml +++ b/__e2e__/flows/curate-lists.yml @@ -3,11 +3,14 @@ appId: xyz.blueskyweb.app - runScript: file: ../setupServer.js env: - SERVER_PATH: "?users&follows&posts" + SERVER_PATH: "?users&follows&posts" - runFlow: file: ../setupApp.yml - tapOn: id: "e2eSignInAlice" +- extendedWaitUntil: + visible: + id: "viewHeaderHomeFeedPrefsBtn" - tapOn: label: "Create a curate list" @@ -75,9 +78,8 @@ appId: xyz.blueskyweb.app - tapOn: id: "confirmBtn" -- tapOn: - label: "Create a new curatelist" - id: "e2eGotoLists" +- assertVisible: + id: "newUserListBtn" - tapOn: id: "newUserListBtn" - assertVisible: @@ -146,7 +148,7 @@ appId: xyz.blueskyweb.app - tapOn: id: "bottomBarSearchBtn" -- tapOn: "Search for posts, users, or feeds" +- tapOn: "Search for posts, users[,]? or feeds" - inputText: "bob" - tapOn: id: "searchAutoCompleteResult-bob.test" diff --git a/__e2e__/flows/mod-lists.yml b/__e2e__/flows/mod-lists.yml index ef757c5b11..02d76b83ed 100644 --- a/__e2e__/flows/mod-lists.yml +++ b/__e2e__/flows/mod-lists.yml @@ -3,11 +3,14 @@ appId: xyz.blueskyweb.app - runScript: file: ../setupServer.js env: - SERVER_PATH: "?users&follows&labels" + SERVER_PATH: "?users&follows&labels" - runFlow: file: ../setupApp.yml - tapOn: id: "e2eSignInAlice" +- extendedWaitUntil: + visible: + id: "viewHeaderHomeFeedPrefsBtn" # create a modlist - tapOn: @@ -28,20 +31,17 @@ appId: xyz.blueskyweb.app - assertVisible: "Muted Users" - assertVisible: "Shhh" -- tapOn: - label: "Dropdown" - point: "71%,9%" - +# DOES NOT WORK - THE BUTTON IS NOT ACCESSIBLE +# IGNORING FOR NOW, FIX THE COMPONENTS IN THE NEXT RELEASE +# BECAUSE THIS IS A LEGIT A11Y PROBLEM -sfn +- tapOn: "Subscribe to this list" - tapOn: "Mute accounts" - tapOn: "Mute list" - tapOn: "Unmute" -- tapOn: - label: "Dropdown" - point: "71%,9%" - +- tapOn: "Subscribe to this list" - tapOn: "Block accounts" - tapOn: "Block list" - tapOn: "Unblock" - # the rest of the behaviors are tested in curate-lists.yml + # the rest of the behaviors are tested in curate-lists.yml diff --git a/__e2e__/flows/onboarding-avatar-creator.yml b/__e2e__/flows/onboarding-avatar-creator.yml index 3a20053ba5..b8f65b9c38 100644 --- a/__e2e__/flows/onboarding-avatar-creator.yml +++ b/__e2e__/flows/onboarding-avatar-creator.yml @@ -3,11 +3,15 @@ appId: xyz.blueskyweb.app - runScript: file: ../setupServer.js env: - SERVER_PATH: "?users" + SERVER_PATH: "?users" - runFlow: file: ../setupApp.yml - tapOn: id: "e2eSignInAlice" +- extendedWaitUntil: + visible: + id: "viewHeaderHomeFeedPrefsBtn" + - tapOn: id: "e2eStartOnboarding" - tapOn: "Open avatar creator" @@ -21,12 +25,12 @@ appId: xyz.blueskyweb.app - tapOn: "Select the atom emoji as your avatar" - tapOn: "Done" - waitForAnimationToEnd -- tapOn: "Continue to next step" +- tapOn: + id: "onboardingContinue" - assertVisible: "What are your interests?" - tapOn: - label: "Tap on continue" - point: "50%,92%" + id: "onboardingContinue" - assertVisible: "You're ready to go!" - tapOn: - label: "Tap on Lets go" - point: "50%,92%" \ No newline at end of file + id: "onboardingFinish" +- assertVisible: "Following" diff --git a/__e2e__/flows/onboarding.yml b/__e2e__/flows/onboarding.yml index c8d9d57233..81aeef6ccb 100644 --- a/__e2e__/flows/onboarding.yml +++ b/__e2e__/flows/onboarding.yml @@ -3,11 +3,15 @@ appId: xyz.blueskyweb.app - runScript: file: ../setupServer.js env: - SERVER_PATH: "?users" + SERVER_PATH: "?users" - runFlow: file: ../setupApp.yml - tapOn: id: "e2eSignInAlice" +- extendedWaitUntil: + visible: + id: "viewHeaderHomeFeedPrefsBtn" + - tapOn: id: "e2eStartOnboarding" - tapOn: "Select an avatar" @@ -18,12 +22,12 @@ appId: xyz.blueskyweb.app - waitForAnimationToEnd - tapOn: "Done" - waitForAnimationToEnd -- tapOn: "Continue to next step" +- tapOn: + id: "onboardingContinue" - assertVisible: "What are your interests?" - tapOn: - label: "Tap on continue" - point: "50%,92%" + id: "onboardingContinue" - assertVisible: "You're ready to go!" - tapOn: - label: "Tap on Lets go" - point: "50%,92%" \ No newline at end of file + id: "onboardingFinish" +- assertVisible: "Following" diff --git a/__e2e__/flows/post-report-flow.yml b/__e2e__/flows/post-report-flow.yml index 3925bef897..a509fcc024 100644 --- a/__e2e__/flows/post-report-flow.yml +++ b/__e2e__/flows/post-report-flow.yml @@ -3,11 +3,14 @@ appId: xyz.blueskyweb.app - runScript: file: ../setupServer.js env: - SERVER_PATH: "?users&follows&posts" + SERVER_PATH: "?users&follows&posts" - runFlow: file: ../setupApp.yml - tapOn: id: "e2eSignInAlice" +- extendedWaitUntil: + visible: + id: "viewHeaderHomeFeedPrefsBtn" - tapOn: id: "postDropdownBtn" diff --git a/__e2e__/flows/profile-screen.yml b/__e2e__/flows/profile-screen.yml index 858448b445..a20302dacc 100644 --- a/__e2e__/flows/profile-screen.yml +++ b/__e2e__/flows/profile-screen.yml @@ -3,7 +3,7 @@ appId: xyz.blueskyweb.app - runScript: file: ../setupServer.js env: - SERVER_PATH: "?users&posts&feeds" + SERVER_PATH: "?users&posts&feeds" - runFlow: file: ../setupApp.yml - tapOn: @@ -12,10 +12,10 @@ appId: xyz.blueskyweb.app # Navigate to another user profile - extendedWaitUntil: visible: - id: "bottomBarSearchBtn" + id: "bottomBarSearchBtn" - tapOn: id: "bottomBarSearchBtn" -- tapOn: "Search for posts, users, or feeds" +- tapOn: "Search for posts, users[,]? or feeds" - inputText: "b" - tapOn: id: "searchAutoCompleteResult-bob.test" @@ -38,4 +38,4 @@ appId: xyz.blueskyweb.app - tapOn: id: "profileHeaderDropdownBtn" - tapOn: "Unmute Account" -- assertNotVisible: "Account Muted" \ No newline at end of file +- assertNotVisible: "Account Muted" diff --git a/__e2e__/flows/search-screen.yml b/__e2e__/flows/search-screen.yml index 78ebbee369..13a1b06fa2 100644 --- a/__e2e__/flows/search-screen.yml +++ b/__e2e__/flows/search-screen.yml @@ -3,20 +3,22 @@ appId: xyz.blueskyweb.app - runScript: file: ../setupServer.js env: - SERVER_PATH: "?users" + SERVER_PATH: "?users" - runFlow: file: ../setupApp.yml - tapOn: id: "e2eSignInAlice" # Navigate to another user profile via autocomplete +- extendedWaitUntil: + visible: + id: "bottomBarSearchBtn" - tapOn: id: "bottomBarSearchBtn" -- assertVisible: "Search for posts, users, or feeds" -- tapOn: "Search for posts, users, or feeds" +- assertVisible: "Search for posts, users[,]? or feeds" +- tapOn: "Search for posts, users[,]? or feeds" - inputText: "b" - tapOn: id: "searchAutoCompleteResult-bob.test" - assertVisible: id: "profileView" - diff --git a/__e2e__/flows/shared-prefs.yml b/__e2e__/flows/shared-prefs.yml index 9cc7707be1..8b773a7665 100644 --- a/__e2e__/flows/shared-prefs.yml +++ b/__e2e__/flows/shared-prefs.yml @@ -8,8 +8,12 @@ appId: xyz.blueskyweb.app file: ../setupApp.yml - tapOn: id: "e2eSignInAlice" +- extendedWaitUntil: + visible: + id: "viewHeaderHomeFeedPrefsBtn" + - assertVisible: - id: "storybookBtn" + id: "storybookBtn" - tapOn: id: "storybookBtn" - tapOn: diff --git a/__e2e__/flows/thread-muting.yml b/__e2e__/flows/thread-muting.yml index e588805c2d..2724833feb 100644 --- a/__e2e__/flows/thread-muting.yml +++ b/__e2e__/flows/thread-muting.yml @@ -3,13 +3,16 @@ appId: xyz.blueskyweb.app - runScript: file: ../setupServer.js env: - SERVER_PATH: "?users&follows" + SERVER_PATH: "?users&follows" - runFlow: file: ../setupApp.yml # Login, create a thread, and log out - tapOn: id: "e2eSignInAlice" +- extendedWaitUntil: + visible: + id: "viewHeaderHomeFeedPrefsBtn" - assertVisible: id: "composeFAB" - tapOn: @@ -19,8 +22,13 @@ appId: xyz.blueskyweb.app id: "composerPublishBtn" # Login, reply to the thread, and log out +- tapOn: + id: "e2eSignOut" - tapOn: id: "e2eSignInBob" +- extendedWaitUntil: + visible: + id: "viewHeaderHomeFeedPrefsBtn" - tapOn: id: "replyBtn" - inputText: "Reply 1" @@ -28,8 +36,13 @@ appId: xyz.blueskyweb.app id: "composerPublishBtn" # Login, confirm notification exists, mute thread, and log out +- tapOn: + id: "e2eSignOut" - tapOn: id: "e2eSignInAlice" +- extendedWaitUntil: + visible: + id: "viewHeaderHomeFeedPrefsBtn" - tapOn: id: "bottomBarNotificationsBtn" - assertVisible: @@ -39,12 +52,17 @@ appId: xyz.blueskyweb.app - tapOn: id: "postDropdownBtn" childOf: - id: "postThreadItem-by-bob.test" + id: "postThreadItem-by-bob.test" - tapOn: "Mute thread" # Login, reply to the thread twice, and log out +- tapOn: + id: "e2eSignOut" - tapOn: id: "e2eSignInBob" +- extendedWaitUntil: + visible: + id: "viewHeaderHomeFeedPrefsBtn" - tapOn: id: "bottomBarProfileBtn" - tapOn: @@ -60,24 +78,35 @@ appId: xyz.blueskyweb.app - tapOn: id: "composerPublishBtn" - -# Login, confirm notifications dont exist, unmute the thread, confirm notifications exist +# Login, confirm notifications dont exist, unmute the thread, ~~confirm notifications exist~~ +# Mute thread behaviour no longer change old notifications after muting/unmuting a thread -sfn +- tapOn: + id: "e2eSignOut" - tapOn: id: "e2eSignInAlice" +- extendedWaitUntil: + visible: + id: "viewHeaderHomeFeedPrefsBtn" - tapOn: id: "bottomBarNotificationsBtn" -- assertNotVisible: +- assertVisible: ".*Reply 1.*" +- assertNotVisible: ".*Reply 2.*" +- assertNotVisible: ".*Reply 3.*" +- assertVisible: id: "feedItem-by-bob.test" - tapOn: - id: "bottomBarHomeBtn" + id: "feedItem-by-bob.test" - tapOn: id: "postDropdownBtn" + childOf: + id: "postThreadItem-by-bob.test" - tapOn: "Unmute thread" - tapOn: id: "bottomBarNotificationsBtn" - swipe: from: - id: "notifsFeed" + id: "notifsFeed" direction: DOWN -- assertVisible: - id: "feedItem-by-bob.test" +- assertVisible: ".*Reply 1.*" +- assertNotVisible: ".*Reply 2.*" +- assertNotVisible: ".*Reply 3.*" diff --git a/__e2e__/mock-server.ts b/__e2e__/mock-server.ts index b5f13a87fd..1f78848446 100644 --- a/__e2e__/mock-server.ts +++ b/__e2e__/mock-server.ts @@ -1,7 +1,7 @@ import {createServer as createHTTPServer} from 'node:http' import {parse} from 'node:url' -import {createServer, TestPDS} from '../jest/test-pds' +import {createServer, type TestPDS} from '../jest/test-pds' async function main() { let server: TestPDS @@ -181,10 +181,10 @@ async function main() { 'warn-profile', 'warn-posts', 'muted-account', - 'muted-by-list-account', + 'muted-by-list-acc', 'blocking-account', 'blockedby-account', - 'mutual-block-account', + 'mutual-block-acc', ]) { await server.mocker.createUser(user) await server.mocker.follow('alice', user) @@ -411,16 +411,16 @@ async function main() { await server.mocker.addToMuteList( 'alice', list, - server.mocker.users['muted-by-list-account'].did, + server.mocker.users['muted-by-list-acc'].did, ) - await server.mocker.createPost('muted-by-list-account', 'muted post') + await server.mocker.createPost('muted-by-list-acc', 'muted post') await server.mocker.createQuotePost( - 'muted-by-list-account', + 'muted-by-list-acc', 'account quote post', anchorPost, ) await server.mocker.createReply( - 'muted-by-list-account', + 'muted-by-list-acc', 'account reply', anchorPost, ) @@ -470,16 +470,16 @@ async function main() { ) await server.mocker.createPost( - 'mutual-block-account', + 'mutual-block-acc', 'mutual-block post', ) await server.mocker.createQuotePost( - 'mutual-block-account', + 'mutual-block-acc', 'mutual-block quote post', anchorPost, ) await server.mocker.createReply( - 'mutual-block-account', + 'mutual-block-acc', 'mutual-block reply', anchorPost, ) @@ -488,15 +488,15 @@ async function main() { repo: server.mocker.users.alice.did, }, { - subject: server.mocker.users['mutual-block-account'].did, + subject: server.mocker.users['mutual-block-acc'].did, createdAt: new Date().toISOString(), }, ) await server.mocker.users[ - 'mutual-block-account' + 'mutual-block-acc' ].agent.app.bsky.graph.block.create( { - repo: server.mocker.users['mutual-block-account'].did, + repo: server.mocker.users['mutual-block-acc'].did, }, { subject: server.mocker.users.alice.did, @@ -509,7 +509,16 @@ async function main() { } } console.log('Ready') - return res.writeHead(200).end(server.pdsUrl) + return res + .writeHead(200, { + 'content-type': 'application/json', + }) + .end( + JSON.stringify({ + pdsUrl: server.pdsUrl, + appviewDid: server.appviewDid, + }), + ) } catch (e) { console.error('Error!', e) return res.writeHead(500).end() diff --git a/__e2e__/setupApp.yml b/__e2e__/setupApp.yml index 25f9aa8470..728d548fb3 100644 --- a/__e2e__/setupApp.yml +++ b/__e2e__/setupApp.yml @@ -11,3 +11,8 @@ appId: xyz.blueskyweb.app - swipe: from: "Bluesky" direction: DOWN +- tapOn: + id: e2eProxyHeaderInput +- inputText: ${output.result} +- pressKey: Enter +- hideKeyboard diff --git a/__e2e__/setupServer.js b/__e2e__/setupServer.js index 7b1fb95745..5038197b0a 100644 --- a/__e2e__/setupServer.js +++ b/__e2e__/setupServer.js @@ -1,5 +1,8 @@ -// eslint-disable-next-line -http.post('http://localhost:1986/' + SERVER_PATH, { +// eslint-disable-next-line no-undef +var res = http.post('http://localhost:1986/' + SERVER_PATH, { headers: {'Content-Type': 'text/plain'}, body: '', }) + +// eslint-disable-next-line no-undef +output.result = json(res.body).appviewDid diff --git a/app.config.js b/app.config.js index b30cdf0fea..8a0e6e48c1 100644 --- a/app.config.js +++ b/app.config.js @@ -303,6 +303,11 @@ module.exports = function (_config) { android: './assets/app-icons/android_icon_default_dark.png', prerendered: true, }, + next: { + ios: './assets/app-icons/icon_default_next.png', + android: './assets/app-icons/icon_default_next.png', + prerendered: true, + }, /** * Bluesky+ core set diff --git a/assets/app-icons/icon_default_next.png b/assets/app-icons/icon_default_next.png new file mode 100644 index 0000000000..8c17c0ea6e Binary files /dev/null and b/assets/app-icons/icon_default_next.png differ diff --git a/assets/images/onboarding/value_prop_1_dark.webp b/assets/images/onboarding/value_prop_1_dark.webp new file mode 100644 index 0000000000..259e6155b2 Binary files /dev/null and b/assets/images/onboarding/value_prop_1_dark.webp differ diff --git a/assets/images/onboarding/value_prop_1_dark_borderless.webp b/assets/images/onboarding/value_prop_1_dark_borderless.webp new file mode 100644 index 0000000000..5c44735f9b Binary files /dev/null and b/assets/images/onboarding/value_prop_1_dark_borderless.webp differ diff --git a/assets/images/onboarding/value_prop_1_dim.webp b/assets/images/onboarding/value_prop_1_dim.webp new file mode 100644 index 0000000000..2fea1b9916 Binary files /dev/null and b/assets/images/onboarding/value_prop_1_dim.webp differ diff --git a/assets/images/onboarding/value_prop_1_dim_borderless.webp b/assets/images/onboarding/value_prop_1_dim_borderless.webp new file mode 100644 index 0000000000..98c7542b44 Binary files /dev/null and b/assets/images/onboarding/value_prop_1_dim_borderless.webp differ diff --git a/assets/images/onboarding/value_prop_1_light.webp b/assets/images/onboarding/value_prop_1_light.webp new file mode 100644 index 0000000000..13ffbf02b3 Binary files /dev/null and b/assets/images/onboarding/value_prop_1_light.webp differ diff --git a/assets/images/onboarding/value_prop_1_light_borderless.webp b/assets/images/onboarding/value_prop_1_light_borderless.webp new file mode 100644 index 0000000000..1cf0cd032e Binary files /dev/null and b/assets/images/onboarding/value_prop_1_light_borderless.webp differ diff --git a/assets/images/onboarding/value_prop_2_dark.webp b/assets/images/onboarding/value_prop_2_dark.webp new file mode 100644 index 0000000000..7a60d554eb Binary files /dev/null and b/assets/images/onboarding/value_prop_2_dark.webp differ diff --git a/assets/images/onboarding/value_prop_2_dim.webp b/assets/images/onboarding/value_prop_2_dim.webp new file mode 100644 index 0000000000..86f2c1f893 Binary files /dev/null and b/assets/images/onboarding/value_prop_2_dim.webp differ diff --git a/assets/images/onboarding/value_prop_2_light.webp b/assets/images/onboarding/value_prop_2_light.webp new file mode 100644 index 0000000000..2b385a3f2a Binary files /dev/null and b/assets/images/onboarding/value_prop_2_light.webp differ diff --git a/assets/images/onboarding/value_prop_3_dark.webp b/assets/images/onboarding/value_prop_3_dark.webp new file mode 100644 index 0000000000..0ea0dba1c1 Binary files /dev/null and b/assets/images/onboarding/value_prop_3_dark.webp differ diff --git a/assets/images/onboarding/value_prop_3_dim.webp b/assets/images/onboarding/value_prop_3_dim.webp new file mode 100644 index 0000000000..a0986e94be Binary files /dev/null and b/assets/images/onboarding/value_prop_3_dim.webp differ diff --git a/assets/images/onboarding/value_prop_3_light.webp b/assets/images/onboarding/value_prop_3_light.webp new file mode 100644 index 0000000000..cd8bcbb457 Binary files /dev/null and b/assets/images/onboarding/value_prop_3_light.webp differ diff --git a/bskyembed/package.json b/bskyembed/package.json index e269b1c953..c47c4218da 100644 --- a/bskyembed/package.json +++ b/bskyembed/package.json @@ -6,24 +6,25 @@ "dev": "vite", "build": "tsc && vite build", "build-snippet": "tsc --project tsconfig.snippet.json", - "lint": "eslint --cache --ext .js,.jsx,.ts,.tsx src" + "lint": "eslint --cache --ext .js,.jsx,.ts,.tsx src", + "typecheck": "tsc --noEmit" }, "dependencies": { - "@atproto/api": "0.13.6", - "@preact/preset-vite": "^2.8.2", - "@vitejs/plugin-legacy": "^5.3.2", - "preact": "^10.4.8", - "terser": "^5.30.3" + "@atproto/api": "^0.15.25", + "preact": "^10.4.8" }, "devDependencies": { + "@preact/preset-vite": "^2.10.2", + "@vitejs/plugin-legacy": "^7.0.0", "autoprefixer": "^10.4.19", "eslint": "^8.19.0", "eslint-config-preact": "^1.3.0", "eslint-plugin-simple-import-sort": "^12.0.0", "postcss": "^8.4.38", "tailwindcss": "^3.4.3", - "typescript": "^5.5.4", - "vite": "^5.2.8", - "vite-tsconfig-paths": "^4.3.2" + "terser": "^5.43.1", + "typescript": "^5.8.3", + "vite": "^7.0.4", + "vite-tsconfig-paths": "^5.1.4" } } diff --git a/bskyembed/src/components/container.tsx b/bskyembed/src/components/container.tsx index 8e142a25be..bafc497aea 100644 --- a/bskyembed/src/components/container.tsx +++ b/bskyembed/src/components/container.tsx @@ -49,7 +49,7 @@ export function Container({ } }}> {href && } -
{children}
+
{children}
) } diff --git a/bskyembed/src/components/embed.tsx b/bskyembed/src/components/embed.tsx index 428782b642..52618a89da 100644 --- a/bskyembed/src/components/embed.tsx +++ b/bskyembed/src/components/embed.tsx @@ -17,8 +17,11 @@ import infoIcon from '../../assets/circleInfo_stroke2_corner0_rounded.svg' import playIcon from '../../assets/play_filled_corner2_rounded.svg' import starterPackIcon from '../../assets/starterPack.svg' import {CONTENT_LABELS, labelsToInfo} from '../labels' -import {getRkey} from '../utils' +import * as bsky from '../types/bsky' +import {getRkey} from '../util/rkey' +import {getVerificationState} from '../util/verification-state' import {Link} from './link' +import {VerificationCheck} from './verification-check' export function Embed({ content, @@ -75,23 +78,35 @@ export function Embed({ CONTENT_LABELS.includes(label.val), ) + const verification = getVerificationState({profile: record.author}) + return (
-
+
-

- {record.author.displayName} - +

+

+ {record.author.displayName?.trim() || record.author.handle} +

+ {verification.isVerified && ( + + )} +

@{record.author.handle} - -

+

+
{text &&

{text}

} {record.embeds?.map(embed => ( @@ -404,7 +419,12 @@ function StarterPackEmbed({ }: { content: AppBskyGraphDefs.StarterPackViewBasic }) { - if (!AppBskyGraphStarterpack.isRecord(content.record)) { + if ( + !bsky.dangerousIsType( + content.record, + AppBskyGraphStarterpack.isRecord, + ) + ) { return null } @@ -443,7 +463,9 @@ function StarterPackEmbed({ } // from #/lib/strings/starter-pack.ts -function getStarterPackImage(starterPack: AppBskyGraphDefs.StarterPackView) { +function getStarterPackImage( + starterPack: AppBskyGraphDefs.StarterPackViewBasic, +) { const rkey = getRkey({uri: starterPack.uri}) return `https://ogcard.cdn.bsky.app/start/${starterPack.creator.did}/${rkey}` } diff --git a/bskyembed/src/components/post.tsx b/bskyembed/src/components/post.tsx index 6ecac57965..d216ce0e54 100644 --- a/bskyembed/src/components/post.tsx +++ b/bskyembed/src/components/post.tsx @@ -11,10 +11,15 @@ import likeIcon from '../../assets/heart2_filled_stroke2_corner0_rounded.svg' import logo from '../../assets/logo.svg' import repostIcon from '../../assets/repost_stroke2_corner2_rounded.svg' import {CONTENT_LABELS} from '../labels' -import {getRkey, niceDate, prettyNumber} from '../utils' +import * as bsky from '../types/bsky' +import {niceDate} from '../util/nice-date' +import {prettyNumber} from '../util/pretty-number' +import {getRkey} from '../util/rkey' +import {getVerificationState} from '../util/verification-state' import {Container} from './container' import {Embed} from './embed' import {Link} from './link' +import {VerificationCheck} from './verification-check' interface Props { thread: AppBskyFeedDefs.ThreadViewPost @@ -28,16 +33,25 @@ export function Post({thread}: Props) { ) let record: AppBskyFeedPost.Record | null = null - if (AppBskyFeedPost.isRecord(post.record)) { + if ( + bsky.dangerousIsType( + post.record, + AppBskyFeedPost.isRecord, + ) + ) { record = post.record } + const verification = getVerificationState({profile: post.author}) + const href = `/profile/${post.author.did}/post/${getRkey(post)}` return (
-
- +
+
-
+
+
+ + {post.author.displayName?.trim() || post.author.handle} + + {verification.isVerified && ( + + )} +
-

{post.author.displayName}

- - -

@{post.author.handle}

+ className="block text-[15px] text-textLight dark:text-textDimmed hover:underline line-clamp-1"> + @{post.author.handle}
-
@@ -133,7 +155,7 @@ function PostContent({record}: {record: AppBskyFeedPost.Record | null}) { : +} + +export function VerifiedCheck({size, className}: IconProps) { + return ( + + + + + ) +} + +export function VerifierCheck({size, className}: IconProps) { + return ( + + + + + ) +} diff --git a/bskyembed/src/screens/landing.tsx b/bskyembed/src/screens/landing.tsx index 880b713372..bb650241f4 100644 --- a/bskyembed/src/screens/landing.tsx +++ b/bskyembed/src/screens/landing.tsx @@ -14,9 +14,11 @@ import { import {Container} from '../components/container' import {Link} from '../components/link' import {Post} from '../components/post' -import {niceDate} from '../utils' +import * as bsky from '../types/bsky' +import {niceDate} from '../util/nice-date' -const DEFAULT_POST = 'https://bsky.app/profile/emilyliu.me/post/3jzn6g7ixgq2y' +const DEFAULT_POST = + 'https://bsky.app/profile/did:plc:vjug55kidv6sye7ykr5faxxn/post/3jzn6g7ixgq2y' const DEFAULT_URI = 'at://did:plc:vjug55kidv6sye7ykr5faxxn/app.bsky.feed.post/3jzn6g7ixgq2y' @@ -222,7 +224,12 @@ function Snippet({ const snippet = useMemo(() => { const record = thread.post.record - if (!AppBskyFeedPost.isRecord(record)) { + if ( + !bsky.dangerousIsType( + record, + AppBskyFeedPost.isRecord, + ) + ) { return '' } diff --git a/bskyembed/src/screens/post.tsx b/bskyembed/src/screens/post.tsx index 4cd72b69bc..83914f66f3 100644 --- a/bskyembed/src/screens/post.tsx +++ b/bskyembed/src/screens/post.tsx @@ -8,7 +8,7 @@ import {applyTheme, initSystemColorMode} from '../color-mode' import {Container} from '../components/container' import {Link} from '../components/link' import {Post} from '../components/post' -import {getRkey} from '../utils' +import {getRkey} from '../util/rkey' const root = document.getElementById('app') if (!root) throw new Error('No root element') diff --git a/bskyembed/src/types/bsky/index.ts b/bskyembed/src/types/bsky/index.ts new file mode 100644 index 0000000000..c462cdf654 --- /dev/null +++ b/bskyembed/src/types/bsky/index.ts @@ -0,0 +1,49 @@ +import {ValidationResult} from '@atproto/lexicon' + +export * as profile from './profile' + +/** + * Fast type checking without full schema validation, for use with data we + * trust, or for non-critical path use cases. Why? Our SDK's `is*` identity + * utils do not assert the type of the entire object, only the `$type` string. + * + * For full validation of the object schema, use the `validate` export from + * this file. + * + * Usage: + * ```ts + * import * as bsky from '#/types/bsky' + * + * if (bsky.dangerousIsType(item, AppBskyFeedPost.isRecord)) { + * // `item` has type `$Typed` here + * } + * ``` + */ +export function dangerousIsType( + record: unknown, + identity: (v: V) => v is V & {$type: NonNullable}, +): record is R { + return identity(record) +} + +/** + * Fully validates the object schema, which has a performance cost. + * + * For faster checks with data we trust, like that from our app view, use the + * `dangerousIsType` export from this same file. + * + * Usage: + * ```ts + * import * as bsky from '#/types/bsky' + * + * if (bsky.validate(item, AppBskyFeedPost.validateRecord)) { + * // `item` has type `$Typed` here + * } + * ``` + */ +export function validate( + record: unknown, + validator: (v: unknown) => ValidationResult, +): record is R { + return validator(record).success +} diff --git a/bskyembed/src/types/bsky/profile.ts b/bskyembed/src/types/bsky/profile.ts new file mode 100644 index 0000000000..12c8146ae1 --- /dev/null +++ b/bskyembed/src/types/bsky/profile.ts @@ -0,0 +1,10 @@ +import {type AppBskyActorDefs, type ChatBskyActorDefs} from '@atproto/api' + +/** + * Matches any profile view exported by our SDK + */ +export type AnyProfileView = + | AppBskyActorDefs.ProfileViewBasic + | AppBskyActorDefs.ProfileView + | AppBskyActorDefs.ProfileViewDetailed + | ChatBskyActorDefs.ProfileViewBasic diff --git a/bskyembed/src/util/nice-date.ts b/bskyembed/src/util/nice-date.ts new file mode 100644 index 0000000000..016c97a694 --- /dev/null +++ b/bskyembed/src/util/nice-date.ts @@ -0,0 +1,11 @@ +export function niceDate(date: number | string | Date) { + const d = new Date(date) + return `${d.toLocaleDateString('en-us', { + year: 'numeric', + month: 'short', + day: 'numeric', + })} at ${d.toLocaleTimeString(undefined, { + hour: 'numeric', + minute: '2-digit', + })}` +} diff --git a/bskyembed/src/util/parse-embed.ts b/bskyembed/src/util/parse-embed.ts new file mode 100644 index 0000000000..97c3dc33e7 --- /dev/null +++ b/bskyembed/src/util/parse-embed.ts @@ -0,0 +1,152 @@ +/** + * This file is a copy of what exists in the social-app + */ + +import { + AppBskyEmbedExternal, + AppBskyEmbedImages, + AppBskyEmbedRecord, + AppBskyEmbedRecordWithMedia, + AppBskyEmbedVideo, + AppBskyFeedDefs, + AppBskyGraphDefs, + AppBskyLabelerDefs, +} from '@atproto/api' + +export type Embed = + | { + type: 'post' + view: AppBskyEmbedRecord.ViewRecord + } + | { + type: 'post_not_found' + view: AppBskyEmbedRecord.ViewNotFound + } + | { + type: 'post_blocked' + view: AppBskyEmbedRecord.ViewBlocked + } + | { + type: 'post_detached' + view: AppBskyEmbedRecord.ViewDetached + } + | { + type: 'feed' + view: AppBskyFeedDefs.GeneratorView + } + | { + type: 'list' + view: AppBskyGraphDefs.ListView + } + | { + type: 'labeler' + view: AppBskyLabelerDefs.LabelerView + } + | { + type: 'starter_pack' + view: AppBskyGraphDefs.StarterPackViewBasic + } + | { + type: 'images' + view: AppBskyEmbedImages.View + } + | { + type: 'link' + view: AppBskyEmbedExternal.View + } + | { + type: 'video' + view: AppBskyEmbedVideo.View + } + | { + type: 'post_with_media' + view: Embed + media: Embed + } + | { + type: 'unknown' + view: null + } + +export type EmbedType = Extract + +export function parseEmbedRecordView({record}: AppBskyEmbedRecord.View): Embed { + if (AppBskyEmbedRecord.isViewRecord(record)) { + return { + type: 'post', + view: record, + } + } else if (AppBskyEmbedRecord.isViewNotFound(record)) { + return { + type: 'post_not_found', + view: record, + } + } else if (AppBskyEmbedRecord.isViewBlocked(record)) { + return { + type: 'post_blocked', + view: record, + } + } else if (AppBskyEmbedRecord.isViewDetached(record)) { + return { + type: 'post_detached', + view: record, + } + } else if (AppBskyFeedDefs.isGeneratorView(record)) { + return { + type: 'feed', + view: record, + } + } else if (AppBskyGraphDefs.isListView(record)) { + return { + type: 'list', + view: record, + } + } else if (AppBskyLabelerDefs.isLabelerView(record)) { + return { + type: 'labeler', + view: record, + } + } else if (AppBskyGraphDefs.isStarterPackViewBasic(record)) { + return { + type: 'starter_pack', + view: record, + } + } else { + return { + type: 'unknown', + view: null, + } + } +} + +export function parseEmbed(embed: AppBskyFeedDefs.PostView['embed']): Embed { + if (AppBskyEmbedImages.isView(embed)) { + return { + type: 'images', + view: embed, + } + } else if (AppBskyEmbedExternal.isView(embed)) { + return { + type: 'link', + view: embed, + } + } else if (AppBskyEmbedVideo.isView(embed)) { + return { + type: 'video', + view: embed, + } + } else if (AppBskyEmbedRecord.isView(embed)) { + return parseEmbedRecordView(embed) + } else if (AppBskyEmbedRecordWithMedia.isView(embed)) { + return { + type: 'post_with_media', + view: parseEmbedRecordView(embed.record), + media: parseEmbed(embed.media), + } + } else { + return { + type: 'unknown', + view: null, + } + } +} diff --git a/bskyembed/src/util/pretty-number.ts b/bskyembed/src/util/pretty-number.ts new file mode 100644 index 0000000000..07f7e95774 --- /dev/null +++ b/bskyembed/src/util/pretty-number.ts @@ -0,0 +1,9 @@ +const formatter = new Intl.NumberFormat('en-US', { + notation: 'compact', + maximumFractionDigits: 1, + roundingMode: 'trunc', +}) + +export function prettyNumber(number: number) { + return formatter.format(number) +} diff --git a/bskyembed/src/util/rkey.ts b/bskyembed/src/util/rkey.ts new file mode 100644 index 0000000000..71d57f8c6a --- /dev/null +++ b/bskyembed/src/util/rkey.ts @@ -0,0 +1,6 @@ +import {AtUri} from '@atproto/api' + +export function getRkey({uri}: {uri: string}): string { + const at = new AtUri(uri) + return at.rkey +} diff --git a/bskyembed/src/util/verification-state.ts b/bskyembed/src/util/verification-state.ts new file mode 100644 index 0000000000..29355e511c --- /dev/null +++ b/bskyembed/src/util/verification-state.ts @@ -0,0 +1,31 @@ +import * as bsky from '../types/bsky' + +export type VerificationState = { + role: 'default' | 'verifier' + isVerified: boolean +} + +export function getVerificationState({ + profile, +}: { + profile?: bsky.profile.AnyProfileView +}): VerificationState { + if (!profile || !profile.verification) { + return { + role: 'default', + isVerified: false, + } + } + + const {verifiedStatus, trustedVerifierStatus} = profile.verification + const isVerifiedUser = ['valid', 'invalid'].includes(verifiedStatus) + const isVerifierUser = ['valid', 'invalid'].includes(trustedVerifierStatus) + const isVerified = + (isVerifiedUser && verifiedStatus === 'valid') || + (isVerifierUser && trustedVerifierStatus === 'valid') + + return { + role: isVerifierUser ? 'verifier' : 'default', + isVerified, + } +} diff --git a/bskyembed/src/utils.ts b/bskyembed/src/utils.ts deleted file mode 100644 index cfa4a525bf..0000000000 --- a/bskyembed/src/utils.ts +++ /dev/null @@ -1,28 +0,0 @@ -import {AtUri} from '@atproto/api' - -export function niceDate(date: number | string | Date) { - const d = new Date(date) - return `${d.toLocaleDateString('en-us', { - year: 'numeric', - month: 'short', - day: 'numeric', - })} at ${d.toLocaleTimeString(undefined, { - hour: 'numeric', - minute: '2-digit', - })}` -} - -export function getRkey({uri}: {uri: string}): string { - const at = new AtUri(uri) - return at.rkey -} - -const formatter = new Intl.NumberFormat('en-US', { - notation: 'compact', - maximumFractionDigits: 1, - roundingMode: 'trunc', -}) - -export function prettyNumber(number: number) { - return formatter.format(number) -} diff --git a/bskyembed/tsconfig.json b/bskyembed/tsconfig.json index f11db03e60..769488cc6e 100644 --- a/bskyembed/tsconfig.json +++ b/bskyembed/tsconfig.json @@ -10,7 +10,7 @@ "strict": true, "forceConsistentCasingInFileNames": true, "module": "ESNext", - "moduleResolution": "Node", + "moduleResolution": "Bundler", "resolveJsonModule": true, "isolatedModules": true, "noEmit": true, @@ -19,5 +19,5 @@ "jsxFragmentFactory": "Fragment", "downlevelIteration": true }, - "include": ["src", "snippet", "vite.config.ts"] + "include": ["src", "snippet", "vite.config.ts", "*.config.cjs", ".eslintrc.cjs"] } diff --git a/bskyembed/yarn.lock b/bskyembed/yarn.lock index 6a86395c1b..9cb6d73180 100644 --- a/bskyembed/yarn.lock +++ b/bskyembed/yarn.lock @@ -20,67 +20,69 @@ "@jridgewell/gen-mapping" "^0.3.5" "@jridgewell/trace-mapping" "^0.3.24" -"@atproto/api@0.13.6": - version "0.13.6" - resolved "https://registry.yarnpkg.com/@atproto/api/-/api-0.13.6.tgz#2500e9d7143e6718089632300c42ce50149f8cd5" - integrity sha512-58emFFZhqY8nVWD3xFWK0yYqAmJ2un+NaTtZxBbRo00mGq1rz9VXTpVmfoHFcuXL1hoDQN3WyJfsub8r6xGOgg== +"@atproto/api@^0.15.25": + version "0.15.25" + resolved "https://registry.yarnpkg.com/@atproto/api/-/api-0.15.25.tgz#6ed0115a53b9890cd0067d6b0839f5223f18d2a2" + integrity sha512-dUqe920qyXd596AI5iJyBlSv0vK5fh1a8PC0zPoeM+FzGDiebnbxuJdPIZ3HeBT/xQ2ce9HwYk1Ih2G7a+JkzQ== dependencies: - "@atproto/common-web" "^0.3.0" - "@atproto/lexicon" "^0.4.1" - "@atproto/syntax" "^0.3.0" - "@atproto/xrpc" "^0.6.1" + "@atproto/common-web" "^0.4.2" + "@atproto/lexicon" "^0.4.12" + "@atproto/syntax" "^0.4.0" + "@atproto/xrpc" "^0.7.1" await-lock "^2.2.2" multiformats "^9.9.0" tlds "^1.234.0" + zod "^3.23.8" -"@atproto/common-web@^0.3.0": - version "0.3.0" - resolved "https://registry.yarnpkg.com/@atproto/common-web/-/common-web-0.3.0.tgz#36da8c2c31d8cf8a140c3c8f03223319bf4430bb" - integrity sha512-67VnV6JJyX+ZWyjV7xFQMypAgDmjVaR9ZCuU/QW+mqlqI7fex2uL4Fv+7/jHadgzhuJHVd6OHOvNn0wR5WZYtA== +"@atproto/common-web@^0.4.2": + version "0.4.2" + resolved "https://registry.yarnpkg.com/@atproto/common-web/-/common-web-0.4.2.tgz#6e3add6939da93d3dfbc8f87e26dc4f57fad7259" + integrity sha512-vrXwGNoFGogodjQvJDxAeP3QbGtawgZute2ed1XdRO0wMixLk3qewtikZm06H259QDJVu6voKC5mubml+WgQUw== dependencies: graphemer "^1.4.0" multiformats "^9.9.0" uint8arrays "3.0.0" - zod "^3.21.4" + zod "^3.23.8" -"@atproto/lexicon@^0.4.1": - version "0.4.1" - resolved "https://registry.yarnpkg.com/@atproto/lexicon/-/lexicon-0.4.1.tgz#19155210570a2fafbcc7d4f655d9b813948e72a0" - integrity sha512-bzyr+/VHXLQWbumViX5L7h1NKQObfs8Z+XZJl43OUK8nYFUI4e/sW1IZKRNfw7Wvi5YVNK+J+yP3DWIBZhkCYA== +"@atproto/lexicon@^0.4.12": + version "0.4.12" + resolved "https://registry.yarnpkg.com/@atproto/lexicon/-/lexicon-0.4.12.tgz#89a704789d983f8405a52095769b5b58d87f5af7" + integrity sha512-fcEvEQ1GpQYF5igZ4IZjPWEoWVpsEF22L9RexxLS3ptfySXLflEyH384e7HITzO/73McDeaJx3lqHIuqn9ulnw== dependencies: - "@atproto/common-web" "^0.3.0" - "@atproto/syntax" "^0.3.0" + "@atproto/common-web" "^0.4.2" + "@atproto/syntax" "^0.4.0" iso-datestring-validator "^2.2.2" multiformats "^9.9.0" zod "^3.23.8" -"@atproto/syntax@^0.3.0": - version "0.3.0" - resolved "https://registry.yarnpkg.com/@atproto/syntax/-/syntax-0.3.0.tgz#fafa2dbea9add37253005cb663e7373e05e618b3" - integrity sha512-Weq0ZBxffGHDXHl9U7BQc2BFJi/e23AL+k+i5+D9hUq/bzT4yjGsrCejkjq0xt82xXDjmhhvQSZ0LqxyZ5woxA== +"@atproto/syntax@^0.4.0": + version "0.4.0" + resolved "https://registry.yarnpkg.com/@atproto/syntax/-/syntax-0.4.0.tgz#bec71552087bb24c208a06ef418c0040b65542f2" + integrity sha512-b9y5ceHS8YKOfP3mdKmwAx5yVj9294UN7FG2XzP6V5aKUdFazEYRnR9m5n5ZQFKa3GNvz7de9guZCJ/sUTcOAA== -"@atproto/xrpc@^0.6.1": - version "0.6.1" - resolved "https://registry.yarnpkg.com/@atproto/xrpc/-/xrpc-0.6.1.tgz#dcd1315c8c60eef5af2db7fa4e35a38ebc6d79d5" - integrity sha512-Zy5ydXEdk6sY7FDUZcEVfCL1jvbL4tXu5CcdPqbEaW6LQtk9GLds/DK1bCX9kswTGaBC88EMuqQMfkxOhp2t4A== +"@atproto/xrpc@^0.7.1": + version "0.7.1" + resolved "https://registry.yarnpkg.com/@atproto/xrpc/-/xrpc-0.7.1.tgz#51a8fc131eb21bd1229129d0a46384accc50ad65" + integrity sha512-ANHEzlskYlMEdH18m+Itp3a8d0pEJao2qoDybDoMupTnoeNkya4VKIaOgAi6ERQnqatBBZyn9asW+7rJmSt/8g== dependencies: - "@atproto/lexicon" "^0.4.1" + "@atproto/lexicon" "^0.4.12" zod "^3.23.8" -"@babel/code-frame@^7.23.5", "@babel/code-frame@^7.24.1", "@babel/code-frame@^7.24.2": - version "7.24.2" - resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.24.2.tgz#718b4b19841809a58b29b68cde80bc5e1aa6d9ae" - integrity sha512-y5+tLQyV8pg3fsiln67BVLD1P13Eg4lh5RW9mF0zUuvLrv9uIQ4MCL+CRT+FTsBlBjcIan6PGsLcBN0m3ClUyQ== +"@babel/code-frame@^7.24.2", "@babel/code-frame@^7.27.1": + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.27.1.tgz#200f715e66d52a23b221a9435534a91cc13ad5be" + integrity sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg== dependencies: - "@babel/highlight" "^7.24.2" - picocolors "^1.0.0" + "@babel/helper-validator-identifier" "^7.27.1" + js-tokens "^4.0.0" + picocolors "^1.1.1" -"@babel/compat-data@^7.22.6", "@babel/compat-data@^7.23.5", "@babel/compat-data@^7.24.4": - version "7.24.4" - resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.24.4.tgz#6f102372e9094f25d908ca0d34fc74c74606059a" - integrity sha512-vg8Gih2MLK+kOkHJp4gBEIkyaIi00jgWot2D9QOmmfLC8jINSOzmCLta6Bvz/JSBCqnegV0L80jhxkol5GWNfQ== +"@babel/compat-data@^7.27.2", "@babel/compat-data@^7.27.7", "@babel/compat-data@^7.28.0": + version "7.28.0" + resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.28.0.tgz#9fc6fd58c2a6a15243cd13983224968392070790" + integrity sha512-60X7qkglvrap8mn1lh2ebxXdZYtUcpd7gsmy9kLaBJ4i/WdY8PqTSdxyA8qraikqKQK5C1KRBKXqznrVapyNaw== -"@babel/core@^7.13.16", "@babel/core@^7.22.1", "@babel/core@^7.23.9": +"@babel/core@^7.13.16": version "7.24.4" resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.24.4.tgz#1f758428e88e0d8c563874741bc4ffc4f71a4717" integrity sha512-MBVlMXP+kkl5394RBLSxxk/iLTeVGuXTV3cIDXavPpMMqnSnt6apKgan/U8O3USWZCWZT/TbgfEpKa4uMgN4Dg== @@ -101,6 +103,27 @@ json5 "^2.2.3" semver "^6.3.1" +"@babel/core@^7.22.1", "@babel/core@^7.27.4": + version "7.28.0" + resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.28.0.tgz#55dad808d5bf3445a108eefc88ea3fdf034749a4" + integrity sha512-UlLAnTPrFdNGoFtbSXwcGFQBtQZJCNjaN6hQNP3UPvuNXT1i82N26KL3dZeIpNalWywr9IuQuncaAfUaS1g6sQ== + dependencies: + "@ampproject/remapping" "^2.2.0" + "@babel/code-frame" "^7.27.1" + "@babel/generator" "^7.28.0" + "@babel/helper-compilation-targets" "^7.27.2" + "@babel/helper-module-transforms" "^7.27.3" + "@babel/helpers" "^7.27.6" + "@babel/parser" "^7.28.0" + "@babel/template" "^7.27.2" + "@babel/traverse" "^7.28.0" + "@babel/types" "^7.28.0" + convert-source-map "^2.0.0" + debug "^4.1.0" + gensync "^1.0.0-beta.2" + json5 "^2.2.3" + semver "^6.3.1" + "@babel/eslint-parser@^7.13.14": version "7.24.1" resolved "https://registry.yarnpkg.com/@babel/eslint-parser/-/eslint-parser-7.24.1.tgz#e27eee93ed1d271637165ef3a86e2b9332395c32" @@ -110,264 +133,224 @@ eslint-visitor-keys "^2.1.0" semver "^6.3.1" -"@babel/generator@^7.24.1", "@babel/generator@^7.24.4": - version "7.24.4" - resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.24.4.tgz#1fc55532b88adf952025d5d2d1e71f946cb1c498" - integrity sha512-Xd6+v6SnjWVx/nus+y0l1sxMOTOMBkyL4+BIdbALyatQnAe/SRVjANeDPSCYaX+i1iJmuGSKf3Z+E+V/va1Hvw== +"@babel/generator@^7.24.4", "@babel/generator@^7.28.0": + version "7.28.0" + resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.28.0.tgz#9cc2f7bd6eb054d77dc66c2664148a0c5118acd2" + integrity sha512-lJjzvrbEeWrhB4P3QBsH7tey117PjLZnDbLiQEKjQ/fNJTjuq4HSqgFA+UNSwZT8D7dxxbnuSBMsa1lrWzKlQg== dependencies: - "@babel/types" "^7.24.0" - "@jridgewell/gen-mapping" "^0.3.5" - "@jridgewell/trace-mapping" "^0.3.25" - jsesc "^2.5.1" + "@babel/parser" "^7.28.0" + "@babel/types" "^7.28.0" + "@jridgewell/gen-mapping" "^0.3.12" + "@jridgewell/trace-mapping" "^0.3.28" + jsesc "^3.0.2" -"@babel/helper-annotate-as-pure@^7.22.5": - version "7.22.5" - resolved "https://registry.yarnpkg.com/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.22.5.tgz#e7f06737b197d580a01edf75d97e2c8be99d3882" - integrity sha512-LvBTxu8bQSQkcyKOU+a1btnNFQ1dMAd0R6PyW3arXes06F6QLWLIrd681bxRPIXlrMGR3XYnW9JyML7dP3qgxg== +"@babel/helper-annotate-as-pure@^7.27.1", "@babel/helper-annotate-as-pure@^7.27.3": + version "7.27.3" + resolved "https://registry.yarnpkg.com/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.27.3.tgz#f31fd86b915fc4daf1f3ac6976c59be7084ed9c5" + integrity sha512-fXSwMQqitTGeHLBC08Eq5yXz2m37E4pJX1qAU1+2cNedz/ifv/bVXft90VeSav5nFO61EcNgwr0aJxbyPaWBPg== dependencies: - "@babel/types" "^7.22.5" + "@babel/types" "^7.27.3" -"@babel/helper-builder-binary-assignment-operator-visitor@^7.22.15": - version "7.22.15" - resolved "https://registry.yarnpkg.com/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.22.15.tgz#5426b109cf3ad47b91120f8328d8ab1be8b0b956" - integrity sha512-QkBXwGgaoC2GtGZRoma6kv7Szfv06khvhFav67ZExau2RaXzy8MpHSMO2PNoP2XtmQphJQRHFfg77Bq731Yizw== +"@babel/helper-compilation-targets@^7.23.6", "@babel/helper-compilation-targets@^7.27.1", "@babel/helper-compilation-targets@^7.27.2": + version "7.27.2" + resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.27.2.tgz#46a0f6efab808d51d29ce96858dd10ce8732733d" + integrity sha512-2+1thGUUWWjLTYTHZWK1n8Yga0ijBz1XAhUXcKy81rd5g6yh7hGqMp45v7cadSbEHc9G3OTv45SyneRN3ps4DQ== dependencies: - "@babel/types" "^7.22.15" - -"@babel/helper-compilation-targets@^7.22.6", "@babel/helper-compilation-targets@^7.23.6": - version "7.23.6" - resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.23.6.tgz#4d79069b16cbcf1461289eccfbbd81501ae39991" - integrity sha512-9JB548GZoQVmzrFgp8o7KxdgkTGm6xs9DW0o/Pim72UDjzr5ObUQ6ZzYPqA+g9OTS2bBQoctLJrky0RDCAWRgQ== - dependencies: - "@babel/compat-data" "^7.23.5" - "@babel/helper-validator-option" "^7.23.5" - browserslist "^4.22.2" + "@babel/compat-data" "^7.27.2" + "@babel/helper-validator-option" "^7.27.1" + browserslist "^4.24.0" lru-cache "^5.1.1" semver "^6.3.1" -"@babel/helper-create-class-features-plugin@^7.24.1", "@babel/helper-create-class-features-plugin@^7.24.4": - version "7.24.4" - resolved "https://registry.yarnpkg.com/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.24.4.tgz#c806f73788a6800a5cfbbc04d2df7ee4d927cce3" - integrity sha512-lG75yeuUSVu0pIcbhiYMXBXANHrpUPaOfu7ryAzskCgKUHuAxRQI5ssrtmF0X9UXldPlvT0XM/A4F44OXRt6iQ== +"@babel/helper-create-class-features-plugin@^7.27.1": + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.27.1.tgz#5bee4262a6ea5ddc852d0806199eb17ca3de9281" + integrity sha512-QwGAmuvM17btKU5VqXfb+Giw4JcN0hjuufz3DYnpeVDvZLAObloM77bhMXiqry3Iio+Ai4phVRDwl6WU10+r5A== dependencies: - "@babel/helper-annotate-as-pure" "^7.22.5" - "@babel/helper-environment-visitor" "^7.22.20" - "@babel/helper-function-name" "^7.23.0" - "@babel/helper-member-expression-to-functions" "^7.23.0" - "@babel/helper-optimise-call-expression" "^7.22.5" - "@babel/helper-replace-supers" "^7.24.1" - "@babel/helper-skip-transparent-expression-wrappers" "^7.22.5" - "@babel/helper-split-export-declaration" "^7.22.6" + "@babel/helper-annotate-as-pure" "^7.27.1" + "@babel/helper-member-expression-to-functions" "^7.27.1" + "@babel/helper-optimise-call-expression" "^7.27.1" + "@babel/helper-replace-supers" "^7.27.1" + "@babel/helper-skip-transparent-expression-wrappers" "^7.27.1" + "@babel/traverse" "^7.27.1" semver "^6.3.1" -"@babel/helper-create-regexp-features-plugin@^7.18.6", "@babel/helper-create-regexp-features-plugin@^7.22.15", "@babel/helper-create-regexp-features-plugin@^7.22.5": - version "7.22.15" - resolved "https://registry.yarnpkg.com/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.22.15.tgz#5ee90093914ea09639b01c711db0d6775e558be1" - integrity sha512-29FkPLFjn4TPEa3RE7GpW+qbE8tlsu3jntNYNfcGsc49LphF1PQIiD+vMZ1z1xVOKt+93khA9tc2JBs3kBjA7w== +"@babel/helper-create-regexp-features-plugin@^7.18.6", "@babel/helper-create-regexp-features-plugin@^7.27.1": + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.27.1.tgz#05b0882d97ba1d4d03519e4bce615d70afa18c53" + integrity sha512-uVDC72XVf8UbrH5qQTc18Agb8emwjTiZrQE11Nv3CuBEZmVvTwwE9CBUEvHku06gQCAyYf8Nv6ja1IN+6LMbxQ== dependencies: - "@babel/helper-annotate-as-pure" "^7.22.5" - regexpu-core "^5.3.1" + "@babel/helper-annotate-as-pure" "^7.27.1" + regexpu-core "^6.2.0" semver "^6.3.1" -"@babel/helper-define-polyfill-provider@^0.6.1": - version "0.6.1" - resolved "https://registry.yarnpkg.com/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.6.1.tgz#fadc63f0c2ff3c8d02ed905dcea747c5b0fb74fd" - integrity sha512-o7SDgTJuvx5vLKD6SFvkydkSMBvahDKGiNJzG22IZYXhiqoe9efY7zocICBgzHV4IRg5wdgl2nEL/tulKIEIbA== +"@babel/helper-define-polyfill-provider@^0.6.5": + version "0.6.5" + resolved "https://registry.yarnpkg.com/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.6.5.tgz#742ccf1cb003c07b48859fc9fa2c1bbe40e5f753" + integrity sha512-uJnGFcPsWQK8fvjgGP5LZUZZsYGIoPeRjSF5PGwrelYgq7Q15/Ft9NGFp1zglwgIv//W0uG4BevRuSJRyylZPg== dependencies: - "@babel/helper-compilation-targets" "^7.22.6" - "@babel/helper-plugin-utils" "^7.22.5" - debug "^4.1.1" + "@babel/helper-compilation-targets" "^7.27.2" + "@babel/helper-plugin-utils" "^7.27.1" + debug "^4.4.1" lodash.debounce "^4.0.8" - resolve "^1.14.2" + resolve "^1.22.10" -"@babel/helper-environment-visitor@^7.22.20": - version "7.22.20" - resolved "https://registry.yarnpkg.com/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.20.tgz#96159db61d34a29dba454c959f5ae4a649ba9167" - integrity sha512-zfedSIzFhat/gFhWfHtgWvlec0nqB9YEIVrpuwjruLlXfUSnA8cJB0miHKwqDnQ7d32aKo2xt88/xZptwxbfhA== +"@babel/helper-globals@^7.28.0": + version "7.28.0" + resolved "https://registry.yarnpkg.com/@babel/helper-globals/-/helper-globals-7.28.0.tgz#b9430df2aa4e17bc28665eadeae8aa1d985e6674" + integrity sha512-+W6cISkXFa1jXsDEdYA8HeevQT/FULhxzR99pxphltZcVaugps53THCeiWA8SguxxpSp3gKPiuYfSWopkLQ4hw== -"@babel/helper-function-name@^7.22.5", "@babel/helper-function-name@^7.23.0": - version "7.23.0" - resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.23.0.tgz#1f9a3cdbd5b2698a670c30d2735f9af95ed52759" - integrity sha512-OErEqsrxjZTJciZ4Oo+eoZqeW9UIiOcuYKRJA4ZAgV9myA+pOXhhmpfNCKjEH/auVfEYVFJ6y1Tc4r0eIApqiw== +"@babel/helper-member-expression-to-functions@^7.27.1": + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.27.1.tgz#ea1211276be93e798ce19037da6f06fbb994fa44" + integrity sha512-E5chM8eWjTp/aNoVpcbfM7mLxu9XGLWYise2eBKGQomAk/Mb4XoxyqXTZbuTohbsl8EKqdlMhnDI2CCLfcs9wA== dependencies: - "@babel/template" "^7.22.15" - "@babel/types" "^7.23.0" + "@babel/traverse" "^7.27.1" + "@babel/types" "^7.27.1" -"@babel/helper-hoist-variables@^7.22.5": - version "7.22.5" - resolved "https://registry.yarnpkg.com/@babel/helper-hoist-variables/-/helper-hoist-variables-7.22.5.tgz#c01a007dac05c085914e8fb652b339db50d823bb" - integrity sha512-wGjk9QZVzvknA6yKIUURb8zY3grXCcOZt+/7Wcy8O2uctxhplmUPkOdlgoNhmdVee2c92JXbf1xpMtVNbfoxRw== +"@babel/helper-module-imports@^7.27.1": + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.27.1.tgz#7ef769a323e2655e126673bb6d2d6913bbead204" + integrity sha512-0gSFWUPNXNopqtIPQvlD5WgXYI5GY2kP2cCvoT8kczjbfcfuIljTbcWrulD1CIPIX2gt1wghbDy08yE1p+/r3w== dependencies: - "@babel/types" "^7.22.5" + "@babel/traverse" "^7.27.1" + "@babel/types" "^7.27.1" -"@babel/helper-member-expression-to-functions@^7.23.0": - version "7.23.0" - resolved "https://registry.yarnpkg.com/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.23.0.tgz#9263e88cc5e41d39ec18c9a3e0eced59a3e7d366" - integrity sha512-6gfrPwh7OuT6gZyJZvd6WbTfrqAo7vm4xCzAXOusKqq/vWdKXphTpj5klHKNmRUU6/QRGlBsyU9mAIPaWHlqJA== +"@babel/helper-module-transforms@^7.23.3", "@babel/helper-module-transforms@^7.27.1", "@babel/helper-module-transforms@^7.27.3": + version "7.27.3" + resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.27.3.tgz#db0bbcfba5802f9ef7870705a7ef8788508ede02" + integrity sha512-dSOvYwvyLsWBeIRyOeHXp5vPj5l1I011r52FM1+r1jCERv+aFXYk4whgQccYEGYxK2H3ZAIA8nuPkQ0HaUo3qg== dependencies: - "@babel/types" "^7.23.0" + "@babel/helper-module-imports" "^7.27.1" + "@babel/helper-validator-identifier" "^7.27.1" + "@babel/traverse" "^7.27.3" -"@babel/helper-module-imports@^7.22.15", "@babel/helper-module-imports@^7.24.1": - version "7.24.3" - resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.24.3.tgz#6ac476e6d168c7c23ff3ba3cf4f7841d46ac8128" - integrity sha512-viKb0F9f2s0BCS22QSF308z/+1YWKV/76mwt61NBzS5izMzDPwdq1pTrzf+Li3npBWX9KdQbkeCt1jSAM7lZqg== +"@babel/helper-optimise-call-expression@^7.27.1": + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.27.1.tgz#c65221b61a643f3e62705e5dd2b5f115e35f9200" + integrity sha512-URMGH08NzYFhubNSGJrpUEphGKQwMQYBySzat5cAByY1/YgIRkULnIy3tAMeszlL/so2HbeilYloUmSpd7GdVw== dependencies: - "@babel/types" "^7.24.0" + "@babel/types" "^7.27.1" -"@babel/helper-module-transforms@^7.23.3": - version "7.23.3" - resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.23.3.tgz#d7d12c3c5d30af5b3c0fcab2a6d5217773e2d0f1" - integrity sha512-7bBs4ED9OmswdfDzpz4MpWgSrV7FXlc3zIagvLFjS5H+Mk7Snr21vQ6QwrsoCGMfNC4e4LQPdoULEt4ykz0SRQ== - dependencies: - "@babel/helper-environment-visitor" "^7.22.20" - "@babel/helper-module-imports" "^7.22.15" - "@babel/helper-simple-access" "^7.22.5" - "@babel/helper-split-export-declaration" "^7.22.6" - "@babel/helper-validator-identifier" "^7.22.20" +"@babel/helper-plugin-utils@^7.0.0", "@babel/helper-plugin-utils@^7.18.6", "@babel/helper-plugin-utils@^7.24.0", "@babel/helper-plugin-utils@^7.27.1": + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.27.1.tgz#ddb2f876534ff8013e6c2b299bf4d39b3c51d44c" + integrity sha512-1gn1Up5YXka3YYAHGKpbideQ5Yjf1tDa9qYcgysz+cNCXukyLl6DjPXhD3VRwSb8c0J9tA4b2+rHEZtc6R0tlw== -"@babel/helper-optimise-call-expression@^7.22.5": - version "7.22.5" - resolved "https://registry.yarnpkg.com/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.22.5.tgz#f21531a9ccbff644fdd156b4077c16ff0c3f609e" - integrity sha512-HBwaojN0xFRx4yIvpwGqxiV2tUfl7401jlok564NgB9EHS1y6QT17FmKWm4ztqjeVdXLuC4fSvHc5ePpQjoTbw== - dependencies: - "@babel/types" "^7.22.5" - -"@babel/helper-plugin-utils@^7.0.0", "@babel/helper-plugin-utils@^7.10.4", "@babel/helper-plugin-utils@^7.12.13", "@babel/helper-plugin-utils@^7.14.5", "@babel/helper-plugin-utils@^7.18.6", "@babel/helper-plugin-utils@^7.22.5", "@babel/helper-plugin-utils@^7.24.0", "@babel/helper-plugin-utils@^7.8.0", "@babel/helper-plugin-utils@^7.8.3": +"@babel/helper-plugin-utils@^7.12.13": version "7.24.0" resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.24.0.tgz#945681931a52f15ce879fd5b86ce2dae6d3d7f2a" integrity sha512-9cUznXMG0+FxRuJfvL82QlTqIzhVW9sL0KjMPHhAOOvpQGL8QtdxnBKILjBqxlHyliz0yCa1G903ZXI/FuHy2w== -"@babel/helper-remap-async-to-generator@^7.22.20": - version "7.22.20" - resolved "https://registry.yarnpkg.com/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.22.20.tgz#7b68e1cb4fa964d2996fd063723fb48eca8498e0" - integrity sha512-pBGyV4uBqOns+0UvhsTO8qgl8hO89PmiDYv+/COyp1aeMcmfrfruz+/nCMFiYyFF/Knn0yfrC85ZzNFjembFTw== +"@babel/helper-remap-async-to-generator@^7.27.1": + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.27.1.tgz#4601d5c7ce2eb2aea58328d43725523fcd362ce6" + integrity sha512-7fiA521aVw8lSPeI4ZOD3vRFkoqkJcS+z4hFo82bFSH/2tNd6eJ5qCVMS5OzDmZh/kaHQeBaeyxK6wljcPtveA== dependencies: - "@babel/helper-annotate-as-pure" "^7.22.5" - "@babel/helper-environment-visitor" "^7.22.20" - "@babel/helper-wrap-function" "^7.22.20" + "@babel/helper-annotate-as-pure" "^7.27.1" + "@babel/helper-wrap-function" "^7.27.1" + "@babel/traverse" "^7.27.1" -"@babel/helper-replace-supers@^7.24.1": - version "7.24.1" - resolved "https://registry.yarnpkg.com/@babel/helper-replace-supers/-/helper-replace-supers-7.24.1.tgz#7085bd19d4a0b7ed8f405c1ed73ccb70f323abc1" - integrity sha512-QCR1UqC9BzG5vZl8BMicmZ28RuUBnHhAMddD8yHFHDRH9lLTZ9uUPehX8ctVPT8l0TKblJidqcgUUKGVrePleQ== +"@babel/helper-replace-supers@^7.27.1": + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/helper-replace-supers/-/helper-replace-supers-7.27.1.tgz#b1ed2d634ce3bdb730e4b52de30f8cccfd692bc0" + integrity sha512-7EHz6qDZc8RYS5ElPoShMheWvEgERonFCs7IAonWLLUTXW59DP14bCZt89/GKyreYn8g3S83m21FelHKbeDCKA== dependencies: - "@babel/helper-environment-visitor" "^7.22.20" - "@babel/helper-member-expression-to-functions" "^7.23.0" - "@babel/helper-optimise-call-expression" "^7.22.5" + "@babel/helper-member-expression-to-functions" "^7.27.1" + "@babel/helper-optimise-call-expression" "^7.27.1" + "@babel/traverse" "^7.27.1" -"@babel/helper-simple-access@^7.22.5": - version "7.22.5" - resolved "https://registry.yarnpkg.com/@babel/helper-simple-access/-/helper-simple-access-7.22.5.tgz#4938357dc7d782b80ed6dbb03a0fba3d22b1d5de" - integrity sha512-n0H99E/K+Bika3++WNL17POvo4rKWZ7lZEp1Q+fStVbUi8nxPQEBOlTmCOxW/0JsS56SKKQ+ojAe2pHKJHN35w== +"@babel/helper-skip-transparent-expression-wrappers@^7.27.1": + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.27.1.tgz#62bb91b3abba8c7f1fec0252d9dbea11b3ee7a56" + integrity sha512-Tub4ZKEXqbPjXgWLl2+3JpQAYBJ8+ikpQ2Ocj/q/r0LwE3UhENh7EUabyHjz2kCEsrRY83ew2DQdHluuiDQFzg== dependencies: - "@babel/types" "^7.22.5" + "@babel/traverse" "^7.27.1" + "@babel/types" "^7.27.1" -"@babel/helper-skip-transparent-expression-wrappers@^7.22.5": - version "7.22.5" - resolved "https://registry.yarnpkg.com/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.22.5.tgz#007f15240b5751c537c40e77abb4e89eeaaa8847" - integrity sha512-tK14r66JZKiC43p8Ki33yLBVJKlQDFoA8GYN67lWCDCqoL6EMMSuM9b+Iff2jHaM/RRFYl7K+iiru7hbRqNx8Q== +"@babel/helper-string-parser@^7.27.1": + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/helper-string-parser/-/helper-string-parser-7.27.1.tgz#54da796097ab19ce67ed9f88b47bb2ec49367687" + integrity sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA== + +"@babel/helper-validator-identifier@^7.27.1": + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.27.1.tgz#a7054dcc145a967dd4dc8fee845a57c1316c9df8" + integrity sha512-D2hP9eA+Sqx1kBZgzxZh0y1trbuU+JoDkiEwqhQ36nodYqJwyEIhPSdMNd7lOm/4io72luTPWH20Yda0xOuUow== + +"@babel/helper-validator-option@^7.27.1": + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/helper-validator-option/-/helper-validator-option-7.27.1.tgz#fa52f5b1e7db1ab049445b421c4471303897702f" + integrity sha512-YvjJow9FxbhFFKDSuFnVCe2WxXk1zWc22fFePVNEaWJEu8IrZVlda6N0uHwzZrUM1il7NC9Mlp4MaJYbYd9JSg== + +"@babel/helper-wrap-function@^7.27.1": + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/helper-wrap-function/-/helper-wrap-function-7.27.1.tgz#b88285009c31427af318d4fe37651cd62a142409" + integrity sha512-NFJK2sHUvrjo8wAU/nQTWU890/zB2jj0qBcCbZbbf+005cAsv6tMjXz31fBign6M5ov1o0Bllu+9nbqkfsjjJQ== dependencies: - "@babel/types" "^7.22.5" + "@babel/template" "^7.27.1" + "@babel/traverse" "^7.27.1" + "@babel/types" "^7.27.1" -"@babel/helper-split-export-declaration@^7.22.6": - version "7.22.6" - resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.22.6.tgz#322c61b7310c0997fe4c323955667f18fcefb91c" - integrity sha512-AsUnxuLhRYsisFiaJwvp1QF+I3KjD5FOxut14q/GzovUe6orHLesW2C7d754kRm53h5gqrz6sFl6sxc4BVtE/g== +"@babel/helpers@^7.24.4", "@babel/helpers@^7.27.6": + version "7.27.6" + resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.27.6.tgz#6456fed15b2cb669d2d1fabe84b66b34991d812c" + integrity sha512-muE8Tt8M22638HU31A3CgfSUciwz1fhATfoVai05aPXGor//CdWDCbnlY1yvBPo07njuVOCNGCSp/GTt12lIug== dependencies: - "@babel/types" "^7.22.5" + "@babel/template" "^7.27.2" + "@babel/types" "^7.27.6" -"@babel/helper-string-parser@^7.23.4": - version "7.24.1" - resolved "https://registry.yarnpkg.com/@babel/helper-string-parser/-/helper-string-parser-7.24.1.tgz#f99c36d3593db9540705d0739a1f10b5e20c696e" - integrity sha512-2ofRCjnnA9y+wk8b9IAREroeUP02KHp431N2mhKniy2yKIDKpbrHv9eXwm8cBeWQYcJmzv5qKCu65P47eCF7CQ== - -"@babel/helper-validator-identifier@^7.22.20": - version "7.22.20" - resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.20.tgz#c4ae002c61d2879e724581d96665583dbc1dc0e0" - integrity sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A== - -"@babel/helper-validator-option@^7.23.5": - version "7.23.5" - resolved "https://registry.yarnpkg.com/@babel/helper-validator-option/-/helper-validator-option-7.23.5.tgz#907a3fbd4523426285365d1206c423c4c5520307" - integrity sha512-85ttAOMLsr53VgXkTbkx8oA6YTfT4q7/HzXSLEYmjcSTJPMPQtvq1BD79Byep5xMUYbGRzEpDsjUf3dyp54IKw== - -"@babel/helper-wrap-function@^7.22.20": - version "7.22.20" - resolved "https://registry.yarnpkg.com/@babel/helper-wrap-function/-/helper-wrap-function-7.22.20.tgz#15352b0b9bfb10fc9c76f79f6342c00e3411a569" - integrity sha512-pms/UwkOpnQe/PDAEdV/d7dVCoBbB+R4FvYoHGZz+4VPcg7RtYy2KP7S2lbuWM6FCSgob5wshfGESbC/hzNXZw== +"@babel/parser@^7.24.4", "@babel/parser@^7.27.2", "@babel/parser@^7.28.0": + version "7.28.0" + resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.28.0.tgz#979829fbab51a29e13901e5a80713dbcb840825e" + integrity sha512-jVZGvOxOuNSsuQuLRTh13nU0AogFlw32w/MT+LV6D3sP5WdbW61E77RnkbaO2dUvmPAYrBDJXGn5gGS6tH4j8g== dependencies: - "@babel/helper-function-name" "^7.22.5" - "@babel/template" "^7.22.15" - "@babel/types" "^7.22.19" + "@babel/types" "^7.28.0" -"@babel/helpers@^7.24.4": - version "7.24.4" - resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.24.4.tgz#dc00907fd0d95da74563c142ef4cd21f2cb856b6" - integrity sha512-FewdlZbSiwaVGlgT1DPANDuCHaDMiOo+D/IDYRFYjHOuv66xMSJ7fQwwODwRNAPkADIO/z1EoF/l2BCWlWABDw== +"@babel/plugin-bugfix-firefox-class-in-computed-class-key@^7.27.1": + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-bugfix-firefox-class-in-computed-class-key/-/plugin-bugfix-firefox-class-in-computed-class-key-7.27.1.tgz#61dd8a8e61f7eb568268d1b5f129da3eee364bf9" + integrity sha512-QPG3C9cCVRQLxAVwmefEmwdTanECuUBMQZ/ym5kiw3XKCGA7qkuQLcjWWHcrD/GKbn/WmJwaezfuuAOcyKlRPA== dependencies: - "@babel/template" "^7.24.0" - "@babel/traverse" "^7.24.1" - "@babel/types" "^7.24.0" + "@babel/helper-plugin-utils" "^7.27.1" + "@babel/traverse" "^7.27.1" -"@babel/highlight@^7.24.2": - version "7.24.2" - resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.24.2.tgz#3f539503efc83d3c59080a10e6634306e0370d26" - integrity sha512-Yac1ao4flkTxTteCDZLEvdxg2fZfz1v8M4QpaGypq/WPDqg3ijHYbDfs+LG5hvzSoqaSZ9/Z9lKSP3CjZjv+pA== +"@babel/plugin-bugfix-safari-class-field-initializer-scope@^7.27.1": + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-bugfix-safari-class-field-initializer-scope/-/plugin-bugfix-safari-class-field-initializer-scope-7.27.1.tgz#43f70a6d7efd52370eefbdf55ae03d91b293856d" + integrity sha512-qNeq3bCKnGgLkEXUuFry6dPlGfCdQNZbn7yUAPCInwAJHMU7THJfrBSozkcWq5sNM6RcF3S8XyQL2A52KNR9IA== dependencies: - "@babel/helper-validator-identifier" "^7.22.20" - chalk "^2.4.2" - js-tokens "^4.0.0" - picocolors "^1.0.0" + "@babel/helper-plugin-utils" "^7.27.1" -"@babel/parser@^7.24.0", "@babel/parser@^7.24.1", "@babel/parser@^7.24.4": - version "7.24.4" - resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.24.4.tgz#234487a110d89ad5a3ed4a8a566c36b9453e8c88" - integrity sha512-zTvEBcghmeBma9QIGunWevvBAp4/Qu9Bdq+2k0Ot4fVMD6v3dsC9WOcRSKk7tRRyBM/53yKMJko9xOatGQAwSg== - -"@babel/plugin-bugfix-firefox-class-in-computed-class-key@^7.24.4": - version "7.24.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-bugfix-firefox-class-in-computed-class-key/-/plugin-bugfix-firefox-class-in-computed-class-key-7.24.4.tgz#6125f0158543fb4edf1c22f322f3db67f21cb3e1" - integrity sha512-qpl6vOOEEzTLLcsuqYYo8yDtrTocmu2xkGvgNebvPjT9DTtfFYGmgDqY+rBYXNlqL4s9qLDn6xkrJv4RxAPiTA== +"@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@^7.27.1": + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.27.1.tgz#beb623bd573b8b6f3047bd04c32506adc3e58a72" + integrity sha512-g4L7OYun04N1WyqMNjldFwlfPCLVkgB54A/YCXICZYBsvJJE3kByKv9c9+R/nAfmIfjl2rKYLNyMHboYbZaWaA== dependencies: - "@babel/helper-environment-visitor" "^7.22.20" - "@babel/helper-plugin-utils" "^7.24.0" + "@babel/helper-plugin-utils" "^7.27.1" -"@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@^7.24.1": - version "7.24.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.24.1.tgz#b645d9ba8c2bc5b7af50f0fe949f9edbeb07c8cf" - integrity sha512-y4HqEnkelJIOQGd+3g1bTeKsA5c6qM7eOn7VggGVbBc0y8MLSKHacwcIE2PplNlQSj0PqS9rrXL/nkPVK+kUNg== +"@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining@^7.27.1": + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.27.1.tgz#e134a5479eb2ba9c02714e8c1ebf1ec9076124fd" + integrity sha512-oO02gcONcD5O1iTLi/6frMJBIwWEHceWGSGqrpCmEL8nogiS6J9PBlE48CaK20/Jx1LuRml9aDftLgdjXT8+Cw== dependencies: - "@babel/helper-plugin-utils" "^7.24.0" + "@babel/helper-plugin-utils" "^7.27.1" + "@babel/helper-skip-transparent-expression-wrappers" "^7.27.1" + "@babel/plugin-transform-optional-chaining" "^7.27.1" -"@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining@^7.24.1": - version "7.24.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.24.1.tgz#da8261f2697f0f41b0855b91d3a20a1fbfd271d3" - integrity sha512-Hj791Ii4ci8HqnaKHAlLNs+zaLXb0EzSDhiAWp5VNlyvCNymYfacs64pxTxbH1znW/NcArSmwpmG9IKE/TUVVQ== +"@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly@^7.27.1": + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly/-/plugin-bugfix-v8-static-class-fields-redefine-readonly-7.27.1.tgz#bb1c25af34d75115ce229a1de7fa44bf8f955670" + integrity sha512-6BpaYGDavZqkI6yT+KSPdpZFfpnd68UKXbcjI9pJ13pvHhPrCKWOOLp+ysvMeA+DxnhuPpgIaRpxRxo5A9t5jw== dependencies: - "@babel/helper-plugin-utils" "^7.24.0" - "@babel/helper-skip-transparent-expression-wrappers" "^7.22.5" - "@babel/plugin-transform-optional-chaining" "^7.24.1" - -"@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly@^7.24.1": - version "7.24.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly/-/plugin-bugfix-v8-static-class-fields-redefine-readonly-7.24.1.tgz#1181d9685984c91d657b8ddf14f0487a6bab2988" - integrity sha512-m9m/fXsXLiHfwdgydIFnpk+7jlVbnvlK5B2EKiPdLUb6WX654ZaaEWJUjk8TftRbZpK0XibovlLWX4KIZhV6jw== - dependencies: - "@babel/helper-environment-visitor" "^7.22.20" - "@babel/helper-plugin-utils" "^7.24.0" + "@babel/helper-plugin-utils" "^7.27.1" + "@babel/traverse" "^7.27.1" "@babel/plugin-proposal-private-property-in-object@7.21.0-placeholder-for-preset-env.2": version "7.21.0-placeholder-for-preset-env.2" resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.21.0-placeholder-for-preset-env.2.tgz#7844f9289546efa9febac2de4cfe358a050bd703" integrity sha512-SOSkfJDddaM7mak6cPEpswyTRnuRltl429hMraQEglW+OkovnCzsiszTmsrlY//qLFjCpQDFRvjdm2wA5pPm9w== -"@babel/plugin-syntax-async-generators@^7.8.4": - version "7.8.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz#a983fb1aeb2ec3f6ed042a210f640e90e786fe0d" - integrity sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw== - dependencies: - "@babel/helper-plugin-utils" "^7.8.0" - "@babel/plugin-syntax-class-properties@^7.12.13": version "7.12.13" resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz#b5c987274c4a3a82b89714796931a6b53544ae10" @@ -375,13 +358,6 @@ dependencies: "@babel/helper-plugin-utils" "^7.12.13" -"@babel/plugin-syntax-class-static-block@^7.14.5": - version "7.14.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-class-static-block/-/plugin-syntax-class-static-block-7.14.5.tgz#195df89b146b4b78b3bf897fd7a257c84659d406" - integrity sha512-b+YyPmr6ldyNnM6sqYeMWE+bgJcJpO6yS4QD7ymxgH34GBPNDM/THBh8iunyvKIZztiwLH4CJZ0RxTk9emgpjw== - dependencies: - "@babel/helper-plugin-utils" "^7.14.5" - "@babel/plugin-syntax-decorators@^7.12.13": version "7.24.1" resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-decorators/-/plugin-syntax-decorators-7.24.1.tgz#71d9ad06063a6ac5430db126b5df48c70ee885fa" @@ -389,110 +365,33 @@ dependencies: "@babel/helper-plugin-utils" "^7.24.0" -"@babel/plugin-syntax-dynamic-import@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-dynamic-import/-/plugin-syntax-dynamic-import-7.8.3.tgz#62bf98b2da3cd21d626154fc96ee5b3cb68eacb3" - integrity sha512-5gdGbFon+PszYzqs83S3E5mpi7/y/8M9eC90MRTZfduQOYW76ig6SOSPNe41IG5LoP3FGBn2N0RjVDSQiS94kQ== +"@babel/plugin-syntax-import-assertions@^7.27.1": + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-import-assertions/-/plugin-syntax-import-assertions-7.27.1.tgz#88894aefd2b03b5ee6ad1562a7c8e1587496aecd" + integrity sha512-UT/Jrhw57xg4ILHLFnzFpPDlMbcdEicaAtjPQpbj9wa8T4r5KVWCimHcL/460g8Ht0DMxDyjsLgiWSkVjnwPFg== dependencies: - "@babel/helper-plugin-utils" "^7.8.0" + "@babel/helper-plugin-utils" "^7.27.1" -"@babel/plugin-syntax-export-namespace-from@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-export-namespace-from/-/plugin-syntax-export-namespace-from-7.8.3.tgz#028964a9ba80dbc094c915c487ad7c4e7a66465a" - integrity sha512-MXf5laXo6c1IbEbegDmzGPwGNTsHZmEy6QGznu5Sh2UCWvueywb2ee+CCE4zQiZstxU9BMoQO9i6zUFSY0Kj0Q== +"@babel/plugin-syntax-import-attributes@^7.27.1": + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.27.1.tgz#34c017d54496f9b11b61474e7ea3dfd5563ffe07" + integrity sha512-oFT0FrKHgF53f4vOsZGi2Hh3I35PfSmVs4IBFLFj4dnafP+hIWDLg3VyKmUHfLoLHlyxY4C7DGtmHuJgn+IGww== dependencies: - "@babel/helper-plugin-utils" "^7.8.3" + "@babel/helper-plugin-utils" "^7.27.1" -"@babel/plugin-syntax-import-assertions@^7.24.1": - version "7.24.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-import-assertions/-/plugin-syntax-import-assertions-7.24.1.tgz#db3aad724153a00eaac115a3fb898de544e34971" - integrity sha512-IuwnI5XnuF189t91XbxmXeCDz3qs6iDRO7GJ++wcfgeXNs/8FmIlKcpDSXNVyuLQxlwvskmI3Ct73wUODkJBlQ== - dependencies: - "@babel/helper-plugin-utils" "^7.24.0" - -"@babel/plugin-syntax-import-attributes@^7.24.1": - version "7.24.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.24.1.tgz#c66b966c63b714c4eec508fcf5763b1f2d381093" - integrity sha512-zhQTMH0X2nVLnb04tz+s7AMuasX8U0FnpE+nHTOhSOINjWMnopoZTxtIKsd45n4GQ/HIZLyfIpoul8e2m0DnRA== - dependencies: - "@babel/helper-plugin-utils" "^7.24.0" - -"@babel/plugin-syntax-import-meta@^7.10.4": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.10.4.tgz#ee601348c370fa334d2207be158777496521fd51" - integrity sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g== - dependencies: - "@babel/helper-plugin-utils" "^7.10.4" - -"@babel/plugin-syntax-json-strings@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz#01ca21b668cd8218c9e640cb6dd88c5412b2c96a" - integrity sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA== - dependencies: - "@babel/helper-plugin-utils" "^7.8.0" - -"@babel/plugin-syntax-jsx@^7.12.13", "@babel/plugin-syntax-jsx@^7.23.3": +"@babel/plugin-syntax-jsx@^7.12.13": version "7.24.1" resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.24.1.tgz#3f6ca04b8c841811dbc3c5c5f837934e0d626c10" integrity sha512-2eCtxZXf+kbkMIsXS4poTvT4Yu5rXiRa+9xGVT56raghjmBTKMpFNc9R4IDiB4emao9eO22Ox7CxuJG7BgExqA== dependencies: "@babel/helper-plugin-utils" "^7.24.0" -"@babel/plugin-syntax-logical-assignment-operators@^7.10.4": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz#ca91ef46303530448b906652bac2e9fe9941f699" - integrity sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig== +"@babel/plugin-syntax-jsx@^7.27.1": + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.27.1.tgz#2f9beb5eff30fa507c5532d107daac7b888fa34c" + integrity sha512-y8YTNIeKoyhGd9O0Jiyzyyqk8gdjnumGTQPsz0xOZOQ2RmkVJeZ1vmmfIvFEKqucBG6axJGBZDE/7iI5suUI/w== dependencies: - "@babel/helper-plugin-utils" "^7.10.4" - -"@babel/plugin-syntax-nullish-coalescing-operator@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz#167ed70368886081f74b5c36c65a88c03b66d1a9" - integrity sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ== - dependencies: - "@babel/helper-plugin-utils" "^7.8.0" - -"@babel/plugin-syntax-numeric-separator@^7.10.4": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz#b9b070b3e33570cd9fd07ba7fa91c0dd37b9af97" - integrity sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug== - dependencies: - "@babel/helper-plugin-utils" "^7.10.4" - -"@babel/plugin-syntax-object-rest-spread@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz#60e225edcbd98a640332a2e72dd3e66f1af55871" - integrity sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA== - dependencies: - "@babel/helper-plugin-utils" "^7.8.0" - -"@babel/plugin-syntax-optional-catch-binding@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz#6111a265bcfb020eb9efd0fdfd7d26402b9ed6c1" - integrity sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q== - dependencies: - "@babel/helper-plugin-utils" "^7.8.0" - -"@babel/plugin-syntax-optional-chaining@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz#4f69c2ab95167e0180cd5336613f8c5788f7d48a" - integrity sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg== - dependencies: - "@babel/helper-plugin-utils" "^7.8.0" - -"@babel/plugin-syntax-private-property-in-object@^7.14.5": - version "7.14.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-private-property-in-object/-/plugin-syntax-private-property-in-object-7.14.5.tgz#0dc6671ec0ea22b6e94a1114f857970cd39de1ad" - integrity sha512-0wVnp9dxJ72ZUJDV27ZfbSj6iHLoytYZmh3rFcxNnvsJF3ktkzLDZPy/mA17HGsaQT3/DQsWYX1f1QGWkCoVUg== - dependencies: - "@babel/helper-plugin-utils" "^7.14.5" - -"@babel/plugin-syntax-top-level-await@^7.14.5": - version "7.14.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz#c1cfdadc35a646240001f06138247b741c34d94c" - integrity sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw== - dependencies: - "@babel/helper-plugin-utils" "^7.14.5" + "@babel/helper-plugin-utils" "^7.27.1" "@babel/plugin-syntax-unicode-sets-regex@^7.18.6": version "7.18.6" @@ -502,496 +401,495 @@ "@babel/helper-create-regexp-features-plugin" "^7.18.6" "@babel/helper-plugin-utils" "^7.18.6" -"@babel/plugin-transform-arrow-functions@^7.24.1": - version "7.24.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.24.1.tgz#2bf263617060c9cc45bcdbf492b8cc805082bf27" - integrity sha512-ngT/3NkRhsaep9ck9uj2Xhv9+xB1zShY3tM3g6om4xxCELwCDN4g4Aq5dRn48+0hasAql7s2hdBOysCfNpr4fw== +"@babel/plugin-transform-arrow-functions@^7.27.1": + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.27.1.tgz#6e2061067ba3ab0266d834a9f94811196f2aba9a" + integrity sha512-8Z4TGic6xW70FKThA5HYEKKyBpOOsucTOD1DjU3fZxDg+K3zBJcXMFnt/4yQiZnf5+MiOMSXQ9PaEK/Ilh1DeA== dependencies: - "@babel/helper-plugin-utils" "^7.24.0" + "@babel/helper-plugin-utils" "^7.27.1" -"@babel/plugin-transform-async-generator-functions@^7.24.3": - version "7.24.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-async-generator-functions/-/plugin-transform-async-generator-functions-7.24.3.tgz#8fa7ae481b100768cc9842c8617808c5352b8b89" - integrity sha512-Qe26CMYVjpQxJ8zxM1340JFNjZaF+ISWpr1Kt/jGo+ZTUzKkfw/pphEWbRCb+lmSM6k/TOgfYLvmbHkUQ0asIg== +"@babel/plugin-transform-async-generator-functions@^7.28.0": + version "7.28.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-async-generator-functions/-/plugin-transform-async-generator-functions-7.28.0.tgz#1276e6c7285ab2cd1eccb0bc7356b7a69ff842c2" + integrity sha512-BEOdvX4+M765icNPZeidyADIvQ1m1gmunXufXxvRESy/jNNyfovIqUyE7MVgGBjWktCoJlzvFA1To2O4ymIO3Q== dependencies: - "@babel/helper-environment-visitor" "^7.22.20" - "@babel/helper-plugin-utils" "^7.24.0" - "@babel/helper-remap-async-to-generator" "^7.22.20" - "@babel/plugin-syntax-async-generators" "^7.8.4" + "@babel/helper-plugin-utils" "^7.27.1" + "@babel/helper-remap-async-to-generator" "^7.27.1" + "@babel/traverse" "^7.28.0" -"@babel/plugin-transform-async-to-generator@^7.24.1": - version "7.24.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.24.1.tgz#0e220703b89f2216800ce7b1c53cb0cf521c37f4" - integrity sha512-AawPptitRXp1y0n4ilKcGbRYWfbbzFWz2NqNu7dacYDtFtz0CMjG64b3LQsb3KIgnf4/obcUL78hfaOS7iCUfw== +"@babel/plugin-transform-async-to-generator@^7.27.1": + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.27.1.tgz#9a93893b9379b39466c74474f55af03de78c66e7" + integrity sha512-NREkZsZVJS4xmTr8qzE5y8AfIPqsdQfRuUiLRTEzb7Qii8iFWCyDKaUV2c0rCuh4ljDZ98ALHP/PetiBV2nddA== dependencies: - "@babel/helper-module-imports" "^7.24.1" - "@babel/helper-plugin-utils" "^7.24.0" - "@babel/helper-remap-async-to-generator" "^7.22.20" + "@babel/helper-module-imports" "^7.27.1" + "@babel/helper-plugin-utils" "^7.27.1" + "@babel/helper-remap-async-to-generator" "^7.27.1" -"@babel/plugin-transform-block-scoped-functions@^7.24.1": - version "7.24.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.24.1.tgz#1c94799e20fcd5c4d4589523bbc57b7692979380" - integrity sha512-TWWC18OShZutrv9C6mye1xwtam+uNi2bnTOCBUd5sZxyHOiWbU6ztSROofIMrK84uweEZC219POICK/sTYwfgg== +"@babel/plugin-transform-block-scoped-functions@^7.27.1": + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.27.1.tgz#558a9d6e24cf72802dd3b62a4b51e0d62c0f57f9" + integrity sha512-cnqkuOtZLapWYZUYM5rVIdv1nXYuFVIltZ6ZJ7nIj585QsjKM5dhL2Fu/lICXZ1OyIAFc7Qy+bvDAtTXqGrlhg== dependencies: - "@babel/helper-plugin-utils" "^7.24.0" + "@babel/helper-plugin-utils" "^7.27.1" -"@babel/plugin-transform-block-scoping@^7.24.4": - version "7.24.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.24.4.tgz#28f5c010b66fbb8ccdeef853bef1935c434d7012" - integrity sha512-nIFUZIpGKDf9O9ttyRXpHFpKC+X3Y5mtshZONuEUYBomAKoM4y029Jr+uB1bHGPhNmK8YXHevDtKDOLmtRrp6g== +"@babel/plugin-transform-block-scoping@^7.28.0": + version "7.28.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.28.0.tgz#e7c50cbacc18034f210b93defa89638666099451" + integrity sha512-gKKnwjpdx5sER/wl0WN0efUBFzF/56YZO0RJrSYP4CljXnP31ByY7fol89AzomdlLNzI36AvOTmYHsnZTCkq8Q== dependencies: - "@babel/helper-plugin-utils" "^7.24.0" + "@babel/helper-plugin-utils" "^7.27.1" -"@babel/plugin-transform-class-properties@^7.24.1": - version "7.24.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-class-properties/-/plugin-transform-class-properties-7.24.1.tgz#bcbf1aef6ba6085cfddec9fc8d58871cf011fc29" - integrity sha512-OMLCXi0NqvJfORTaPQBwqLXHhb93wkBKZ4aNwMl6WtehO7ar+cmp+89iPEQPqxAnxsOKTaMcs3POz3rKayJ72g== +"@babel/plugin-transform-class-properties@^7.27.1": + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-class-properties/-/plugin-transform-class-properties-7.27.1.tgz#dd40a6a370dfd49d32362ae206ddaf2bb082a925" + integrity sha512-D0VcalChDMtuRvJIu3U/fwWjf8ZMykz5iZsg77Nuj821vCKI3zCyRLwRdWbsuJ/uRwZhZ002QtCqIkwC/ZkvbA== dependencies: - "@babel/helper-create-class-features-plugin" "^7.24.1" - "@babel/helper-plugin-utils" "^7.24.0" + "@babel/helper-create-class-features-plugin" "^7.27.1" + "@babel/helper-plugin-utils" "^7.27.1" -"@babel/plugin-transform-class-static-block@^7.24.4": - version "7.24.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-class-static-block/-/plugin-transform-class-static-block-7.24.4.tgz#1a4653c0cf8ac46441ec406dece6e9bc590356a4" - integrity sha512-B8q7Pz870Hz/q9UgP8InNpY01CSLDSCyqX7zcRuv3FcPl87A2G17lASroHWaCtbdIcbYzOZ7kWmXFKbijMSmFg== +"@babel/plugin-transform-class-static-block@^7.27.1": + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-class-static-block/-/plugin-transform-class-static-block-7.27.1.tgz#7e920d5625b25bbccd3061aefbcc05805ed56ce4" + integrity sha512-s734HmYU78MVzZ++joYM+NkJusItbdRcbm+AGRgJCt3iA+yux0QpD9cBVdz3tKyrjVYWRl7j0mHSmv4lhV0aoA== dependencies: - "@babel/helper-create-class-features-plugin" "^7.24.4" - "@babel/helper-plugin-utils" "^7.24.0" - "@babel/plugin-syntax-class-static-block" "^7.14.5" + "@babel/helper-create-class-features-plugin" "^7.27.1" + "@babel/helper-plugin-utils" "^7.27.1" -"@babel/plugin-transform-classes@^7.24.1": - version "7.24.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-classes/-/plugin-transform-classes-7.24.1.tgz#5bc8fc160ed96378184bc10042af47f50884dcb1" - integrity sha512-ZTIe3W7UejJd3/3R4p7ScyyOoafetUShSf4kCqV0O7F/RiHxVj/wRaRnQlrGwflvcehNA8M42HkAiEDYZu2F1Q== +"@babel/plugin-transform-classes@^7.28.0": + version "7.28.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-classes/-/plugin-transform-classes-7.28.0.tgz#12fa46cffc32a6e084011b650539e880add8a0f8" + integrity sha512-IjM1IoJNw72AZFlj33Cu8X0q2XK/6AaVC3jQu+cgQ5lThWD5ajnuUAml80dqRmOhmPkTH8uAwnpMu9Rvj0LTRA== dependencies: - "@babel/helper-annotate-as-pure" "^7.22.5" - "@babel/helper-compilation-targets" "^7.23.6" - "@babel/helper-environment-visitor" "^7.22.20" - "@babel/helper-function-name" "^7.23.0" - "@babel/helper-plugin-utils" "^7.24.0" - "@babel/helper-replace-supers" "^7.24.1" - "@babel/helper-split-export-declaration" "^7.22.6" - globals "^11.1.0" + "@babel/helper-annotate-as-pure" "^7.27.3" + "@babel/helper-compilation-targets" "^7.27.2" + "@babel/helper-globals" "^7.28.0" + "@babel/helper-plugin-utils" "^7.27.1" + "@babel/helper-replace-supers" "^7.27.1" + "@babel/traverse" "^7.28.0" -"@babel/plugin-transform-computed-properties@^7.24.1": - version "7.24.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.24.1.tgz#bc7e787f8e021eccfb677af5f13c29a9934ed8a7" - integrity sha512-5pJGVIUfJpOS+pAqBQd+QMaTD2vCL/HcePooON6pDpHgRp4gNRmzyHTPIkXntwKsq3ayUFVfJaIKPw2pOkOcTw== +"@babel/plugin-transform-computed-properties@^7.27.1": + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.27.1.tgz#81662e78bf5e734a97982c2b7f0a793288ef3caa" + integrity sha512-lj9PGWvMTVksbWiDT2tW68zGS/cyo4AkZ/QTp0sQT0mjPopCmrSkzxeXkznjqBxzDI6TclZhOJbBmbBLjuOZUw== dependencies: - "@babel/helper-plugin-utils" "^7.24.0" - "@babel/template" "^7.24.0" + "@babel/helper-plugin-utils" "^7.27.1" + "@babel/template" "^7.27.1" -"@babel/plugin-transform-destructuring@^7.24.1": - version "7.24.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.24.1.tgz#b1e8243af4a0206841973786292b8c8dd8447345" - integrity sha512-ow8jciWqNxR3RYbSNVuF4U2Jx130nwnBnhRw6N6h1bOejNkABmcI5X5oz29K4alWX7vf1C+o6gtKXikzRKkVdw== +"@babel/plugin-transform-destructuring@^7.28.0": + version "7.28.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.28.0.tgz#0f156588f69c596089b7d5b06f5af83d9aa7f97a" + integrity sha512-v1nrSMBiKcodhsyJ4Gf+Z0U/yawmJDBOTpEB3mcQY52r9RIyPneGyAS/yM6seP/8I+mWI3elOMtT5dB8GJVs+A== dependencies: - "@babel/helper-plugin-utils" "^7.24.0" + "@babel/helper-plugin-utils" "^7.27.1" + "@babel/traverse" "^7.28.0" -"@babel/plugin-transform-dotall-regex@^7.24.1": - version "7.24.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.24.1.tgz#d56913d2f12795cc9930801b84c6f8c47513ac13" - integrity sha512-p7uUxgSoZwZ2lPNMzUkqCts3xlp8n+o05ikjy7gbtFJSt9gdU88jAmtfmOxHM14noQXBxfgzf2yRWECiNVhTCw== +"@babel/plugin-transform-dotall-regex@^7.27.1": + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.27.1.tgz#aa6821de864c528b1fecf286f0a174e38e826f4d" + integrity sha512-gEbkDVGRvjj7+T1ivxrfgygpT7GUd4vmODtYpbs0gZATdkX8/iSnOtZSxiZnsgm1YjTgjI6VKBGSJJevkrclzw== dependencies: - "@babel/helper-create-regexp-features-plugin" "^7.22.15" - "@babel/helper-plugin-utils" "^7.24.0" + "@babel/helper-create-regexp-features-plugin" "^7.27.1" + "@babel/helper-plugin-utils" "^7.27.1" -"@babel/plugin-transform-duplicate-keys@^7.24.1": - version "7.24.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.24.1.tgz#5347a797fe82b8d09749d10e9f5b83665adbca88" - integrity sha512-msyzuUnvsjsaSaocV6L7ErfNsa5nDWL1XKNnDePLgmz+WdU4w/J8+AxBMrWfi9m4IxfL5sZQKUPQKDQeeAT6lA== +"@babel/plugin-transform-duplicate-keys@^7.27.1": + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.27.1.tgz#f1fbf628ece18e12e7b32b175940e68358f546d1" + integrity sha512-MTyJk98sHvSs+cvZ4nOauwTTG1JeonDjSGvGGUNHreGQns+Mpt6WX/dVzWBHgg+dYZhkC4X+zTDfkTU+Vy9y7Q== dependencies: - "@babel/helper-plugin-utils" "^7.24.0" + "@babel/helper-plugin-utils" "^7.27.1" -"@babel/plugin-transform-dynamic-import@^7.24.1": - version "7.24.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-dynamic-import/-/plugin-transform-dynamic-import-7.24.1.tgz#2a5a49959201970dd09a5fca856cb651e44439dd" - integrity sha512-av2gdSTyXcJVdI+8aFZsCAtR29xJt0S5tas+Ef8NvBNmD1a+N/3ecMLeMBgfcK+xzsjdLDT6oHt+DFPyeqUbDA== +"@babel/plugin-transform-duplicate-named-capturing-groups-regex@^7.27.1": + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-duplicate-named-capturing-groups-regex/-/plugin-transform-duplicate-named-capturing-groups-regex-7.27.1.tgz#5043854ca620a94149372e69030ff8cb6a9eb0ec" + integrity sha512-hkGcueTEzuhB30B3eJCbCYeCaaEQOmQR0AdvzpD4LoN0GXMWzzGSuRrxR2xTnCrvNbVwK9N6/jQ92GSLfiZWoQ== dependencies: - "@babel/helper-plugin-utils" "^7.24.0" - "@babel/plugin-syntax-dynamic-import" "^7.8.3" + "@babel/helper-create-regexp-features-plugin" "^7.27.1" + "@babel/helper-plugin-utils" "^7.27.1" -"@babel/plugin-transform-exponentiation-operator@^7.24.1": - version "7.24.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.24.1.tgz#6650ebeb5bd5c012d5f5f90a26613a08162e8ba4" - integrity sha512-U1yX13dVBSwS23DEAqU+Z/PkwE9/m7QQy8Y9/+Tdb8UWYaGNDYwTLi19wqIAiROr8sXVum9A/rtiH5H0boUcTw== +"@babel/plugin-transform-dynamic-import@^7.27.1": + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-dynamic-import/-/plugin-transform-dynamic-import-7.27.1.tgz#4c78f35552ac0e06aa1f6e3c573d67695e8af5a4" + integrity sha512-MHzkWQcEmjzzVW9j2q8LGjwGWpG2mjwaaB0BNQwst3FIjqsg8Ct/mIZlvSPJvfi9y2AC8mi/ktxbFVL9pZ1I4A== dependencies: - "@babel/helper-builder-binary-assignment-operator-visitor" "^7.22.15" - "@babel/helper-plugin-utils" "^7.24.0" + "@babel/helper-plugin-utils" "^7.27.1" -"@babel/plugin-transform-export-namespace-from@^7.24.1": - version "7.24.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-export-namespace-from/-/plugin-transform-export-namespace-from-7.24.1.tgz#f033541fc036e3efb2dcb58eedafd4f6b8078acd" - integrity sha512-Ft38m/KFOyzKw2UaJFkWG9QnHPG/Q/2SkOrRk4pNBPg5IPZ+dOxcmkK5IyuBcxiNPyyYowPGUReyBvrvZs7IlQ== +"@babel/plugin-transform-explicit-resource-management@^7.28.0": + version "7.28.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-explicit-resource-management/-/plugin-transform-explicit-resource-management-7.28.0.tgz#45be6211b778dbf4b9d54c4e8a2b42fa72e09a1a" + integrity sha512-K8nhUcn3f6iB+P3gwCv/no7OdzOZQcKchW6N389V6PD8NUWKZHzndOd9sPDVbMoBsbmjMqlB4L9fm+fEFNVlwQ== dependencies: - "@babel/helper-plugin-utils" "^7.24.0" - "@babel/plugin-syntax-export-namespace-from" "^7.8.3" + "@babel/helper-plugin-utils" "^7.27.1" + "@babel/plugin-transform-destructuring" "^7.28.0" -"@babel/plugin-transform-for-of@^7.24.1": - version "7.24.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.24.1.tgz#67448446b67ab6c091360ce3717e7d3a59e202fd" - integrity sha512-OxBdcnF04bpdQdR3i4giHZNZQn7cm8RQKcSwA17wAAqEELo1ZOwp5FFgeptWUQXFyT9kwHo10aqqauYkRZPCAg== +"@babel/plugin-transform-exponentiation-operator@^7.27.1": + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.27.1.tgz#fc497b12d8277e559747f5a3ed868dd8064f83e1" + integrity sha512-uspvXnhHvGKf2r4VVtBpeFnuDWsJLQ6MF6lGJLC89jBR1uoVeqM416AZtTuhTezOfgHicpJQmoD5YUakO/YmXQ== dependencies: - "@babel/helper-plugin-utils" "^7.24.0" - "@babel/helper-skip-transparent-expression-wrappers" "^7.22.5" + "@babel/helper-plugin-utils" "^7.27.1" -"@babel/plugin-transform-function-name@^7.24.1": - version "7.24.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.24.1.tgz#8cba6f7730626cc4dfe4ca2fa516215a0592b361" - integrity sha512-BXmDZpPlh7jwicKArQASrj8n22/w6iymRnvHYYd2zO30DbE277JO20/7yXJT3QxDPtiQiOxQBbZH4TpivNXIxA== +"@babel/plugin-transform-export-namespace-from@^7.27.1": + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-export-namespace-from/-/plugin-transform-export-namespace-from-7.27.1.tgz#71ca69d3471edd6daa711cf4dfc3400415df9c23" + integrity sha512-tQvHWSZ3/jH2xuq/vZDy0jNn+ZdXJeM8gHvX4lnJmsc3+50yPlWdZXIc5ay+umX+2/tJIqHqiEqcJvxlmIvRvQ== dependencies: - "@babel/helper-compilation-targets" "^7.23.6" - "@babel/helper-function-name" "^7.23.0" - "@babel/helper-plugin-utils" "^7.24.0" + "@babel/helper-plugin-utils" "^7.27.1" -"@babel/plugin-transform-json-strings@^7.24.1": - version "7.24.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-json-strings/-/plugin-transform-json-strings-7.24.1.tgz#08e6369b62ab3e8a7b61089151b161180c8299f7" - integrity sha512-U7RMFmRvoasscrIFy5xA4gIp8iWnWubnKkKuUGJjsuOH7GfbMkB+XZzeslx2kLdEGdOJDamEmCqOks6e8nv8DQ== +"@babel/plugin-transform-for-of@^7.27.1": + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.27.1.tgz#bc24f7080e9ff721b63a70ac7b2564ca15b6c40a" + integrity sha512-BfbWFFEJFQzLCQ5N8VocnCtA8J1CLkNTe2Ms2wocj75dd6VpiqS5Z5quTYcUoo4Yq+DN0rtikODccuv7RU81sw== dependencies: - "@babel/helper-plugin-utils" "^7.24.0" - "@babel/plugin-syntax-json-strings" "^7.8.3" + "@babel/helper-plugin-utils" "^7.27.1" + "@babel/helper-skip-transparent-expression-wrappers" "^7.27.1" -"@babel/plugin-transform-literals@^7.24.1": - version "7.24.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-literals/-/plugin-transform-literals-7.24.1.tgz#0a1982297af83e6b3c94972686067df588c5c096" - integrity sha512-zn9pwz8U7nCqOYIiBaOxoQOtYmMODXTJnkxG4AtX8fPmnCRYWBOHD0qcpwS9e2VDSp1zNJYpdnFMIKb8jmwu6g== +"@babel/plugin-transform-function-name@^7.27.1": + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.27.1.tgz#4d0bf307720e4dce6d7c30fcb1fd6ca77bdeb3a7" + integrity sha512-1bQeydJF9Nr1eBCMMbC+hdwmRlsv5XYOMu03YSWFwNs0HsAmtSxxF1fyuYPqemVldVyFmlCU7w8UE14LupUSZQ== dependencies: - "@babel/helper-plugin-utils" "^7.24.0" + "@babel/helper-compilation-targets" "^7.27.1" + "@babel/helper-plugin-utils" "^7.27.1" + "@babel/traverse" "^7.27.1" -"@babel/plugin-transform-logical-assignment-operators@^7.24.1": - version "7.24.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-logical-assignment-operators/-/plugin-transform-logical-assignment-operators-7.24.1.tgz#719d8aded1aa94b8fb34e3a785ae8518e24cfa40" - integrity sha512-OhN6J4Bpz+hIBqItTeWJujDOfNP+unqv/NJgyhlpSqgBTPm37KkMmZV6SYcOj+pnDbdcl1qRGV/ZiIjX9Iy34w== +"@babel/plugin-transform-json-strings@^7.27.1": + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-json-strings/-/plugin-transform-json-strings-7.27.1.tgz#a2e0ce6ef256376bd527f290da023983527a4f4c" + integrity sha512-6WVLVJiTjqcQauBhn1LkICsR2H+zm62I3h9faTDKt1qP4jn2o72tSvqMwtGFKGTpojce0gJs+76eZ2uCHRZh0Q== dependencies: - "@babel/helper-plugin-utils" "^7.24.0" - "@babel/plugin-syntax-logical-assignment-operators" "^7.10.4" + "@babel/helper-plugin-utils" "^7.27.1" -"@babel/plugin-transform-member-expression-literals@^7.24.1": - version "7.24.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.24.1.tgz#896d23601c92f437af8b01371ad34beb75df4489" - integrity sha512-4ojai0KysTWXzHseJKa1XPNXKRbuUrhkOPY4rEGeR+7ChlJVKxFa3H3Bz+7tWaGKgJAXUWKOGmltN+u9B3+CVg== +"@babel/plugin-transform-literals@^7.27.1": + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-literals/-/plugin-transform-literals-7.27.1.tgz#baaefa4d10a1d4206f9dcdda50d7d5827bb70b24" + integrity sha512-0HCFSepIpLTkLcsi86GG3mTUzxV5jpmbv97hTETW3yzrAij8aqlD36toB1D0daVFJM8NK6GvKO0gslVQmm+zZA== dependencies: - "@babel/helper-plugin-utils" "^7.24.0" + "@babel/helper-plugin-utils" "^7.27.1" -"@babel/plugin-transform-modules-amd@^7.24.1": - version "7.24.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.24.1.tgz#b6d829ed15258536977e9c7cc6437814871ffa39" - integrity sha512-lAxNHi4HVtjnHd5Rxg3D5t99Xm6H7b04hUS7EHIXcUl2EV4yl1gWdqZrNzXnSrHveL9qMdbODlLF55mvgjAfaQ== +"@babel/plugin-transform-logical-assignment-operators@^7.27.1": + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-logical-assignment-operators/-/plugin-transform-logical-assignment-operators-7.27.1.tgz#890cb20e0270e0e5bebe3f025b434841c32d5baa" + integrity sha512-SJvDs5dXxiae4FbSL1aBJlG4wvl594N6YEVVn9e3JGulwioy6z3oPjx/sQBO3Y4NwUu5HNix6KJ3wBZoewcdbw== dependencies: - "@babel/helper-module-transforms" "^7.23.3" - "@babel/helper-plugin-utils" "^7.24.0" + "@babel/helper-plugin-utils" "^7.27.1" -"@babel/plugin-transform-modules-commonjs@^7.24.1": - version "7.24.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.24.1.tgz#e71ba1d0d69e049a22bf90b3867e263823d3f1b9" - integrity sha512-szog8fFTUxBfw0b98gEWPaEqF42ZUD/T3bkynW/wtgx2p/XCP55WEsb+VosKceRSd6njipdZvNogqdtI4Q0chw== +"@babel/plugin-transform-member-expression-literals@^7.27.1": + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.27.1.tgz#37b88ba594d852418e99536f5612f795f23aeaf9" + integrity sha512-hqoBX4dcZ1I33jCSWcXrP+1Ku7kdqXf1oeah7ooKOIiAdKQ+uqftgCFNOSzA5AMS2XIHEYeGFg4cKRCdpxzVOQ== dependencies: - "@babel/helper-module-transforms" "^7.23.3" - "@babel/helper-plugin-utils" "^7.24.0" - "@babel/helper-simple-access" "^7.22.5" + "@babel/helper-plugin-utils" "^7.27.1" -"@babel/plugin-transform-modules-systemjs@^7.24.1": - version "7.24.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.24.1.tgz#2b9625a3d4e445babac9788daec39094e6b11e3e" - integrity sha512-mqQ3Zh9vFO1Tpmlt8QPnbwGHzNz3lpNEMxQb1kAemn/erstyqw1r9KeOlOfo3y6xAnFEcOv2tSyrXfmMk+/YZA== +"@babel/plugin-transform-modules-amd@^7.27.1": + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.27.1.tgz#a4145f9d87c2291fe2d05f994b65dba4e3e7196f" + integrity sha512-iCsytMg/N9/oFq6n+gFTvUYDZQOMK5kEdeYxmxt91fcJGycfxVP9CnrxoliM0oumFERba2i8ZtwRUCMhvP1LnA== dependencies: - "@babel/helper-hoist-variables" "^7.22.5" - "@babel/helper-module-transforms" "^7.23.3" - "@babel/helper-plugin-utils" "^7.24.0" - "@babel/helper-validator-identifier" "^7.22.20" + "@babel/helper-module-transforms" "^7.27.1" + "@babel/helper-plugin-utils" "^7.27.1" -"@babel/plugin-transform-modules-umd@^7.24.1": - version "7.24.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.24.1.tgz#69220c66653a19cf2c0872b9c762b9a48b8bebef" - integrity sha512-tuA3lpPj+5ITfcCluy6nWonSL7RvaG0AOTeAuvXqEKS34lnLzXpDb0dcP6K8jD0zWZFNDVly90AGFJPnm4fOYg== +"@babel/plugin-transform-modules-commonjs@^7.27.1": + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.27.1.tgz#8e44ed37c2787ecc23bdc367f49977476614e832" + integrity sha512-OJguuwlTYlN0gBZFRPqwOGNWssZjfIUdS7HMYtN8c1KmwpwHFBwTeFZrg9XZa+DFTitWOW5iTAG7tyCUPsCCyw== dependencies: - "@babel/helper-module-transforms" "^7.23.3" - "@babel/helper-plugin-utils" "^7.24.0" + "@babel/helper-module-transforms" "^7.27.1" + "@babel/helper-plugin-utils" "^7.27.1" -"@babel/plugin-transform-named-capturing-groups-regex@^7.22.5": - version "7.22.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.22.5.tgz#67fe18ee8ce02d57c855185e27e3dc959b2e991f" - integrity sha512-YgLLKmS3aUBhHaxp5hi1WJTgOUb/NCuDHzGT9z9WTt3YG+CPRhJs6nprbStx6DnWM4dh6gt7SU3sZodbZ08adQ== +"@babel/plugin-transform-modules-systemjs@^7.27.1": + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.27.1.tgz#00e05b61863070d0f3292a00126c16c0e024c4ed" + integrity sha512-w5N1XzsRbc0PQStASMksmUeqECuzKuTJer7kFagK8AXgpCMkeDMO5S+aaFb7A51ZYDF7XI34qsTX+fkHiIm5yA== dependencies: - "@babel/helper-create-regexp-features-plugin" "^7.22.5" - "@babel/helper-plugin-utils" "^7.22.5" + "@babel/helper-module-transforms" "^7.27.1" + "@babel/helper-plugin-utils" "^7.27.1" + "@babel/helper-validator-identifier" "^7.27.1" + "@babel/traverse" "^7.27.1" -"@babel/plugin-transform-new-target@^7.24.1": - version "7.24.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.24.1.tgz#29c59988fa3d0157de1c871a28cd83096363cc34" - integrity sha512-/rurytBM34hYy0HKZQyA0nHbQgQNFm4Q/BOc9Hflxi2X3twRof7NaE5W46j4kQitm7SvACVRXsa6N/tSZxvPug== +"@babel/plugin-transform-modules-umd@^7.27.1": + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.27.1.tgz#63f2cf4f6dc15debc12f694e44714863d34cd334" + integrity sha512-iQBE/xC5BV1OxJbp6WG7jq9IWiD+xxlZhLrdwpPkTX3ydmXdvoCpyfJN7acaIBZaOqTfr76pgzqBJflNbeRK+w== dependencies: - "@babel/helper-plugin-utils" "^7.24.0" + "@babel/helper-module-transforms" "^7.27.1" + "@babel/helper-plugin-utils" "^7.27.1" -"@babel/plugin-transform-nullish-coalescing-operator@^7.24.1": - version "7.24.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-nullish-coalescing-operator/-/plugin-transform-nullish-coalescing-operator-7.24.1.tgz#0cd494bb97cb07d428bd651632cb9d4140513988" - integrity sha512-iQ+caew8wRrhCikO5DrUYx0mrmdhkaELgFa+7baMcVuhxIkN7oxt06CZ51D65ugIb1UWRQ8oQe+HXAVM6qHFjw== +"@babel/plugin-transform-named-capturing-groups-regex@^7.27.1": + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.27.1.tgz#f32b8f7818d8fc0cc46ee20a8ef75f071af976e1" + integrity sha512-SstR5JYy8ddZvD6MhV0tM/j16Qds4mIpJTOd1Yu9J9pJjH93bxHECF7pgtc28XvkzTD6Pxcm/0Z73Hvk7kb3Ng== dependencies: - "@babel/helper-plugin-utils" "^7.24.0" - "@babel/plugin-syntax-nullish-coalescing-operator" "^7.8.3" + "@babel/helper-create-regexp-features-plugin" "^7.27.1" + "@babel/helper-plugin-utils" "^7.27.1" -"@babel/plugin-transform-numeric-separator@^7.24.1": - version "7.24.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-numeric-separator/-/plugin-transform-numeric-separator-7.24.1.tgz#5bc019ce5b3435c1cadf37215e55e433d674d4e8" - integrity sha512-7GAsGlK4cNL2OExJH1DzmDeKnRv/LXq0eLUSvudrehVA5Rgg4bIrqEUW29FbKMBRT0ztSqisv7kjP+XIC4ZMNw== +"@babel/plugin-transform-new-target@^7.27.1": + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.27.1.tgz#259c43939728cad1706ac17351b7e6a7bea1abeb" + integrity sha512-f6PiYeqXQ05lYq3TIfIDu/MtliKUbNwkGApPUvyo6+tc7uaR4cPjPe7DFPr15Uyycg2lZU6btZ575CuQoYh7MQ== dependencies: - "@babel/helper-plugin-utils" "^7.24.0" - "@babel/plugin-syntax-numeric-separator" "^7.10.4" + "@babel/helper-plugin-utils" "^7.27.1" -"@babel/plugin-transform-object-rest-spread@^7.24.1": - version "7.24.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-object-rest-spread/-/plugin-transform-object-rest-spread-7.24.1.tgz#5a3ce73caf0e7871a02e1c31e8b473093af241ff" - integrity sha512-XjD5f0YqOtebto4HGISLNfiNMTTs6tbkFf2TOqJlYKYmbo+mN9Dnpl4SRoofiziuOWMIyq3sZEUqLo3hLITFEA== +"@babel/plugin-transform-nullish-coalescing-operator@^7.27.1": + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-nullish-coalescing-operator/-/plugin-transform-nullish-coalescing-operator-7.27.1.tgz#4f9d3153bf6782d73dd42785a9d22d03197bc91d" + integrity sha512-aGZh6xMo6q9vq1JGcw58lZ1Z0+i0xB2x0XaauNIUXd6O1xXc3RwoWEBlsTQrY4KQ9Jf0s5rgD6SiNkaUdJegTA== dependencies: - "@babel/helper-compilation-targets" "^7.23.6" - "@babel/helper-plugin-utils" "^7.24.0" - "@babel/plugin-syntax-object-rest-spread" "^7.8.3" - "@babel/plugin-transform-parameters" "^7.24.1" + "@babel/helper-plugin-utils" "^7.27.1" -"@babel/plugin-transform-object-super@^7.24.1": - version "7.24.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.24.1.tgz#e71d6ab13483cca89ed95a474f542bbfc20a0520" - integrity sha512-oKJqR3TeI5hSLRxudMjFQ9re9fBVUU0GICqM3J1mi8MqlhVr6hC/ZN4ttAyMuQR6EZZIY6h/exe5swqGNNIkWQ== +"@babel/plugin-transform-numeric-separator@^7.27.1": + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-numeric-separator/-/plugin-transform-numeric-separator-7.27.1.tgz#614e0b15cc800e5997dadd9bd6ea524ed6c819c6" + integrity sha512-fdPKAcujuvEChxDBJ5c+0BTaS6revLV7CJL08e4m3de8qJfNIuCc2nc7XJYOjBoTMJeqSmwXJ0ypE14RCjLwaw== dependencies: - "@babel/helper-plugin-utils" "^7.24.0" - "@babel/helper-replace-supers" "^7.24.1" + "@babel/helper-plugin-utils" "^7.27.1" -"@babel/plugin-transform-optional-catch-binding@^7.24.1": - version "7.24.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-optional-catch-binding/-/plugin-transform-optional-catch-binding-7.24.1.tgz#92a3d0efe847ba722f1a4508669b23134669e2da" - integrity sha512-oBTH7oURV4Y+3EUrf6cWn1OHio3qG/PVwO5J03iSJmBg6m2EhKjkAu/xuaXaYwWW9miYtvbWv4LNf0AmR43LUA== +"@babel/plugin-transform-object-rest-spread@^7.28.0": + version "7.28.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-object-rest-spread/-/plugin-transform-object-rest-spread-7.28.0.tgz#d23021857ffd7cd809f54d624299b8086402ed8d" + integrity sha512-9VNGikXxzu5eCiQjdE4IZn8sb9q7Xsk5EXLDBKUYg1e/Tve8/05+KJEtcxGxAgCY5t/BpKQM+JEL/yT4tvgiUA== dependencies: - "@babel/helper-plugin-utils" "^7.24.0" - "@babel/plugin-syntax-optional-catch-binding" "^7.8.3" + "@babel/helper-compilation-targets" "^7.27.2" + "@babel/helper-plugin-utils" "^7.27.1" + "@babel/plugin-transform-destructuring" "^7.28.0" + "@babel/plugin-transform-parameters" "^7.27.7" + "@babel/traverse" "^7.28.0" -"@babel/plugin-transform-optional-chaining@^7.24.1": - version "7.24.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-optional-chaining/-/plugin-transform-optional-chaining-7.24.1.tgz#26e588acbedce1ab3519ac40cc748e380c5291e6" - integrity sha512-n03wmDt+987qXwAgcBlnUUivrZBPZ8z1plL0YvgQalLm+ZE5BMhGm94jhxXtA1wzv1Cu2aaOv1BM9vbVttrzSg== +"@babel/plugin-transform-object-super@^7.27.1": + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.27.1.tgz#1c932cd27bf3874c43a5cac4f43ebf970c9871b5" + integrity sha512-SFy8S9plRPbIcxlJ8A6mT/CxFdJx/c04JEctz4jf8YZaVS2px34j7NXRrlGlHkN/M2gnpL37ZpGRGVFLd3l8Ng== dependencies: - "@babel/helper-plugin-utils" "^7.24.0" - "@babel/helper-skip-transparent-expression-wrappers" "^7.22.5" - "@babel/plugin-syntax-optional-chaining" "^7.8.3" + "@babel/helper-plugin-utils" "^7.27.1" + "@babel/helper-replace-supers" "^7.27.1" -"@babel/plugin-transform-parameters@^7.24.1": - version "7.24.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.24.1.tgz#983c15d114da190506c75b616ceb0f817afcc510" - integrity sha512-8Jl6V24g+Uw5OGPeWNKrKqXPDw2YDjLc53ojwfMcKwlEoETKU9rU0mHUtcg9JntWI/QYzGAXNWEcVHZ+fR+XXg== +"@babel/plugin-transform-optional-catch-binding@^7.27.1": + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-optional-catch-binding/-/plugin-transform-optional-catch-binding-7.27.1.tgz#84c7341ebde35ccd36b137e9e45866825072a30c" + integrity sha512-txEAEKzYrHEX4xSZN4kJ+OfKXFVSWKB2ZxM9dpcE3wT7smwkNmXo5ORRlVzMVdJbD+Q8ILTgSD7959uj+3Dm3Q== dependencies: - "@babel/helper-plugin-utils" "^7.24.0" + "@babel/helper-plugin-utils" "^7.27.1" -"@babel/plugin-transform-private-methods@^7.24.1": - version "7.24.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-private-methods/-/plugin-transform-private-methods-7.24.1.tgz#a0faa1ae87eff077e1e47a5ec81c3aef383dc15a" - integrity sha512-tGvisebwBO5em4PaYNqt4fkw56K2VALsAbAakY0FjTYqJp7gfdrgr7YX76Or8/cpik0W6+tj3rZ0uHU9Oil4tw== +"@babel/plugin-transform-optional-chaining@^7.27.1": + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-optional-chaining/-/plugin-transform-optional-chaining-7.27.1.tgz#874ce3c4f06b7780592e946026eb76a32830454f" + integrity sha512-BQmKPPIuc8EkZgNKsv0X4bPmOoayeu4F1YCwx2/CfmDSXDbp7GnzlUH+/ul5VGfRg1AoFPsrIThlEBj2xb4CAg== dependencies: - "@babel/helper-create-class-features-plugin" "^7.24.1" - "@babel/helper-plugin-utils" "^7.24.0" + "@babel/helper-plugin-utils" "^7.27.1" + "@babel/helper-skip-transparent-expression-wrappers" "^7.27.1" -"@babel/plugin-transform-private-property-in-object@^7.24.1": - version "7.24.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-private-property-in-object/-/plugin-transform-private-property-in-object-7.24.1.tgz#756443d400274f8fb7896742962cc1b9f25c1f6a" - integrity sha512-pTHxDVa0BpUbvAgX3Gat+7cSciXqUcY9j2VZKTbSB6+VQGpNgNO9ailxTGHSXlqOnX1Hcx1Enme2+yv7VqP9bg== +"@babel/plugin-transform-parameters@^7.27.7": + version "7.27.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.27.7.tgz#1fd2febb7c74e7d21cf3b05f7aebc907940af53a" + integrity sha512-qBkYTYCb76RRxUM6CcZA5KRu8K4SM8ajzVeUgVdMVO9NN9uI/GaVmBg/WKJJGnNokV9SY8FxNOVWGXzqzUidBg== dependencies: - "@babel/helper-annotate-as-pure" "^7.22.5" - "@babel/helper-create-class-features-plugin" "^7.24.1" - "@babel/helper-plugin-utils" "^7.24.0" - "@babel/plugin-syntax-private-property-in-object" "^7.14.5" + "@babel/helper-plugin-utils" "^7.27.1" -"@babel/plugin-transform-property-literals@^7.24.1": - version "7.24.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.24.1.tgz#d6a9aeab96f03749f4eebeb0b6ea8e90ec958825" - integrity sha512-LetvD7CrHmEx0G442gOomRr66d7q8HzzGGr4PMHGr+5YIm6++Yke+jxj246rpvsbyhJwCLxcTn6zW1P1BSenqA== +"@babel/plugin-transform-private-methods@^7.27.1": + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-private-methods/-/plugin-transform-private-methods-7.27.1.tgz#fdacbab1c5ed81ec70dfdbb8b213d65da148b6af" + integrity sha512-10FVt+X55AjRAYI9BrdISN9/AQWHqldOeZDUoLyif1Kn05a56xVBXb8ZouL8pZ9jem8QpXaOt8TS7RHUIS+GPA== dependencies: - "@babel/helper-plugin-utils" "^7.24.0" + "@babel/helper-create-class-features-plugin" "^7.27.1" + "@babel/helper-plugin-utils" "^7.27.1" + +"@babel/plugin-transform-private-property-in-object@^7.27.1": + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-private-property-in-object/-/plugin-transform-private-property-in-object-7.27.1.tgz#4dbbef283b5b2f01a21e81e299f76e35f900fb11" + integrity sha512-5J+IhqTi1XPa0DXF83jYOaARrX+41gOewWbkPyjMNRDqgOCqdffGh8L3f/Ek5utaEBZExjSAzcyjmV9SSAWObQ== + dependencies: + "@babel/helper-annotate-as-pure" "^7.27.1" + "@babel/helper-create-class-features-plugin" "^7.27.1" + "@babel/helper-plugin-utils" "^7.27.1" + +"@babel/plugin-transform-property-literals@^7.27.1": + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.27.1.tgz#07eafd618800591e88073a0af1b940d9a42c6424" + integrity sha512-oThy3BCuCha8kDZ8ZkgOg2exvPYUlprMukKQXI1r1pJ47NCvxfkEy8vK+r/hT9nF0Aa4H1WUPZZjHTFtAhGfmQ== + dependencies: + "@babel/helper-plugin-utils" "^7.27.1" "@babel/plugin-transform-react-jsx-development@^7.22.5": - version "7.22.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx-development/-/plugin-transform-react-jsx-development-7.22.5.tgz#e716b6edbef972a92165cd69d92f1255f7e73e87" - integrity sha512-bDhuzwWMuInwCYeDeMzyi7TaBgRQei6DqxhbyniL7/VG4RSS7HtSL2QbY4eESy1KJqlWt8g3xeEBGPuo+XqC8A== + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx-development/-/plugin-transform-react-jsx-development-7.27.1.tgz#47ff95940e20a3a70e68ad3d4fcb657b647f6c98" + integrity sha512-ykDdF5yI4f1WrAolLqeF3hmYU12j9ntLQl/AOG1HAS21jxyg1Q0/J/tpREuYLfatGdGmXp/3yS0ZA76kOlVq9Q== dependencies: - "@babel/plugin-transform-react-jsx" "^7.22.5" + "@babel/plugin-transform-react-jsx" "^7.27.1" -"@babel/plugin-transform-react-jsx@^7.22.15", "@babel/plugin-transform-react-jsx@^7.22.5": - version "7.23.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.23.4.tgz#393f99185110cea87184ea47bcb4a7b0c2e39312" - integrity sha512-5xOpoPguCZCRbo/JeHlloSkTA8Bld1J/E1/kLfD1nsuiW1m8tduTA1ERCgIZokDflX/IBzKcqR3l7VlRgiIfHA== +"@babel/plugin-transform-react-jsx@^7.22.15", "@babel/plugin-transform-react-jsx@^7.27.1": + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.27.1.tgz#1023bc94b78b0a2d68c82b5e96aed573bcfb9db0" + integrity sha512-2KH4LWGSrJIkVf5tSiBFYuXDAoWRq2MMwgivCf+93dd0GQi8RXLjKA/0EvRnVV5G0hrHczsquXuD01L8s6dmBw== dependencies: - "@babel/helper-annotate-as-pure" "^7.22.5" - "@babel/helper-module-imports" "^7.22.15" - "@babel/helper-plugin-utils" "^7.22.5" - "@babel/plugin-syntax-jsx" "^7.23.3" - "@babel/types" "^7.23.4" + "@babel/helper-annotate-as-pure" "^7.27.1" + "@babel/helper-module-imports" "^7.27.1" + "@babel/helper-plugin-utils" "^7.27.1" + "@babel/plugin-syntax-jsx" "^7.27.1" + "@babel/types" "^7.27.1" -"@babel/plugin-transform-regenerator@^7.24.1": - version "7.24.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.24.1.tgz#625b7545bae52363bdc1fbbdc7252b5046409c8c" - integrity sha512-sJwZBCzIBE4t+5Q4IGLaaun5ExVMRY0lYwos/jNecjMrVCygCdph3IKv0tkP5Fc87e/1+bebAmEAGBfnRD+cnw== +"@babel/plugin-transform-regenerator@^7.28.0": + version "7.28.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.28.1.tgz#bde80603442ff4bb4e910bc8b35485295d556ab1" + integrity sha512-P0QiV/taaa3kXpLY+sXla5zec4E+4t4Aqc9ggHlfZ7a2cp8/x/Gv08jfwEtn9gnnYIMvHx6aoOZ8XJL8eU71Dg== dependencies: - "@babel/helper-plugin-utils" "^7.24.0" - regenerator-transform "^0.15.2" + "@babel/helper-plugin-utils" "^7.27.1" -"@babel/plugin-transform-reserved-words@^7.24.1": - version "7.24.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.24.1.tgz#8de729f5ecbaaf5cf83b67de13bad38a21be57c1" - integrity sha512-JAclqStUfIwKN15HrsQADFgeZt+wexNQ0uLhuqvqAUFoqPMjEcFCYZBhq0LUdz6dZK/mD+rErhW71fbx8RYElg== +"@babel/plugin-transform-regexp-modifiers@^7.27.1": + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-regexp-modifiers/-/plugin-transform-regexp-modifiers-7.27.1.tgz#df9ba5577c974e3f1449888b70b76169998a6d09" + integrity sha512-TtEciroaiODtXvLZv4rmfMhkCv8jx3wgKpL68PuiPh2M4fvz5jhsA7697N1gMvkvr/JTF13DrFYyEbY9U7cVPA== dependencies: - "@babel/helper-plugin-utils" "^7.24.0" + "@babel/helper-create-regexp-features-plugin" "^7.27.1" + "@babel/helper-plugin-utils" "^7.27.1" -"@babel/plugin-transform-shorthand-properties@^7.24.1": - version "7.24.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.24.1.tgz#ba9a09144cf55d35ec6b93a32253becad8ee5b55" - integrity sha512-LyjVB1nsJ6gTTUKRjRWx9C1s9hE7dLfP/knKdrfeH9UPtAGjYGgxIbFfx7xyLIEWs7Xe1Gnf8EWiUqfjLhInZA== +"@babel/plugin-transform-reserved-words@^7.27.1": + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.27.1.tgz#40fba4878ccbd1c56605a4479a3a891ac0274bb4" + integrity sha512-V2ABPHIJX4kC7HegLkYoDpfg9PVmuWy/i6vUM5eGK22bx4YVFD3M5F0QQnWQoDs6AGsUWTVOopBiMFQgHaSkVw== dependencies: - "@babel/helper-plugin-utils" "^7.24.0" + "@babel/helper-plugin-utils" "^7.27.1" -"@babel/plugin-transform-spread@^7.24.1": - version "7.24.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-spread/-/plugin-transform-spread-7.24.1.tgz#a1acf9152cbf690e4da0ba10790b3ac7d2b2b391" - integrity sha512-KjmcIM+fxgY+KxPVbjelJC6hrH1CgtPmTvdXAfn3/a9CnWGSTY7nH4zm5+cjmWJybdcPSsD0++QssDsjcpe47g== +"@babel/plugin-transform-shorthand-properties@^7.27.1": + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.27.1.tgz#532abdacdec87bfee1e0ef8e2fcdee543fe32b90" + integrity sha512-N/wH1vcn4oYawbJ13Y/FxcQrWk63jhfNa7jef0ih7PHSIHX2LB7GWE1rkPrOnka9kwMxb6hMl19p7lidA+EHmQ== dependencies: - "@babel/helper-plugin-utils" "^7.24.0" - "@babel/helper-skip-transparent-expression-wrappers" "^7.22.5" + "@babel/helper-plugin-utils" "^7.27.1" -"@babel/plugin-transform-sticky-regex@^7.24.1": - version "7.24.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.24.1.tgz#f03e672912c6e203ed8d6e0271d9c2113dc031b9" - integrity sha512-9v0f1bRXgPVcPrngOQvLXeGNNVLc8UjMVfebo9ka0WF3/7+aVUHmaJVT3sa0XCzEFioPfPHZiOcYG9qOsH63cw== +"@babel/plugin-transform-spread@^7.27.1": + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-spread/-/plugin-transform-spread-7.27.1.tgz#1a264d5fc12750918f50e3fe3e24e437178abb08" + integrity sha512-kpb3HUqaILBJcRFVhFUs6Trdd4mkrzcGXss+6/mxUd273PfbWqSDHRzMT2234gIg2QYfAjvXLSquP1xECSg09Q== dependencies: - "@babel/helper-plugin-utils" "^7.24.0" + "@babel/helper-plugin-utils" "^7.27.1" + "@babel/helper-skip-transparent-expression-wrappers" "^7.27.1" -"@babel/plugin-transform-template-literals@^7.24.1": - version "7.24.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.24.1.tgz#15e2166873a30d8617e3e2ccadb86643d327aab7" - integrity sha512-WRkhROsNzriarqECASCNu/nojeXCDTE/F2HmRgOzi7NGvyfYGq1NEjKBK3ckLfRgGc6/lPAqP0vDOSw3YtG34g== +"@babel/plugin-transform-sticky-regex@^7.27.1": + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.27.1.tgz#18984935d9d2296843a491d78a014939f7dcd280" + integrity sha512-lhInBO5bi/Kowe2/aLdBAawijx+q1pQzicSgnkB6dUPc1+RC8QmJHKf2OjvU+NZWitguJHEaEmbV6VWEouT58g== dependencies: - "@babel/helper-plugin-utils" "^7.24.0" + "@babel/helper-plugin-utils" "^7.27.1" -"@babel/plugin-transform-typeof-symbol@^7.24.1": - version "7.24.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.24.1.tgz#6831f78647080dec044f7e9f68003d99424f94c7" - integrity sha512-CBfU4l/A+KruSUoW+vTQthwcAdwuqbpRNB8HQKlZABwHRhsdHZ9fezp4Sn18PeAlYxTNiLMlx4xUBV3AWfg1BA== +"@babel/plugin-transform-template-literals@^7.27.1": + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.27.1.tgz#1a0eb35d8bb3e6efc06c9fd40eb0bcef548328b8" + integrity sha512-fBJKiV7F2DxZUkg5EtHKXQdbsbURW3DZKQUWphDum0uRP6eHGGa/He9mc0mypL680pb+e/lDIthRohlv8NCHkg== dependencies: - "@babel/helper-plugin-utils" "^7.24.0" + "@babel/helper-plugin-utils" "^7.27.1" -"@babel/plugin-transform-unicode-escapes@^7.24.1": - version "7.24.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.24.1.tgz#fb3fa16676549ac7c7449db9b342614985c2a3a4" - integrity sha512-RlkVIcWT4TLI96zM660S877E7beKlQw7Ig+wqkKBiWfj0zH5Q4h50q6er4wzZKRNSYpfo6ILJ+hrJAGSX2qcNw== +"@babel/plugin-transform-typeof-symbol@^7.27.1": + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.27.1.tgz#70e966bb492e03509cf37eafa6dcc3051f844369" + integrity sha512-RiSILC+nRJM7FY5srIyc4/fGIwUhyDuuBSdWn4y6yT6gm652DpCHZjIipgn6B7MQ1ITOUnAKWixEUjQRIBIcLw== dependencies: - "@babel/helper-plugin-utils" "^7.24.0" + "@babel/helper-plugin-utils" "^7.27.1" -"@babel/plugin-transform-unicode-property-regex@^7.24.1": - version "7.24.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-property-regex/-/plugin-transform-unicode-property-regex-7.24.1.tgz#56704fd4d99da81e5e9f0c0c93cabd91dbc4889e" - integrity sha512-Ss4VvlfYV5huWApFsF8/Sq0oXnGO+jB+rijFEFugTd3cwSObUSnUi88djgR5528Csl0uKlrI331kRqe56Ov2Ng== +"@babel/plugin-transform-unicode-escapes@^7.27.1": + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.27.1.tgz#3e3143f8438aef842de28816ece58780190cf806" + integrity sha512-Ysg4v6AmF26k9vpfFuTZg8HRfVWzsh1kVfowA23y9j/Gu6dOuahdUVhkLqpObp3JIv27MLSii6noRnuKN8H0Mg== dependencies: - "@babel/helper-create-regexp-features-plugin" "^7.22.15" - "@babel/helper-plugin-utils" "^7.24.0" + "@babel/helper-plugin-utils" "^7.27.1" -"@babel/plugin-transform-unicode-regex@^7.24.1": - version "7.24.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.24.1.tgz#57c3c191d68f998ac46b708380c1ce4d13536385" - integrity sha512-2A/94wgZgxfTsiLaQ2E36XAOdcZmGAaEEgVmxQWwZXWkGhvoHbaqXcKnU8zny4ycpu3vNqg0L/PcCiYtHtA13g== +"@babel/plugin-transform-unicode-property-regex@^7.27.1": + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-property-regex/-/plugin-transform-unicode-property-regex-7.27.1.tgz#bdfe2d3170c78c5691a3c3be934c8c0087525956" + integrity sha512-uW20S39PnaTImxp39O5qFlHLS9LJEmANjMG7SxIhap8rCHqu0Ik+tLEPX5DKmHn6CsWQ7j3lix2tFOa5YtL12Q== dependencies: - "@babel/helper-create-regexp-features-plugin" "^7.22.15" - "@babel/helper-plugin-utils" "^7.24.0" + "@babel/helper-create-regexp-features-plugin" "^7.27.1" + "@babel/helper-plugin-utils" "^7.27.1" -"@babel/plugin-transform-unicode-sets-regex@^7.24.1": - version "7.24.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-sets-regex/-/plugin-transform-unicode-sets-regex-7.24.1.tgz#c1ea175b02afcffc9cf57a9c4658326625165b7f" - integrity sha512-fqj4WuzzS+ukpgerpAoOnMfQXwUHFxXUZUE84oL2Kao2N8uSlvcpnAidKASgsNgzZHBsHWvcm8s9FPWUhAb8fA== +"@babel/plugin-transform-unicode-regex@^7.27.1": + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.27.1.tgz#25948f5c395db15f609028e370667ed8bae9af97" + integrity sha512-xvINq24TRojDuyt6JGtHmkVkrfVV3FPT16uytxImLeBZqW3/H52yN+kM1MGuyPkIQxrzKwPHs5U/MP3qKyzkGw== dependencies: - "@babel/helper-create-regexp-features-plugin" "^7.22.15" - "@babel/helper-plugin-utils" "^7.24.0" + "@babel/helper-create-regexp-features-plugin" "^7.27.1" + "@babel/helper-plugin-utils" "^7.27.1" -"@babel/preset-env@^7.23.9": - version "7.24.4" - resolved "https://registry.yarnpkg.com/@babel/preset-env/-/preset-env-7.24.4.tgz#46dbbcd608771373b88f956ffb67d471dce0d23b" - integrity sha512-7Kl6cSmYkak0FK/FXjSEnLJ1N9T/WA2RkMhu17gZ/dsxKJUuTYNIylahPTzqpLyJN4WhDif8X0XK1R8Wsguo/A== +"@babel/plugin-transform-unicode-sets-regex@^7.27.1": + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-sets-regex/-/plugin-transform-unicode-sets-regex-7.27.1.tgz#6ab706d10f801b5c72da8bb2548561fa04193cd1" + integrity sha512-EtkOujbc4cgvb0mlpQefi4NTPBzhSIevblFevACNLUspmrALgmEBdL/XfnyyITfd8fKBZrZys92zOWcik7j9Tw== dependencies: - "@babel/compat-data" "^7.24.4" - "@babel/helper-compilation-targets" "^7.23.6" - "@babel/helper-plugin-utils" "^7.24.0" - "@babel/helper-validator-option" "^7.23.5" - "@babel/plugin-bugfix-firefox-class-in-computed-class-key" "^7.24.4" - "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression" "^7.24.1" - "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining" "^7.24.1" - "@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly" "^7.24.1" + "@babel/helper-create-regexp-features-plugin" "^7.27.1" + "@babel/helper-plugin-utils" "^7.27.1" + +"@babel/preset-env@^7.27.2": + version "7.28.0" + resolved "https://registry.yarnpkg.com/@babel/preset-env/-/preset-env-7.28.0.tgz#d23a6bc17b43227d11db77081a0779c706b5569c" + integrity sha512-VmaxeGOwuDqzLl5JUkIRM1X2Qu2uKGxHEQWh+cvvbl7JuJRgKGJSfsEF/bUaxFhJl/XAyxBe7q7qSuTbKFuCyg== + dependencies: + "@babel/compat-data" "^7.28.0" + "@babel/helper-compilation-targets" "^7.27.2" + "@babel/helper-plugin-utils" "^7.27.1" + "@babel/helper-validator-option" "^7.27.1" + "@babel/plugin-bugfix-firefox-class-in-computed-class-key" "^7.27.1" + "@babel/plugin-bugfix-safari-class-field-initializer-scope" "^7.27.1" + "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression" "^7.27.1" + "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining" "^7.27.1" + "@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly" "^7.27.1" "@babel/plugin-proposal-private-property-in-object" "7.21.0-placeholder-for-preset-env.2" - "@babel/plugin-syntax-async-generators" "^7.8.4" - "@babel/plugin-syntax-class-properties" "^7.12.13" - "@babel/plugin-syntax-class-static-block" "^7.14.5" - "@babel/plugin-syntax-dynamic-import" "^7.8.3" - "@babel/plugin-syntax-export-namespace-from" "^7.8.3" - "@babel/plugin-syntax-import-assertions" "^7.24.1" - "@babel/plugin-syntax-import-attributes" "^7.24.1" - "@babel/plugin-syntax-import-meta" "^7.10.4" - "@babel/plugin-syntax-json-strings" "^7.8.3" - "@babel/plugin-syntax-logical-assignment-operators" "^7.10.4" - "@babel/plugin-syntax-nullish-coalescing-operator" "^7.8.3" - "@babel/plugin-syntax-numeric-separator" "^7.10.4" - "@babel/plugin-syntax-object-rest-spread" "^7.8.3" - "@babel/plugin-syntax-optional-catch-binding" "^7.8.3" - "@babel/plugin-syntax-optional-chaining" "^7.8.3" - "@babel/plugin-syntax-private-property-in-object" "^7.14.5" - "@babel/plugin-syntax-top-level-await" "^7.14.5" + "@babel/plugin-syntax-import-assertions" "^7.27.1" + "@babel/plugin-syntax-import-attributes" "^7.27.1" "@babel/plugin-syntax-unicode-sets-regex" "^7.18.6" - "@babel/plugin-transform-arrow-functions" "^7.24.1" - "@babel/plugin-transform-async-generator-functions" "^7.24.3" - "@babel/plugin-transform-async-to-generator" "^7.24.1" - "@babel/plugin-transform-block-scoped-functions" "^7.24.1" - "@babel/plugin-transform-block-scoping" "^7.24.4" - "@babel/plugin-transform-class-properties" "^7.24.1" - "@babel/plugin-transform-class-static-block" "^7.24.4" - "@babel/plugin-transform-classes" "^7.24.1" - "@babel/plugin-transform-computed-properties" "^7.24.1" - "@babel/plugin-transform-destructuring" "^7.24.1" - "@babel/plugin-transform-dotall-regex" "^7.24.1" - "@babel/plugin-transform-duplicate-keys" "^7.24.1" - "@babel/plugin-transform-dynamic-import" "^7.24.1" - "@babel/plugin-transform-exponentiation-operator" "^7.24.1" - "@babel/plugin-transform-export-namespace-from" "^7.24.1" - "@babel/plugin-transform-for-of" "^7.24.1" - "@babel/plugin-transform-function-name" "^7.24.1" - "@babel/plugin-transform-json-strings" "^7.24.1" - "@babel/plugin-transform-literals" "^7.24.1" - "@babel/plugin-transform-logical-assignment-operators" "^7.24.1" - "@babel/plugin-transform-member-expression-literals" "^7.24.1" - "@babel/plugin-transform-modules-amd" "^7.24.1" - "@babel/plugin-transform-modules-commonjs" "^7.24.1" - "@babel/plugin-transform-modules-systemjs" "^7.24.1" - "@babel/plugin-transform-modules-umd" "^7.24.1" - "@babel/plugin-transform-named-capturing-groups-regex" "^7.22.5" - "@babel/plugin-transform-new-target" "^7.24.1" - "@babel/plugin-transform-nullish-coalescing-operator" "^7.24.1" - "@babel/plugin-transform-numeric-separator" "^7.24.1" - "@babel/plugin-transform-object-rest-spread" "^7.24.1" - "@babel/plugin-transform-object-super" "^7.24.1" - "@babel/plugin-transform-optional-catch-binding" "^7.24.1" - "@babel/plugin-transform-optional-chaining" "^7.24.1" - "@babel/plugin-transform-parameters" "^7.24.1" - "@babel/plugin-transform-private-methods" "^7.24.1" - "@babel/plugin-transform-private-property-in-object" "^7.24.1" - "@babel/plugin-transform-property-literals" "^7.24.1" - "@babel/plugin-transform-regenerator" "^7.24.1" - "@babel/plugin-transform-reserved-words" "^7.24.1" - "@babel/plugin-transform-shorthand-properties" "^7.24.1" - "@babel/plugin-transform-spread" "^7.24.1" - "@babel/plugin-transform-sticky-regex" "^7.24.1" - "@babel/plugin-transform-template-literals" "^7.24.1" - "@babel/plugin-transform-typeof-symbol" "^7.24.1" - "@babel/plugin-transform-unicode-escapes" "^7.24.1" - "@babel/plugin-transform-unicode-property-regex" "^7.24.1" - "@babel/plugin-transform-unicode-regex" "^7.24.1" - "@babel/plugin-transform-unicode-sets-regex" "^7.24.1" + "@babel/plugin-transform-arrow-functions" "^7.27.1" + "@babel/plugin-transform-async-generator-functions" "^7.28.0" + "@babel/plugin-transform-async-to-generator" "^7.27.1" + "@babel/plugin-transform-block-scoped-functions" "^7.27.1" + "@babel/plugin-transform-block-scoping" "^7.28.0" + "@babel/plugin-transform-class-properties" "^7.27.1" + "@babel/plugin-transform-class-static-block" "^7.27.1" + "@babel/plugin-transform-classes" "^7.28.0" + "@babel/plugin-transform-computed-properties" "^7.27.1" + "@babel/plugin-transform-destructuring" "^7.28.0" + "@babel/plugin-transform-dotall-regex" "^7.27.1" + "@babel/plugin-transform-duplicate-keys" "^7.27.1" + "@babel/plugin-transform-duplicate-named-capturing-groups-regex" "^7.27.1" + "@babel/plugin-transform-dynamic-import" "^7.27.1" + "@babel/plugin-transform-explicit-resource-management" "^7.28.0" + "@babel/plugin-transform-exponentiation-operator" "^7.27.1" + "@babel/plugin-transform-export-namespace-from" "^7.27.1" + "@babel/plugin-transform-for-of" "^7.27.1" + "@babel/plugin-transform-function-name" "^7.27.1" + "@babel/plugin-transform-json-strings" "^7.27.1" + "@babel/plugin-transform-literals" "^7.27.1" + "@babel/plugin-transform-logical-assignment-operators" "^7.27.1" + "@babel/plugin-transform-member-expression-literals" "^7.27.1" + "@babel/plugin-transform-modules-amd" "^7.27.1" + "@babel/plugin-transform-modules-commonjs" "^7.27.1" + "@babel/plugin-transform-modules-systemjs" "^7.27.1" + "@babel/plugin-transform-modules-umd" "^7.27.1" + "@babel/plugin-transform-named-capturing-groups-regex" "^7.27.1" + "@babel/plugin-transform-new-target" "^7.27.1" + "@babel/plugin-transform-nullish-coalescing-operator" "^7.27.1" + "@babel/plugin-transform-numeric-separator" "^7.27.1" + "@babel/plugin-transform-object-rest-spread" "^7.28.0" + "@babel/plugin-transform-object-super" "^7.27.1" + "@babel/plugin-transform-optional-catch-binding" "^7.27.1" + "@babel/plugin-transform-optional-chaining" "^7.27.1" + "@babel/plugin-transform-parameters" "^7.27.7" + "@babel/plugin-transform-private-methods" "^7.27.1" + "@babel/plugin-transform-private-property-in-object" "^7.27.1" + "@babel/plugin-transform-property-literals" "^7.27.1" + "@babel/plugin-transform-regenerator" "^7.28.0" + "@babel/plugin-transform-regexp-modifiers" "^7.27.1" + "@babel/plugin-transform-reserved-words" "^7.27.1" + "@babel/plugin-transform-shorthand-properties" "^7.27.1" + "@babel/plugin-transform-spread" "^7.27.1" + "@babel/plugin-transform-sticky-regex" "^7.27.1" + "@babel/plugin-transform-template-literals" "^7.27.1" + "@babel/plugin-transform-typeof-symbol" "^7.27.1" + "@babel/plugin-transform-unicode-escapes" "^7.27.1" + "@babel/plugin-transform-unicode-property-regex" "^7.27.1" + "@babel/plugin-transform-unicode-regex" "^7.27.1" + "@babel/plugin-transform-unicode-sets-regex" "^7.27.1" "@babel/preset-modules" "0.1.6-no-external-plugins" - babel-plugin-polyfill-corejs2 "^0.4.10" - babel-plugin-polyfill-corejs3 "^0.10.4" - babel-plugin-polyfill-regenerator "^0.6.1" - core-js-compat "^3.31.0" + babel-plugin-polyfill-corejs2 "^0.4.14" + babel-plugin-polyfill-corejs3 "^0.13.0" + babel-plugin-polyfill-regenerator "^0.6.5" + core-js-compat "^3.43.0" semver "^6.3.1" "@babel/preset-modules@0.1.6-no-external-plugins": @@ -1003,166 +901,165 @@ "@babel/types" "^7.4.4" esutils "^2.0.2" -"@babel/regjsgen@^0.8.0": - version "0.8.0" - resolved "https://registry.yarnpkg.com/@babel/regjsgen/-/regjsgen-0.8.0.tgz#f0ba69b075e1f05fb2825b7fad991e7adbb18310" - integrity sha512-x/rqGMdzj+fWZvCOYForTghzbtqPDZ5gPwaoNGHdgDfF2QA/XZbCBp4Moo5scrkAMPhB7z26XM/AaHuIJdgauA== - -"@babel/runtime@^7.8.4": - version "7.24.4" - resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.24.4.tgz#de795accd698007a66ba44add6cc86542aff1edd" - integrity sha512-dkxf7+hn8mFBwKjs9bvBlArzLVxVbS8usaPUDd5p2a9JCL9tB8OaOVN1isD4+Xyk4ns89/xeOmbQvgdK7IIVdA== +"@babel/template@^7.24.0", "@babel/template@^7.27.1", "@babel/template@^7.27.2": + version "7.27.2" + resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.27.2.tgz#fa78ceed3c4e7b63ebf6cb39e5852fca45f6809d" + integrity sha512-LPDZ85aEJyYSd18/DkjNh4/y1ntkE5KwUHWTiqgRxruuZL2F1yuHligVHLvcHY2vMHXttKFpJn6LwfI7cw7ODw== dependencies: - regenerator-runtime "^0.14.0" + "@babel/code-frame" "^7.27.1" + "@babel/parser" "^7.27.2" + "@babel/types" "^7.27.1" -"@babel/template@^7.22.15", "@babel/template@^7.24.0": - version "7.24.0" - resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.24.0.tgz#c6a524aa93a4a05d66aaf31654258fae69d87d50" - integrity sha512-Bkf2q8lMB0AFpX0NFEqSbx1OkTHf0f+0j82mkw+ZpzBnkk7e9Ql0891vlfgi+kHwOk8tQjiQHpqh4LaSa0fKEA== +"@babel/traverse@^7.24.1", "@babel/traverse@^7.27.1", "@babel/traverse@^7.27.3", "@babel/traverse@^7.28.0": + version "7.28.0" + resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.28.0.tgz#518aa113359b062042379e333db18380b537e34b" + integrity sha512-mGe7UK5wWyh0bKRfupsUchrQGqvDbZDbKJw+kcRGSmdHVYrv+ltd0pnpDTVpiTqnaBru9iEvA8pz8W46v0Amwg== dependencies: - "@babel/code-frame" "^7.23.5" - "@babel/parser" "^7.24.0" - "@babel/types" "^7.24.0" - -"@babel/traverse@^7.24.1": - version "7.24.1" - resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.24.1.tgz#d65c36ac9dd17282175d1e4a3c49d5b7988f530c" - integrity sha512-xuU6o9m68KeqZbQuDt2TcKSxUw/mrsvavlEqQ1leZ/B+C9tk6E4sRWy97WaXgvq5E+nU3cXMxv3WKOCanVMCmQ== - dependencies: - "@babel/code-frame" "^7.24.1" - "@babel/generator" "^7.24.1" - "@babel/helper-environment-visitor" "^7.22.20" - "@babel/helper-function-name" "^7.23.0" - "@babel/helper-hoist-variables" "^7.22.5" - "@babel/helper-split-export-declaration" "^7.22.6" - "@babel/parser" "^7.24.1" - "@babel/types" "^7.24.0" + "@babel/code-frame" "^7.27.1" + "@babel/generator" "^7.28.0" + "@babel/helper-globals" "^7.28.0" + "@babel/parser" "^7.28.0" + "@babel/template" "^7.27.2" + "@babel/types" "^7.28.0" debug "^4.3.1" - globals "^11.1.0" -"@babel/types@^7.22.15", "@babel/types@^7.22.19", "@babel/types@^7.22.5", "@babel/types@^7.23.0", "@babel/types@^7.23.4", "@babel/types@^7.24.0", "@babel/types@^7.4.4": - version "7.24.0" - resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.24.0.tgz#3b951f435a92e7333eba05b7566fd297960ea1bf" - integrity sha512-+j7a5c253RfKh8iABBhywc8NSfP5LURe7Uh4qpsh6jc+aLJguvmIUBdjSdEMQv2bENrCR5MfRdjGo7vzS/ob7w== +"@babel/types@^7.24.0", "@babel/types@^7.27.1", "@babel/types@^7.27.3", "@babel/types@^7.27.6", "@babel/types@^7.28.0", "@babel/types@^7.4.4": + version "7.28.1" + resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.28.1.tgz#2aaf3c10b31ba03a77ac84f52b3912a0edef4cf9" + integrity sha512-x0LvFTekgSX+83TI28Y9wYPUfzrnl2aT5+5QLnO6v7mSJYtEEevuDRN0F0uSHRk1G1IWZC43o00Y0xDDrpBGPQ== dependencies: - "@babel/helper-string-parser" "^7.23.4" - "@babel/helper-validator-identifier" "^7.22.20" - to-fast-properties "^2.0.0" + "@babel/helper-string-parser" "^7.27.1" + "@babel/helper-validator-identifier" "^7.27.1" -"@esbuild/aix-ppc64@0.20.2": - version "0.20.2" - resolved "https://registry.yarnpkg.com/@esbuild/aix-ppc64/-/aix-ppc64-0.20.2.tgz#a70f4ac11c6a1dfc18b8bbb13284155d933b9537" - integrity sha512-D+EBOJHXdNZcLJRBkhENNG8Wji2kgc9AZ9KiPr1JuZjsNtyHzrsfLRrY0tk2H2aoFu6RANO1y1iPPUCDYWkb5g== +"@esbuild/aix-ppc64@0.25.6": + version "0.25.6" + resolved "https://registry.yarnpkg.com/@esbuild/aix-ppc64/-/aix-ppc64-0.25.6.tgz#164b19122e2ed54f85469df9dea98ddb01d5e79e" + integrity sha512-ShbM/3XxwuxjFiuVBHA+d3j5dyac0aEVVq1oluIDf71hUw0aRF59dV/efUsIwFnR6m8JNM2FjZOzmaZ8yG61kw== -"@esbuild/android-arm64@0.20.2": - version "0.20.2" - resolved "https://registry.yarnpkg.com/@esbuild/android-arm64/-/android-arm64-0.20.2.tgz#db1c9202a5bc92ea04c7b6840f1bbe09ebf9e6b9" - integrity sha512-mRzjLacRtl/tWU0SvD8lUEwb61yP9cqQo6noDZP/O8VkwafSYwZ4yWy24kan8jE/IMERpYncRt2dw438LP3Xmg== +"@esbuild/android-arm64@0.25.6": + version "0.25.6" + resolved "https://registry.yarnpkg.com/@esbuild/android-arm64/-/android-arm64-0.25.6.tgz#8f539e7def848f764f6432598e51cc3820fde3a5" + integrity sha512-hd5zdUarsK6strW+3Wxi5qWws+rJhCCbMiC9QZyzoxfk5uHRIE8T287giQxzVpEvCwuJ9Qjg6bEjcRJcgfLqoA== -"@esbuild/android-arm@0.20.2": - version "0.20.2" - resolved "https://registry.yarnpkg.com/@esbuild/android-arm/-/android-arm-0.20.2.tgz#3b488c49aee9d491c2c8f98a909b785870d6e995" - integrity sha512-t98Ra6pw2VaDhqNWO2Oph2LXbz/EJcnLmKLGBJwEwXX/JAN83Fym1rU8l0JUWK6HkIbWONCSSatf4sf2NBRx/w== +"@esbuild/android-arm@0.25.6": + version "0.25.6" + resolved "https://registry.yarnpkg.com/@esbuild/android-arm/-/android-arm-0.25.6.tgz#4ceb0f40113e9861169be83e2a670c260dd234ff" + integrity sha512-S8ToEOVfg++AU/bHwdksHNnyLyVM+eMVAOf6yRKFitnwnbwwPNqKr3srzFRe7nzV69RQKb5DgchIX5pt3L53xg== -"@esbuild/android-x64@0.20.2": - version "0.20.2" - resolved "https://registry.yarnpkg.com/@esbuild/android-x64/-/android-x64-0.20.2.tgz#3b1628029e5576249d2b2d766696e50768449f98" - integrity sha512-btzExgV+/lMGDDa194CcUQm53ncxzeBrWJcncOBxuC6ndBkKxnHdFJn86mCIgTELsooUmwUm9FkhSp5HYu00Rg== +"@esbuild/android-x64@0.25.6": + version "0.25.6" + resolved "https://registry.yarnpkg.com/@esbuild/android-x64/-/android-x64-0.25.6.tgz#ad4f280057622c25fe985c08999443a195dc63a8" + integrity sha512-0Z7KpHSr3VBIO9A/1wcT3NTy7EB4oNC4upJ5ye3R7taCc2GUdeynSLArnon5G8scPwaU866d3H4BCrE5xLW25A== -"@esbuild/darwin-arm64@0.20.2": - version "0.20.2" - resolved "https://registry.yarnpkg.com/@esbuild/darwin-arm64/-/darwin-arm64-0.20.2.tgz#6e8517a045ddd86ae30c6608c8475ebc0c4000bb" - integrity sha512-4J6IRT+10J3aJH3l1yzEg9y3wkTDgDk7TSDFX+wKFiWjqWp/iCfLIYzGyasx9l0SAFPT1HwSCR+0w/h1ES/MjA== +"@esbuild/darwin-arm64@0.25.6": + version "0.25.6" + resolved "https://registry.yarnpkg.com/@esbuild/darwin-arm64/-/darwin-arm64-0.25.6.tgz#d1f04027396b3d6afc96bacd0d13167dfd9f01f7" + integrity sha512-FFCssz3XBavjxcFxKsGy2DYK5VSvJqa6y5HXljKzhRZ87LvEi13brPrf/wdyl/BbpbMKJNOr1Sd0jtW4Ge1pAA== -"@esbuild/darwin-x64@0.20.2": - version "0.20.2" - resolved "https://registry.yarnpkg.com/@esbuild/darwin-x64/-/darwin-x64-0.20.2.tgz#90ed098e1f9dd8a9381695b207e1cff45540a0d0" - integrity sha512-tBcXp9KNphnNH0dfhv8KYkZhjc+H3XBkF5DKtswJblV7KlT9EI2+jeA8DgBjp908WEuYll6pF+UStUCfEpdysA== +"@esbuild/darwin-x64@0.25.6": + version "0.25.6" + resolved "https://registry.yarnpkg.com/@esbuild/darwin-x64/-/darwin-x64-0.25.6.tgz#2b4a6cedb799f635758d7832d75b23772c8ef68f" + integrity sha512-GfXs5kry/TkGM2vKqK2oyiLFygJRqKVhawu3+DOCk7OxLy/6jYkWXhlHwOoTb0WqGnWGAS7sooxbZowy+pK9Yg== -"@esbuild/freebsd-arm64@0.20.2": - version "0.20.2" - resolved "https://registry.yarnpkg.com/@esbuild/freebsd-arm64/-/freebsd-arm64-0.20.2.tgz#d71502d1ee89a1130327e890364666c760a2a911" - integrity sha512-d3qI41G4SuLiCGCFGUrKsSeTXyWG6yem1KcGZVS+3FYlYhtNoNgYrWcvkOoaqMhwXSMrZRl69ArHsGJ9mYdbbw== +"@esbuild/freebsd-arm64@0.25.6": + version "0.25.6" + resolved "https://registry.yarnpkg.com/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.6.tgz#a26266cc97dd78dc3c3f3d6788b1b83697b1055d" + integrity sha512-aoLF2c3OvDn2XDTRvn8hN6DRzVVpDlj2B/F66clWd/FHLiHaG3aVZjxQX2DYphA5y/evbdGvC6Us13tvyt4pWg== -"@esbuild/freebsd-x64@0.20.2": - version "0.20.2" - resolved "https://registry.yarnpkg.com/@esbuild/freebsd-x64/-/freebsd-x64-0.20.2.tgz#aa5ea58d9c1dd9af688b8b6f63ef0d3d60cea53c" - integrity sha512-d+DipyvHRuqEeM5zDivKV1KuXn9WeRX6vqSqIDgwIfPQtwMP4jaDsQsDncjTDDsExT4lR/91OLjRo8bmC1e+Cw== +"@esbuild/freebsd-x64@0.25.6": + version "0.25.6" + resolved "https://registry.yarnpkg.com/@esbuild/freebsd-x64/-/freebsd-x64-0.25.6.tgz#9feb8e826735c568ebfd94859b22a3fbb6a9bdd2" + integrity sha512-2SkqTjTSo2dYi/jzFbU9Plt1vk0+nNg8YC8rOXXea+iA3hfNJWebKYPs3xnOUf9+ZWhKAaxnQNUf2X9LOpeiMQ== -"@esbuild/linux-arm64@0.20.2": - version "0.20.2" - resolved "https://registry.yarnpkg.com/@esbuild/linux-arm64/-/linux-arm64-0.20.2.tgz#055b63725df678379b0f6db9d0fa85463755b2e5" - integrity sha512-9pb6rBjGvTFNira2FLIWqDk/uaf42sSyLE8j1rnUpuzsODBq7FvpwHYZxQ/It/8b+QOS1RYfqgGFNLRI+qlq2A== +"@esbuild/linux-arm64@0.25.6": + version "0.25.6" + resolved "https://registry.yarnpkg.com/@esbuild/linux-arm64/-/linux-arm64-0.25.6.tgz#c07cbed8e249f4c28e7f32781d36fc4695293d28" + integrity sha512-b967hU0gqKd9Drsh/UuAm21Khpoh6mPBSgz8mKRq4P5mVK8bpA+hQzmm/ZwGVULSNBzKdZPQBRT3+WuVavcWsQ== -"@esbuild/linux-arm@0.20.2": - version "0.20.2" - resolved "https://registry.yarnpkg.com/@esbuild/linux-arm/-/linux-arm-0.20.2.tgz#76b3b98cb1f87936fbc37f073efabad49dcd889c" - integrity sha512-VhLPeR8HTMPccbuWWcEUD1Az68TqaTYyj6nfE4QByZIQEQVWBB8vup8PpR7y1QHL3CpcF6xd5WVBU/+SBEvGTg== +"@esbuild/linux-arm@0.25.6": + version "0.25.6" + resolved "https://registry.yarnpkg.com/@esbuild/linux-arm/-/linux-arm-0.25.6.tgz#d6e2cd8ef3196468065d41f13fa2a61aaa72644a" + integrity sha512-SZHQlzvqv4Du5PrKE2faN0qlbsaW/3QQfUUc6yO2EjFcA83xnwm91UbEEVx4ApZ9Z5oG8Bxz4qPE+HFwtVcfyw== -"@esbuild/linux-ia32@0.20.2": - version "0.20.2" - resolved "https://registry.yarnpkg.com/@esbuild/linux-ia32/-/linux-ia32-0.20.2.tgz#c0e5e787c285264e5dfc7a79f04b8b4eefdad7fa" - integrity sha512-o10utieEkNPFDZFQm9CoP7Tvb33UutoJqg3qKf1PWVeeJhJw0Q347PxMvBgVVFgouYLGIhFYG0UGdBumROyiig== +"@esbuild/linux-ia32@0.25.6": + version "0.25.6" + resolved "https://registry.yarnpkg.com/@esbuild/linux-ia32/-/linux-ia32-0.25.6.tgz#3e682bd47c4eddcc4b8f1393dfc8222482f17997" + integrity sha512-aHWdQ2AAltRkLPOsKdi3xv0mZ8fUGPdlKEjIEhxCPm5yKEThcUjHpWB1idN74lfXGnZ5SULQSgtr5Qos5B0bPw== -"@esbuild/linux-loong64@0.20.2": - version "0.20.2" - resolved "https://registry.yarnpkg.com/@esbuild/linux-loong64/-/linux-loong64-0.20.2.tgz#a6184e62bd7cdc63e0c0448b83801001653219c5" - integrity sha512-PR7sp6R/UC4CFVomVINKJ80pMFlfDfMQMYynX7t1tNTeivQ6XdX5r2XovMmha/VjR1YN/HgHWsVcTRIMkymrgQ== +"@esbuild/linux-loong64@0.25.6": + version "0.25.6" + resolved "https://registry.yarnpkg.com/@esbuild/linux-loong64/-/linux-loong64-0.25.6.tgz#473f5ea2e52399c08ad4cd6b12e6dbcddd630f05" + integrity sha512-VgKCsHdXRSQ7E1+QXGdRPlQ/e08bN6WMQb27/TMfV+vPjjTImuT9PmLXupRlC90S1JeNNW5lzkAEO/McKeJ2yg== -"@esbuild/linux-mips64el@0.20.2": - version "0.20.2" - resolved "https://registry.yarnpkg.com/@esbuild/linux-mips64el/-/linux-mips64el-0.20.2.tgz#d08e39ce86f45ef8fc88549d29c62b8acf5649aa" - integrity sha512-4BlTqeutE/KnOiTG5Y6Sb/Hw6hsBOZapOVF6njAESHInhlQAghVVZL1ZpIctBOoTFbQyGW+LsVYZ8lSSB3wkjA== +"@esbuild/linux-mips64el@0.25.6": + version "0.25.6" + resolved "https://registry.yarnpkg.com/@esbuild/linux-mips64el/-/linux-mips64el-0.25.6.tgz#9960631c9fd61605b0939c19043acf4ef2b51718" + integrity sha512-WViNlpivRKT9/py3kCmkHnn44GkGXVdXfdc4drNmRl15zVQ2+D2uFwdlGh6IuK5AAnGTo2qPB1Djppj+t78rzw== -"@esbuild/linux-ppc64@0.20.2": - version "0.20.2" - resolved "https://registry.yarnpkg.com/@esbuild/linux-ppc64/-/linux-ppc64-0.20.2.tgz#8d252f0b7756ffd6d1cbde5ea67ff8fd20437f20" - integrity sha512-rD3KsaDprDcfajSKdn25ooz5J5/fWBylaaXkuotBDGnMnDP1Uv5DLAN/45qfnf3JDYyJv/ytGHQaziHUdyzaAg== +"@esbuild/linux-ppc64@0.25.6": + version "0.25.6" + resolved "https://registry.yarnpkg.com/@esbuild/linux-ppc64/-/linux-ppc64-0.25.6.tgz#477cbf8bb04aa034b94f362c32c86b5c31db8d3e" + integrity sha512-wyYKZ9NTdmAMb5730I38lBqVu6cKl4ZfYXIs31Baf8aoOtB4xSGi3THmDYt4BTFHk7/EcVixkOV2uZfwU3Q2Jw== -"@esbuild/linux-riscv64@0.20.2": - version "0.20.2" - resolved "https://registry.yarnpkg.com/@esbuild/linux-riscv64/-/linux-riscv64-0.20.2.tgz#19f6dcdb14409dae607f66ca1181dd4e9db81300" - integrity sha512-snwmBKacKmwTMmhLlz/3aH1Q9T8v45bKYGE3j26TsaOVtjIag4wLfWSiZykXzXuE1kbCE+zJRmwp+ZbIHinnVg== +"@esbuild/linux-riscv64@0.25.6": + version "0.25.6" + resolved "https://registry.yarnpkg.com/@esbuild/linux-riscv64/-/linux-riscv64-0.25.6.tgz#bcdb46c8fb8e93aa779e9a0a62cd4ac00dcac626" + integrity sha512-KZh7bAGGcrinEj4qzilJ4hqTY3Dg2U82c8bv+e1xqNqZCrCyc+TL9AUEn5WGKDzm3CfC5RODE/qc96OcbIe33w== -"@esbuild/linux-s390x@0.20.2": - version "0.20.2" - resolved "https://registry.yarnpkg.com/@esbuild/linux-s390x/-/linux-s390x-0.20.2.tgz#3c830c90f1a5d7dd1473d5595ea4ebb920988685" - integrity sha512-wcWISOobRWNm3cezm5HOZcYz1sKoHLd8VL1dl309DiixxVFoFe/o8HnwuIwn6sXre88Nwj+VwZUvJf4AFxkyrQ== +"@esbuild/linux-s390x@0.25.6": + version "0.25.6" + resolved "https://registry.yarnpkg.com/@esbuild/linux-s390x/-/linux-s390x-0.25.6.tgz#f412cf5fdf0aea849ff51c73fd817c6c0234d46d" + integrity sha512-9N1LsTwAuE9oj6lHMyyAM+ucxGiVnEqUdp4v7IaMmrwb06ZTEVCIs3oPPplVsnjPfyjmxwHxHMF8b6vzUVAUGw== -"@esbuild/linux-x64@0.20.2": - version "0.20.2" - resolved "https://registry.yarnpkg.com/@esbuild/linux-x64/-/linux-x64-0.20.2.tgz#86eca35203afc0d9de0694c64ec0ab0a378f6fff" - integrity sha512-1MdwI6OOTsfQfek8sLwgyjOXAu+wKhLEoaOLTjbijk6E2WONYpH9ZU2mNtR+lZ2B4uwr+usqGuVfFT9tMtGvGw== +"@esbuild/linux-x64@0.25.6": + version "0.25.6" + resolved "https://registry.yarnpkg.com/@esbuild/linux-x64/-/linux-x64-0.25.6.tgz#d8233c09b5ebc0c855712dc5eeb835a3a3341108" + integrity sha512-A6bJB41b4lKFWRKNrWoP2LHsjVzNiaurf7wyj/XtFNTsnPuxwEBWHLty+ZE0dWBKuSK1fvKgrKaNjBS7qbFKig== -"@esbuild/netbsd-x64@0.20.2": - version "0.20.2" - resolved "https://registry.yarnpkg.com/@esbuild/netbsd-x64/-/netbsd-x64-0.20.2.tgz#e771c8eb0e0f6e1877ffd4220036b98aed5915e6" - integrity sha512-K8/DhBxcVQkzYc43yJXDSyjlFeHQJBiowJ0uVL6Tor3jGQfSGHNNJcWxNbOI8v5k82prYqzPuwkzHt3J1T1iZQ== +"@esbuild/netbsd-arm64@0.25.6": + version "0.25.6" + resolved "https://registry.yarnpkg.com/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.6.tgz#f51ae8dd1474172e73cf9cbaf8a38d1c72dd8f1a" + integrity sha512-IjA+DcwoVpjEvyxZddDqBY+uJ2Snc6duLpjmkXm/v4xuS3H+3FkLZlDm9ZsAbF9rsfP3zeA0/ArNDORZgrxR/Q== -"@esbuild/openbsd-x64@0.20.2": - version "0.20.2" - resolved "https://registry.yarnpkg.com/@esbuild/openbsd-x64/-/openbsd-x64-0.20.2.tgz#9a795ae4b4e37e674f0f4d716f3e226dd7c39baf" - integrity sha512-eMpKlV0SThJmmJgiVyN9jTPJ2VBPquf6Kt/nAoo6DgHAoN57K15ZghiHaMvqjCye/uU4X5u3YSMgVBI1h3vKrQ== +"@esbuild/netbsd-x64@0.25.6": + version "0.25.6" + resolved "https://registry.yarnpkg.com/@esbuild/netbsd-x64/-/netbsd-x64-0.25.6.tgz#a267538602c0e50a858cf41dcfe5d8036f8da8e7" + integrity sha512-dUXuZr5WenIDlMHdMkvDc1FAu4xdWixTCRgP7RQLBOkkGgwuuzaGSYcOpW4jFxzpzL1ejb8yF620UxAqnBrR9g== -"@esbuild/sunos-x64@0.20.2": - version "0.20.2" - resolved "https://registry.yarnpkg.com/@esbuild/sunos-x64/-/sunos-x64-0.20.2.tgz#7df23b61a497b8ac189def6e25a95673caedb03f" - integrity sha512-2UyFtRC6cXLyejf/YEld4Hajo7UHILetzE1vsRcGL3earZEW77JxrFjH4Ez2qaTiEfMgAXxfAZCm1fvM/G/o8w== +"@esbuild/openbsd-arm64@0.25.6": + version "0.25.6" + resolved "https://registry.yarnpkg.com/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.6.tgz#a51be60c425b85c216479b8c344ad0511635f2d2" + integrity sha512-l8ZCvXP0tbTJ3iaqdNf3pjaOSd5ex/e6/omLIQCVBLmHTlfXW3zAxQ4fnDmPLOB1x9xrcSi/xtCWFwCZRIaEwg== -"@esbuild/win32-arm64@0.20.2": - version "0.20.2" - resolved "https://registry.yarnpkg.com/@esbuild/win32-arm64/-/win32-arm64-0.20.2.tgz#f1ae5abf9ca052ae11c1bc806fb4c0f519bacf90" - integrity sha512-GRibxoawM9ZCnDxnP3usoUDO9vUkpAxIIZ6GQI+IlVmr5kP3zUq+l17xELTHMWTWzjxa2guPNyrpq1GWmPvcGQ== +"@esbuild/openbsd-x64@0.25.6": + version "0.25.6" + resolved "https://registry.yarnpkg.com/@esbuild/openbsd-x64/-/openbsd-x64-0.25.6.tgz#7e4a743c73f75562e29223ba69d0be6c9c9008da" + integrity sha512-hKrmDa0aOFOr71KQ/19JC7az1P0GWtCN1t2ahYAf4O007DHZt/dW8ym5+CUdJhQ/qkZmI1HAF8KkJbEFtCL7gw== -"@esbuild/win32-ia32@0.20.2": - version "0.20.2" - resolved "https://registry.yarnpkg.com/@esbuild/win32-ia32/-/win32-ia32-0.20.2.tgz#241fe62c34d8e8461cd708277813e1d0ba55ce23" - integrity sha512-HfLOfn9YWmkSKRQqovpnITazdtquEW8/SoHW7pWpuEeguaZI4QnCRW6b+oZTztdBnZOS2hqJ6im/D5cPzBTTlQ== +"@esbuild/openharmony-arm64@0.25.6": + version "0.25.6" + resolved "https://registry.yarnpkg.com/@esbuild/openharmony-arm64/-/openharmony-arm64-0.25.6.tgz#2087a5028f387879154ebf44bdedfafa17682e5b" + integrity sha512-+SqBcAWoB1fYKmpWoQP4pGtx+pUUC//RNYhFdbcSA16617cchuryuhOCRpPsjCblKukAckWsV+aQ3UKT/RMPcA== -"@esbuild/win32-x64@0.20.2": - version "0.20.2" - resolved "https://registry.yarnpkg.com/@esbuild/win32-x64/-/win32-x64-0.20.2.tgz#9c907b21e30a52db959ba4f80bb01a0cc403d5cc" - integrity sha512-N49X4lJX27+l9jbLKSqZ6bKNjzQvHaT8IIFUy+YIqmXQdjYCToGWwOItDrfby14c78aDd5NHQl29xingXfCdLQ== +"@esbuild/sunos-x64@0.25.6": + version "0.25.6" + resolved "https://registry.yarnpkg.com/@esbuild/sunos-x64/-/sunos-x64-0.25.6.tgz#56531f861723ea0dc6283a2bb8837304223cb736" + integrity sha512-dyCGxv1/Br7MiSC42qinGL8KkG4kX0pEsdb0+TKhmJZgCUDBGmyo1/ArCjNGiOLiIAgdbWgmWgib4HoCi5t7kA== + +"@esbuild/win32-arm64@0.25.6": + version "0.25.6" + resolved "https://registry.yarnpkg.com/@esbuild/win32-arm64/-/win32-arm64-0.25.6.tgz#f4989f033deac6fae323acff58764fa8bc01436e" + integrity sha512-42QOgcZeZOvXfsCBJF5Afw73t4veOId//XD3i+/9gSkhSV6Gk3VPlWncctI+JcOyERv85FUo7RxuxGy+z8A43Q== + +"@esbuild/win32-ia32@0.25.6": + version "0.25.6" + resolved "https://registry.yarnpkg.com/@esbuild/win32-ia32/-/win32-ia32-0.25.6.tgz#b260e9df71e3939eb33925076d39f63cec7d1525" + integrity sha512-4AWhgXmDuYN7rJI6ORB+uU9DHLq/erBbuMoAuB4VWJTu5KtCgcKYPynF0YI1VkBNuEfjNlLrFr9KZPJzrtLkrQ== + +"@esbuild/win32-x64@0.25.6": + version "0.25.6" + resolved "https://registry.yarnpkg.com/@esbuild/win32-x64/-/win32-x64-0.25.6.tgz#4276edd5c105bc28b11c6a1f76fb9d29d1bd25c1" + integrity sha512-NgJPHHbEpLQgDH2MjQu90pzW/5vvXIZ7KOnPyNBm92A6WgZ/7b6fJyUBjoumLqeOQQGqY2QjQxRo97ah4Sj0cA== "@eslint-community/eslint-utils@^4.2.0": version "4.4.0" @@ -1227,7 +1124,15 @@ wrap-ansi "^8.1.0" wrap-ansi-cjs "npm:wrap-ansi@^7.0.0" -"@jridgewell/gen-mapping@^0.3.2", "@jridgewell/gen-mapping@^0.3.5": +"@jridgewell/gen-mapping@^0.3.12", "@jridgewell/gen-mapping@^0.3.5": + version "0.3.12" + resolved "https://registry.yarnpkg.com/@jridgewell/gen-mapping/-/gen-mapping-0.3.12.tgz#2234ce26c62889f03db3d7fea43c1932ab3e927b" + integrity sha512-OuLGC46TjB5BbN1dH8JULVVZY4WTdkF7tV9Ys6wLL1rubZnCMstOhNHueU5bLCrnRuDhKPDM4g6sw4Bel5Gzqg== + dependencies: + "@jridgewell/sourcemap-codec" "^1.5.0" + "@jridgewell/trace-mapping" "^0.3.24" + +"@jridgewell/gen-mapping@^0.3.2": version "0.3.5" resolved "https://registry.yarnpkg.com/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz#dcce6aff74bdf6dad1a95802b69b04a2fcb1fb36" integrity sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg== @@ -1254,15 +1159,15 @@ "@jridgewell/gen-mapping" "^0.3.5" "@jridgewell/trace-mapping" "^0.3.25" -"@jridgewell/sourcemap-codec@^1.4.10", "@jridgewell/sourcemap-codec@^1.4.14", "@jridgewell/sourcemap-codec@^1.4.15": - version "1.4.15" - resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz#d7c6e6755c78567a951e04ab52ef0fd26de59f32" - integrity sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg== +"@jridgewell/sourcemap-codec@^1.4.10", "@jridgewell/sourcemap-codec@^1.4.14", "@jridgewell/sourcemap-codec@^1.5.0": + version "1.5.4" + resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.4.tgz#7358043433b2e5da569aa02cbc4c121da3af27d7" + integrity sha512-VT2+G1VQs/9oz078bLrYbecdZKs912zQlkelYpuf+SXF+QvZDYJlbx/LSx+meSAwdDFnF8FVXW92AVjjkVmgFw== -"@jridgewell/trace-mapping@^0.3.24", "@jridgewell/trace-mapping@^0.3.25": - version "0.3.25" - resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz#15f190e98895f3fc23276ee14bc76b675c2e50f0" - integrity sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ== +"@jridgewell/trace-mapping@^0.3.24", "@jridgewell/trace-mapping@^0.3.25", "@jridgewell/trace-mapping@^0.3.28": + version "0.3.29" + resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.29.tgz#a58d31eaadaf92c6695680b2e1d464a9b8fbf7fc" + integrity sha512-uw6guiW/gcAGPDhLmd77/6lW8QLeiV5RUTsAX46Db6oLhGaVj4lhnPwb184s1bkc8kdVg/+h988dro8GRDpmYQ== dependencies: "@jridgewell/resolve-uri" "^3.1.0" "@jridgewell/sourcemap-codec" "^1.4.14" @@ -1305,10 +1210,10 @@ resolved "https://registry.yarnpkg.com/@pkgjs/parseargs/-/parseargs-0.11.0.tgz#a77ea742fab25775145434eb1d2328cf5013ac33" integrity sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg== -"@preact/preset-vite@^2.8.2": - version "2.8.2" - resolved "https://registry.yarnpkg.com/@preact/preset-vite/-/preset-vite-2.8.2.tgz#8113a37c8f7dfa0156fe1e6811bdc2b7ea6a3490" - integrity sha512-m3tl+M8IO8jgiHnk+7LSTFl8axdPXloewi7iGVLdmCwf34XOzEUur0bZVewW4DUbUipFjTS2CXu27+5f/oexBA== +"@preact/preset-vite@^2.10.2": + version "2.10.2" + resolved "https://registry.yarnpkg.com/@preact/preset-vite/-/preset-vite-2.10.2.tgz#7fdf94e523bab2588054858c3ecd4d253fdbcea9" + integrity sha512-K9wHlJOtkE+cGqlyQ5v9kL3Ge0Ql4LlIZjkUTL+1zf3nNdF88F9UZN6VTV8jdzBX9Fl7WSzeNMSDG7qECPmSmg== dependencies: "@babel/plugin-transform-react-jsx" "^7.22.15" "@babel/plugin-transform-react-jsx-development" "^7.22.5" @@ -1316,37 +1221,33 @@ "@rollup/pluginutils" "^4.1.1" babel-plugin-transform-hook-names "^1.0.2" debug "^4.3.4" - kolorist "^1.8.0" - magic-string "0.30.5" - node-html-parser "^6.1.10" - resolve "^1.22.8" - source-map "^0.7.4" - stack-trace "^1.0.0-pre2" + picocolors "^1.1.1" + vite-prerender-plugin "^0.5.3" -"@prefresh/babel-plugin@0.5.1": - version "0.5.1" - resolved "https://registry.yarnpkg.com/@prefresh/babel-plugin/-/babel-plugin-0.5.1.tgz#3161bbbf12dd39a5fe08514349898fa6a20525b7" - integrity sha512-uG3jGEAysxWoyG3XkYfjYHgaySFrSsaEb4GagLzYaxlydbuREtaX+FTxuIidp241RaLl85XoHg9Ej6E4+V1pcg== +"@prefresh/babel-plugin@0.5.2": + version "0.5.2" + resolved "https://registry.yarnpkg.com/@prefresh/babel-plugin/-/babel-plugin-0.5.2.tgz#827a655a89bdf6efa5c7ae2cca3ed45c1a1b43db" + integrity sha512-AOl4HG6dAxWkJ5ndPHBgBa49oo/9bOiJuRDKHLSTyH+Fd9x00shTXpdiTj1W41l6oQIwUOAgJeHMn4QwIDpHkA== -"@prefresh/core@^1.5.1": - version "1.5.2" - resolved "https://registry.yarnpkg.com/@prefresh/core/-/core-1.5.2.tgz#750e1936d82f3b0a1199d3cda5c35e3443128490" - integrity sha512-A/08vkaM1FogrCII5PZKCrygxSsc11obExBScm3JF1CryK2uDS3ZXeni7FeKCx1nYdUkj4UcJxzPzc1WliMzZA== +"@prefresh/core@^1.5.4": + version "1.5.5" + resolved "https://registry.yarnpkg.com/@prefresh/core/-/core-1.5.5.tgz#53af12227f8e16a77cac4d12ef83c66741cbb254" + integrity sha512-H6GTXUl4V4fe3ijz7yhSa/mZ+pGSOh7XaJb6uP/sQsagBx9yl0D1HKDaeoMQA8Ad2Xm27LqvbitMGSdY9UFSKQ== -"@prefresh/utils@^1.2.0": - version "1.2.0" - resolved "https://registry.yarnpkg.com/@prefresh/utils/-/utils-1.2.0.tgz#cbdfe549b207041e38bb6cc382408b30cd24fec8" - integrity sha512-KtC/fZw+oqtwOLUFM9UtiitB0JsVX0zLKNyRTA332sqREqSALIIQQxdUCS1P3xR/jT1e2e8/5rwH6gdcMLEmsQ== +"@prefresh/utils@^1.2.1": + version "1.2.1" + resolved "https://registry.yarnpkg.com/@prefresh/utils/-/utils-1.2.1.tgz#c1cb3c3114839d07271a36b386bf03cf354d31d7" + integrity sha512-vq/sIuN5nYfYzvyayXI4C2QkprfNaHUQ9ZX+3xLD8nL3rWyzpxOm1+K7RtMbhd+66QcaISViK7amjnheQ/4WZw== "@prefresh/vite@^2.4.1": - version "2.4.5" - resolved "https://registry.yarnpkg.com/@prefresh/vite/-/vite-2.4.5.tgz#8e6ecdb36510b8497c346a5a7f55e0bc9b9b5f6b" - integrity sha512-iForDVJ2M8gQYnm5pHumvTEJjGGc7YNYC0GVKnHFL+GvFfKHfH9Rpq67nUAzNbjuLEpqEOUuQVQajMazWu2ZNQ== + version "2.4.8" + resolved "https://registry.yarnpkg.com/@prefresh/vite/-/vite-2.4.8.tgz#def4418ca57020b66fb49d407eb022b4552e4205" + integrity sha512-H7vlo9UbJInuRbZhRQrdgVqLP7qKjDoX7TgYWWwIVhEHeHO0hZ4zyicvwBrV1wX5A3EPOmArgRkUaN7cPI2VXQ== dependencies: "@babel/core" "^7.22.1" - "@prefresh/babel-plugin" "0.5.1" - "@prefresh/core" "^1.5.1" - "@prefresh/utils" "^1.2.0" + "@prefresh/babel-plugin" "0.5.2" + "@prefresh/core" "^1.5.4" + "@prefresh/utils" "^1.2.1" "@rollup/pluginutils" "^4.2.1" "@rollup/pluginutils@^4.1.1", "@rollup/pluginutils@^4.2.1": @@ -1357,85 +1258,110 @@ estree-walker "^2.0.1" picomatch "^2.2.2" -"@rollup/rollup-android-arm-eabi@4.14.1": - version "4.14.1" - resolved "https://registry.yarnpkg.com/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.14.1.tgz#ca0501dd836894216cb9572848c5dde4bfca3bec" - integrity sha512-fH8/o8nSUek8ceQnT7K4EQbSiV7jgkHq81m9lWZFIXjJ7lJzpWXbQFpT/Zh6OZYnpFykvzC3fbEvEAFZu03dPA== +"@rollup/rollup-android-arm-eabi@4.45.0": + version "4.45.0" + resolved "https://registry.yarnpkg.com/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.45.0.tgz#0592252f7550bc0ea0474bb5a22430850f92bdbd" + integrity sha512-2o/FgACbji4tW1dzXOqAV15Eu7DdgbKsF2QKcxfG4xbh5iwU7yr5RRP5/U+0asQliSYv5M4o7BevlGIoSL0LXg== -"@rollup/rollup-android-arm64@4.14.1": - version "4.14.1" - resolved "https://registry.yarnpkg.com/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.14.1.tgz#154ca7e4f815d2e442ffc62ee7f64aee8b2547b0" - integrity sha512-Y/9OHLjzkunF+KGEoJr3heiD5X9OLa8sbT1lm0NYeKyaM3oMhhQFvPB0bNZYJwlq93j8Z6wSxh9+cyKQaxS7PQ== +"@rollup/rollup-android-arm64@4.45.0": + version "4.45.0" + resolved "https://registry.yarnpkg.com/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.45.0.tgz#00a51d1d4380cc677da80ac9da1a19e7806bf57e" + integrity sha512-PSZ0SvMOjEAxwZeTx32eI/j5xSYtDCRxGu5k9zvzoY77xUNssZM+WV6HYBLROpY5CkXsbQjvz40fBb7WPwDqtQ== -"@rollup/rollup-darwin-arm64@4.14.1": - version "4.14.1" - resolved "https://registry.yarnpkg.com/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.14.1.tgz#02b522ab6ccc2c504634651985ff8e657b42c055" - integrity sha512-+kecg3FY84WadgcuSVm6llrABOdQAEbNdnpi5X3UwWiFVhZIZvKgGrF7kmLguvxHNQy+UuRV66cLVl3S+Rkt+Q== +"@rollup/rollup-darwin-arm64@4.45.0": + version "4.45.0" + resolved "https://registry.yarnpkg.com/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.45.0.tgz#6638299dd282ebde1ebdf7dc5b0f150aa6e256e5" + integrity sha512-BA4yPIPssPB2aRAWzmqzQ3y2/KotkLyZukVB7j3psK/U3nVJdceo6qr9pLM2xN6iRP/wKfxEbOb1yrlZH6sYZg== -"@rollup/rollup-darwin-x64@4.14.1": - version "4.14.1" - resolved "https://registry.yarnpkg.com/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.14.1.tgz#217737f9f73de729fdfd7d529afebb6c8283f554" - integrity sha512-2pYRzEjVqq2TB/UNv47BV/8vQiXkFGVmPFwJb+1E0IFFZbIX8/jo1olxqqMbo6xCXf8kabANhp5bzCij2tFLUA== +"@rollup/rollup-darwin-x64@4.45.0": + version "4.45.0" + resolved "https://registry.yarnpkg.com/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.45.0.tgz#33e61daa0a66890059648feda78e1075d4ea1bcb" + integrity sha512-Pr2o0lvTwsiG4HCr43Zy9xXrHspyMvsvEw4FwKYqhli4FuLE5FjcZzuQ4cfPe0iUFCvSQG6lACI0xj74FDZKRA== -"@rollup/rollup-linux-arm-gnueabihf@4.14.1": - version "4.14.1" - resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.14.1.tgz#a87e478ab3f697c7f4e74c8b1cac1e0667f8f4be" - integrity sha512-mS6wQ6Do6/wmrF9aTFVpIJ3/IDXhg1EZcQFYHZLHqw6AzMBjTHWnCG35HxSqUNphh0EHqSM6wRTT8HsL1C0x5g== +"@rollup/rollup-freebsd-arm64@4.45.0": + version "4.45.0" + resolved "https://registry.yarnpkg.com/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.45.0.tgz#2cc4bd3ba7026cd5374e902285ce76e8fae0f6eb" + integrity sha512-lYE8LkE5h4a/+6VnnLiL14zWMPnx6wNbDG23GcYFpRW1V9hYWHAw9lBZ6ZUIrOaoK7NliF1sdwYGiVmziUF4vA== -"@rollup/rollup-linux-arm64-gnu@4.14.1": - version "4.14.1" - resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.14.1.tgz#4da6830eca27e5f4ca15f9197e5660952ca185c6" - integrity sha512-p9rGKYkHdFMzhckOTFubfxgyIO1vw//7IIjBBRVzyZebWlzRLeNhqxuSaZ7kCEKVkm/kuC9fVRW9HkC/zNRG2w== +"@rollup/rollup-freebsd-x64@4.45.0": + version "4.45.0" + resolved "https://registry.yarnpkg.com/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.45.0.tgz#64664ba3015deac473a5d6d6c60c068f274bf2d5" + integrity sha512-PVQWZK9sbzpvqC9Q0GlehNNSVHR+4m7+wET+7FgSnKG3ci5nAMgGmr9mGBXzAuE5SvguCKJ6mHL6vq1JaJ/gvw== -"@rollup/rollup-linux-arm64-musl@4.14.1": - version "4.14.1" - resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.14.1.tgz#0b0ed35720aebc8f5e501d370a9ea0f686ead1e0" - integrity sha512-nDY6Yz5xS/Y4M2i9JLQd3Rofh5OR8Bn8qe3Mv/qCVpHFlwtZSBYSPaU4mrGazWkXrdQ98GB//H0BirGR/SKFSw== +"@rollup/rollup-linux-arm-gnueabihf@4.45.0": + version "4.45.0" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.45.0.tgz#7ab16acae3bcae863e9a9bc32038cd05e794a0ff" + integrity sha512-hLrmRl53prCcD+YXTfNvXd776HTxNh8wPAMllusQ+amcQmtgo3V5i/nkhPN6FakW+QVLoUUr2AsbtIRPFU3xIA== -"@rollup/rollup-linux-powerpc64le-gnu@4.14.1": - version "4.14.1" - resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.14.1.tgz#024ad04d162726f25e62915851f7df69a9677c17" - integrity sha512-im7HE4VBL+aDswvcmfx88Mp1soqL9OBsdDBU8NqDEYtkri0qV0THhQsvZtZeNNlLeCUQ16PZyv7cqutjDF35qw== +"@rollup/rollup-linux-arm-musleabihf@4.45.0": + version "4.45.0" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.45.0.tgz#bef91b1e924ab57e82e767dc2655264bbde7acc6" + integrity sha512-XBKGSYcrkdiRRjl+8XvrUR3AosXU0NvF7VuqMsm7s5nRy+nt58ZMB19Jdp1RdqewLcaYnpk8zeVs/4MlLZEJxw== -"@rollup/rollup-linux-riscv64-gnu@4.14.1": - version "4.14.1" - resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.14.1.tgz#180694d1cd069ddbe22022bb5b1bead3b7de581c" - integrity sha512-RWdiHuAxWmzPJgaHJdpvUUlDz8sdQz4P2uv367T2JocdDa98iRw2UjIJ4QxSyt077mXZT2X6pKfT2iYtVEvOFw== +"@rollup/rollup-linux-arm64-gnu@4.45.0": + version "4.45.0" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.45.0.tgz#0a811b16da334125f6e44570d0badf543876f49e" + integrity sha512-fRvZZPUiBz7NztBE/2QnCS5AtqLVhXmUOPj9IHlfGEXkapgImf4W9+FSkL8cWqoAjozyUzqFmSc4zh2ooaeF6g== -"@rollup/rollup-linux-s390x-gnu@4.14.1": - version "4.14.1" - resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.14.1.tgz#f7b4e2b0ca49be4e34f9ef0b548c926d94edee87" - integrity sha512-VMgaGQ5zRX6ZqV/fas65/sUGc9cPmsntq2FiGmayW9KMNfWVG/j0BAqImvU4KTeOOgYSf1F+k6at1UfNONuNjA== +"@rollup/rollup-linux-arm64-musl@4.45.0": + version "4.45.0" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.45.0.tgz#e8c166efe3cb963faaa924c7721eafbade63036f" + integrity sha512-Btv2WRZOcUGi8XU80XwIvzTg4U6+l6D0V6sZTrZx214nrwxw5nAi8hysaXj/mctyClWgesyuxbeLylCBNauimg== -"@rollup/rollup-linux-x64-gnu@4.14.1": - version "4.14.1" - resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.14.1.tgz#0aaf79e5b9ccf7db3084fe6c3f2d2873a27d5af4" - integrity sha512-9Q7DGjZN+hTdJomaQ3Iub4m6VPu1r94bmK2z3UeWP3dGUecRC54tmVu9vKHTm1bOt3ASoYtEz6JSRLFzrysKlA== +"@rollup/rollup-linux-loongarch64-gnu@4.45.0": + version "4.45.0" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-loongarch64-gnu/-/rollup-linux-loongarch64-gnu-4.45.0.tgz#239feea00fa2a1e734bdff09b8d1c90def2abbf5" + integrity sha512-Li0emNnwtUZdLwHjQPBxn4VWztcrw/h7mgLyHiEI5Z0MhpeFGlzaiBHpSNVOMB/xucjXTTcO+dhv469Djr16KA== -"@rollup/rollup-linux-x64-musl@4.14.1": - version "4.14.1" - resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.14.1.tgz#38f0a37ca5015eb07dff86a1b6f94279c179f4ed" - integrity sha512-JNEG/Ti55413SsreTguSx0LOVKX902OfXIKVg+TCXO6Gjans/k9O6ww9q3oLGjNDaTLxM+IHFMeXy/0RXL5R/g== +"@rollup/rollup-linux-powerpc64le-gnu@4.45.0": + version "4.45.0" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.45.0.tgz#1de2f926bddbf7d689a089277c1284ea6df4b6d1" + integrity sha512-sB8+pfkYx2kvpDCfd63d5ScYT0Fz1LO6jIb2zLZvmK9ob2D8DeVqrmBDE0iDK8KlBVmsTNzrjr3G1xV4eUZhSw== -"@rollup/rollup-win32-arm64-msvc@4.14.1": - version "4.14.1" - resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.14.1.tgz#84d48c55740ede42c77373f76e85f368633a0cc3" - integrity sha512-ryS22I9y0mumlLNwDFYZRDFLwWh3aKaC72CWjFcFvxK0U6v/mOkM5Up1bTbCRAhv3kEIwW2ajROegCIQViUCeA== +"@rollup/rollup-linux-riscv64-gnu@4.45.0": + version "4.45.0" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.45.0.tgz#28dbac643244e477a7b931feb9b475aa826f84c1" + integrity sha512-5GQ6PFhh7E6jQm70p1aW05G2cap5zMOvO0se5JMecHeAdj5ZhWEHbJ4hiKpfi1nnnEdTauDXxPgXae/mqjow9w== -"@rollup/rollup-win32-ia32-msvc@4.14.1": - version "4.14.1" - resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.14.1.tgz#c1e0bc39e20e760f0a526ddf14ae0543af796605" - integrity sha512-TdloItiGk+T0mTxKx7Hp279xy30LspMso+GzQvV2maYePMAWdmrzqSNZhUpPj3CGw12aGj57I026PgLCTu8CGg== +"@rollup/rollup-linux-riscv64-musl@4.45.0": + version "4.45.0" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.45.0.tgz#5d05eeaedadec3625cd50e3ca5d35ef6f96a4bf0" + integrity sha512-N/euLsBd1rekWcuduakTo/dJw6U6sBP3eUq+RXM9RNfPuWTvG2w/WObDkIvJ2KChy6oxZmOSC08Ak2OJA0UiAA== -"@rollup/rollup-win32-x64-msvc@4.14.1": - version "4.14.1" - resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.14.1.tgz#299eee74b7d87e116083ac5b1ce8dd9434668294" - integrity sha512-wQGI+LY/Py20zdUPq+XCem7JcPOyzIJBm3dli+56DJsQOHbnXZFEwgmnC6el1TPAfC8lBT3m+z69RmLykNUbew== +"@rollup/rollup-linux-s390x-gnu@4.45.0": + version "4.45.0" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.45.0.tgz#55b0790f499fb7adc14eb074c4e46aef92915813" + integrity sha512-2l9sA7d7QdikL0xQwNMO3xURBUNEWyHVHfAsHsUdq+E/pgLTUcCE+gih5PCdmyHmfTDeXUWVhqL0WZzg0nua3g== -"@types/estree@1.0.5": - version "1.0.5" - resolved "https://registry.yarnpkg.com/@types/estree/-/estree-1.0.5.tgz#a6ce3e556e00fd9895dd872dd172ad0d4bd687f4" - integrity sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw== +"@rollup/rollup-linux-x64-gnu@4.45.0": + version "4.45.0" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.45.0.tgz#e822632fe5b324b16bdc37149149c8c760b031fd" + integrity sha512-XZdD3fEEQcwG2KrJDdEQu7NrHonPxxaV0/w2HpvINBdcqebz1aL+0vM2WFJq4DeiAVT6F5SUQas65HY5JDqoPw== + +"@rollup/rollup-linux-x64-musl@4.45.0": + version "4.45.0" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.45.0.tgz#19a3602cb8fabd7eb3087f0a1e1e01adac31bbff" + integrity sha512-7ayfgvtmmWgKWBkCGg5+xTQ0r5V1owVm67zTrsEY1008L5ro7mCyGYORomARt/OquB9KY7LpxVBZes+oSniAAQ== + +"@rollup/rollup-win32-arm64-msvc@4.45.0": + version "4.45.0" + resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.45.0.tgz#42e08bf3ea4fc463fc9f199c4f0310a736f03eb1" + integrity sha512-B+IJgcBnE2bm93jEW5kHisqvPITs4ddLOROAcOc/diBgrEiQJJ6Qcjby75rFSmH5eMGrqJryUgJDhrfj942apQ== + +"@rollup/rollup-win32-ia32-msvc@4.45.0": + version "4.45.0" + resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.45.0.tgz#043d25557f59d7e28dfe38ee1f60ddcb95a08124" + integrity sha512-+CXwwG66g0/FpWOnP/v1HnrGVSOygK/osUbu3wPRy8ECXjoYKjRAyfxYpDQOfghC5qPJYLPH0oN4MCOjwgdMug== + +"@rollup/rollup-win32-x64-msvc@4.45.0": + version "4.45.0" + resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.45.0.tgz#0a7eecae41f463d6591c8fecd7a5c5087345ee36" + integrity sha512-SRf1cytG7wqcHVLrBc9VtPK4pU5wxiB/lNIkNmW2ApKXIg+RpqwHfsaEK+e7eH4A1BpI6BX/aBWXxZCIrJg3uA== + +"@types/estree@1.0.8": + version "1.0.8" + resolved "https://registry.yarnpkg.com/@types/estree/-/estree-1.0.8.tgz#958b91c991b1867ced318bedea0e215ee050726e" + integrity sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w== "@types/json-schema@^7.0.9": version "7.0.15" @@ -1507,26 +1433,31 @@ resolved "https://registry.yarnpkg.com/@ungap/structured-clone/-/structured-clone-1.2.0.tgz#756641adb587851b5ccb3e095daf27ae581c8406" integrity sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ== -"@vitejs/plugin-legacy@^5.3.2": - version "5.3.2" - resolved "https://registry.yarnpkg.com/@vitejs/plugin-legacy/-/plugin-legacy-5.3.2.tgz#f890db6014898c36af85b8ad52c680ef026b8aa8" - integrity sha512-8moCOrIMaZ/Rjln0Q6GsH6s8fAt1JOI3k8nmfX4tXUxE5KAExVctSyOBk+A25GClsdSWqIk2yaUthH3KJ2X4tg== +"@vitejs/plugin-legacy@^7.0.0": + version "7.0.0" + resolved "https://registry.yarnpkg.com/@vitejs/plugin-legacy/-/plugin-legacy-7.0.0.tgz#4c39082988d2566f7277311841b9db4eae580321" + integrity sha512-qevhyYFUeZXBd/bAZGwpBgyn4GGAYije9YPV8Jg07newPCZtFEIlFlzsQowPbm87iKekOIL/90wKn+hvGkjzkg== dependencies: - "@babel/core" "^7.23.9" - "@babel/preset-env" "^7.23.9" - browserslist "^4.23.0" + "@babel/core" "^7.27.4" + "@babel/preset-env" "^7.27.2" + browserslist "^4.25.0" browserslist-to-esbuild "^2.1.1" - core-js "^3.36.0" - magic-string "^0.30.7" + core-js "^3.43.0" + magic-string "^0.30.17" regenerator-runtime "^0.14.1" - systemjs "^6.14.3" + systemjs "^6.15.1" acorn-jsx@^5.3.2: version "5.3.2" resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.3.2.tgz#7ed5bb55908b3b2f1bc55c6af1653bada7f07937" integrity sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ== -acorn@^8.8.2, acorn@^8.9.0: +acorn@^8.14.0: + version "8.15.0" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.15.0.tgz#a360898bc415edaac46c8241f6383975b930b816" + integrity sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg== + +acorn@^8.9.0: version "8.11.3" resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.11.3.tgz#71e0b14e13a4ec160724b38fb7b0f233b1b81d7a" integrity sha512-Y9rRfJG5jcKOE0CLisYbojUjIrIEE7AGMzA/Sm4BslANhbS+cDMpgBdcPT91oJ7OuJ9hYJBx59RjbhxVnrF8Xg== @@ -1551,13 +1482,6 @@ ansi-regex@^6.0.1: resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-6.0.1.tgz#3183e38fae9a65d7cb5e53945cd5897d0260a06a" integrity sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA== -ansi-styles@^3.2.1: - version "3.2.1" - resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d" - integrity sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA== - dependencies: - color-convert "^1.9.0" - ansi-styles@^4.0.0, ansi-styles@^4.1.0: version "4.3.0" resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-4.3.0.tgz#edd803628ae71c04c85ae7a0906edad34b648937" @@ -1693,15 +1617,15 @@ ast-metadata-inferer@^0.8.0: "@mdn/browser-compat-data" "^5.2.34" autoprefixer@^10.4.19: - version "10.4.19" - resolved "https://registry.yarnpkg.com/autoprefixer/-/autoprefixer-10.4.19.tgz#ad25a856e82ee9d7898c59583c1afeb3fa65f89f" - integrity sha512-BaENR2+zBZ8xXhM4pUaKUxlVdxZ0EZhjvbopwnXmxRUfqDmwSpC2lAi/QXvx7NRdPCo1WKEcEF6mV64si1z4Ew== + version "10.4.21" + resolved "https://registry.yarnpkg.com/autoprefixer/-/autoprefixer-10.4.21.tgz#77189468e7a8ad1d9a37fbc08efc9f480cf0a95d" + integrity sha512-O+A6LWV5LDHSJD3LjHYoNi4VLsj/Whi7k6zG12xTYaU4cQ8oxQGckXNX8cRHK5yOZ/ppVHe0ZBXGzSV9jXdVbQ== dependencies: - browserslist "^4.23.0" - caniuse-lite "^1.0.30001599" + browserslist "^4.24.4" + caniuse-lite "^1.0.30001702" fraction.js "^4.3.7" normalize-range "^0.1.2" - picocolors "^1.0.0" + picocolors "^1.1.1" postcss-value-parser "^4.2.0" available-typed-arrays@^1.0.7: @@ -1716,29 +1640,29 @@ await-lock@^2.2.2: resolved "https://registry.yarnpkg.com/await-lock/-/await-lock-2.2.2.tgz#a95a9b269bfd2f69d22b17a321686f551152bcef" integrity sha512-aDczADvlvTGajTDjcjpJMqRkOF6Qdz3YbPZm/PyW6tKPkx2hlYBzxMhEywM/tU72HrVZjgl5VCdRuMlA7pZ8Gw== -babel-plugin-polyfill-corejs2@^0.4.10: - version "0.4.10" - resolved "https://registry.yarnpkg.com/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.4.10.tgz#276f41710b03a64f6467433cab72cbc2653c38b1" - integrity sha512-rpIuu//y5OX6jVU+a5BCn1R5RSZYWAl2Nar76iwaOdycqb6JPxediskWFMMl7stfwNJR4b7eiQvh5fB5TEQJTQ== +babel-plugin-polyfill-corejs2@^0.4.14: + version "0.4.14" + resolved "https://registry.yarnpkg.com/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.4.14.tgz#8101b82b769c568835611542488d463395c2ef8f" + integrity sha512-Co2Y9wX854ts6U8gAAPXfn0GmAyctHuK8n0Yhfjd6t30g7yvKjspvvOo9yG+z52PZRgFErt7Ka2pYnXCjLKEpg== dependencies: - "@babel/compat-data" "^7.22.6" - "@babel/helper-define-polyfill-provider" "^0.6.1" + "@babel/compat-data" "^7.27.7" + "@babel/helper-define-polyfill-provider" "^0.6.5" semver "^6.3.1" -babel-plugin-polyfill-corejs3@^0.10.4: - version "0.10.4" - resolved "https://registry.yarnpkg.com/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.10.4.tgz#789ac82405ad664c20476d0233b485281deb9c77" - integrity sha512-25J6I8NGfa5YkCDogHRID3fVCadIR8/pGl1/spvCkzb6lVn6SR3ojpx9nOn9iEBcUsjY24AmdKm5khcfKdylcg== +babel-plugin-polyfill-corejs3@^0.13.0: + version "0.13.0" + resolved "https://registry.yarnpkg.com/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.13.0.tgz#bb7f6aeef7addff17f7602a08a6d19a128c30164" + integrity sha512-U+GNwMdSFgzVmfhNm8GJUX88AadB3uo9KpJqS3FaqNIPKgySuvMb+bHPsOmmuWyIcuqZj/pzt1RUIUZns4y2+A== dependencies: - "@babel/helper-define-polyfill-provider" "^0.6.1" - core-js-compat "^3.36.1" + "@babel/helper-define-polyfill-provider" "^0.6.5" + core-js-compat "^3.43.0" -babel-plugin-polyfill-regenerator@^0.6.1: - version "0.6.1" - resolved "https://registry.yarnpkg.com/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.6.1.tgz#4f08ef4c62c7a7f66a35ed4c0d75e30506acc6be" - integrity sha512-JfTApdE++cgcTWjsiCQlLyFBMbTUft9ja17saCc93lgV33h4tuCVj7tlvu//qpLwaG+3yEz7/KhahGrUMkVq9g== +babel-plugin-polyfill-regenerator@^0.6.5: + version "0.6.5" + resolved "https://registry.yarnpkg.com/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.6.5.tgz#32752e38ab6f6767b92650347bf26a31b16ae8c5" + integrity sha512-ISqQ2frbiNU9vIJkzg7dlPpznPZ4jOiUQ1uSmB0fEHeowtN3COYRsXr/xexn64NpU13P06jc/L5TgiJXOgrbEg== dependencies: - "@babel/helper-define-polyfill-provider" "^0.6.1" + "@babel/helper-define-polyfill-provider" "^0.6.5" babel-plugin-transform-hook-names@^1.0.2: version "1.0.2" @@ -1789,7 +1713,7 @@ browserslist-to-esbuild@^2.1.1: dependencies: meow "^13.0.0" -browserslist@^4.21.10, browserslist@^4.22.2, browserslist@^4.23.0: +browserslist@^4.21.10: version "4.23.0" resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.23.0.tgz#8f3acc2bbe73af7213399430890f86c63a5674ab" integrity sha512-QW8HiM1shhT2GuzkvklfjcKDiWFXHOeFCIA/huJPwHsslwcydgk7X+z2zXpEijP98UCY7HbubZt5J2Zgvf0CaQ== @@ -1799,6 +1723,16 @@ browserslist@^4.21.10, browserslist@^4.22.2, browserslist@^4.23.0: node-releases "^2.0.14" update-browserslist-db "^1.0.13" +browserslist@^4.24.0, browserslist@^4.24.4, browserslist@^4.25.0, browserslist@^4.25.1: + version "4.25.1" + resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.25.1.tgz#ba9e8e6f298a1d86f829c9b975e07948967bb111" + integrity sha512-KGj0KoOMXLpSNkkEI6Z6mShmQy0bc1I+T7K9N81k4WWMrfz+6fQ6es80B/YLAeRoKvjYE1YSHHOW1qe9xIVzHw== + dependencies: + caniuse-lite "^1.0.30001726" + electron-to-chromium "^1.5.173" + node-releases "^2.0.19" + update-browserslist-db "^1.1.3" + buffer-from@^1.0.0: version "1.1.2" resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.2.tgz#2b146a6fd72e80b4f55d255f35ed59a3a9a41bd5" @@ -1825,24 +1759,15 @@ camelcase-css@^2.0.1: resolved "https://registry.yarnpkg.com/camelcase-css/-/camelcase-css-2.0.1.tgz#ee978f6947914cc30c6b44741b6ed1df7f043fd5" integrity sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA== -caniuse-lite@^1.0.30001524, caniuse-lite@^1.0.30001587: +caniuse-lite@^1.0.30001524: version "1.0.30001606" resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001606.tgz#b4d5f67ab0746a3b8b5b6d1f06e39c51beb39a9e" integrity sha512-LPbwnW4vfpJId225pwjZJOgX1m9sGfbw/RKJvw/t0QhYOOaTXHvkjVGFGPpvwEzufrjvTlsULnVTxdy4/6cqkg== -caniuse-lite@^1.0.30001599: - version "1.0.30001607" - resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001607.tgz#b91e8e033f6bca4e13d3d45388d87fa88931d9a5" - integrity sha512-WcvhVRjXLKFB/kmOFVwELtMxyhq3iM/MvmXcyCe2PNf166c39mptscOc/45TTS96n2gpNV2z7+NakArTWZCQ3w== - -chalk@^2.4.2: - version "2.4.2" - resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424" - integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ== - dependencies: - ansi-styles "^3.2.1" - escape-string-regexp "^1.0.5" - supports-color "^5.3.0" +caniuse-lite@^1.0.30001587, caniuse-lite@^1.0.30001702, caniuse-lite@^1.0.30001726: + version "1.0.30001727" + resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001727.tgz#22e9706422ad37aa50556af8c10e40e2d93a8b85" + integrity sha512-pB68nIHmbN6L/4C6MH1DokyR3bYqFwjaSs/sWDHGj4CTcFtQUQMuJftVwWkXq7mNWOybD3KhUv3oWHoGxgP14Q== chalk@^4.0.0: version "4.1.2" @@ -1867,13 +1792,6 @@ chokidar@^3.5.3: optionalDependencies: fsevents "~2.3.2" -color-convert@^1.9.0: - version "1.9.3" - resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8" - integrity sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg== - dependencies: - color-name "1.1.3" - color-convert@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-2.0.1.tgz#72d3a68d598c9bdb3af2ad1e84f21d896abd4de3" @@ -1881,11 +1799,6 @@ color-convert@^2.0.1: dependencies: color-name "~1.1.4" -color-name@1.1.3: - version "1.1.3" - resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25" - integrity sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw== - color-name@~1.1.4: version "1.1.4" resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2" @@ -1911,17 +1824,17 @@ convert-source-map@^2.0.0: resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-2.0.0.tgz#4b560f649fc4e918dd0ab75cf4961e8bc882d82a" integrity sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg== -core-js-compat@^3.31.0, core-js-compat@^3.36.1: - version "3.36.1" - resolved "https://registry.yarnpkg.com/core-js-compat/-/core-js-compat-3.36.1.tgz#1818695d72c99c25d621dca94e6883e190cea3c8" - integrity sha512-Dk997v9ZCt3X/npqzyGdTlq6t7lDBhZwGvV94PKzDArjp7BTRm7WlDAXYd/OWdeFHO8OChQYRJNJvUCqCbrtKA== +core-js-compat@^3.43.0: + version "3.44.0" + resolved "https://registry.yarnpkg.com/core-js-compat/-/core-js-compat-3.44.0.tgz#62b9165b97e4cbdb8bca16b14818e67428b4a0f8" + integrity sha512-JepmAj2zfl6ogy34qfWtcE7nHKAJnKsQFRn++scjVS2bZFllwptzw61BZcZFYBPpUznLfAvh0LGhxKppk04ClA== dependencies: - browserslist "^4.23.0" + browserslist "^4.25.1" -core-js@^3.36.0: - version "3.36.1" - resolved "https://registry.yarnpkg.com/core-js/-/core-js-3.36.1.tgz#c97a7160ebd00b2de19e62f4bbd3406ab720e578" - integrity sha512-BTvUrwxVBezj5SZ3f10ImnX2oRByMxql3EimVqMysepbC9EeMUOpLwdy6Eoili2x6E4kf+ZUB5k/+Jv55alPfA== +core-js@^3.43.0: + version "3.44.0" + resolved "https://registry.yarnpkg.com/core-js/-/core-js-3.44.0.tgz#db4fd4fa07933c1d6898c8b112a1119a9336e959" + integrity sha512-aFCtd4l6GvAXwVEh3XbbVqJGHDJt0OZRa+5ePGx3LLwi12WfexqQxcsohb2wgsa/92xtl19Hd66G/L+TaAxDMw== cross-spawn@^7.0.0, cross-spawn@^7.0.2: version "7.0.3" @@ -1933,9 +1846,9 @@ cross-spawn@^7.0.0, cross-spawn@^7.0.2: which "^2.0.1" css-select@^5.1.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/css-select/-/css-select-5.1.0.tgz#b8ebd6554c3637ccc76688804ad3f6a6fdaea8a6" - integrity sha512-nwoRF1rvRRnnCqqY7updORDsuqKzqYJ28+oSMaJMMgOauh3fvwHqMS7EZpIPqK8GL+g9mKxF1vP/ZjSeNjEVHg== + version "5.2.2" + resolved "https://registry.yarnpkg.com/css-select/-/css-select-5.2.2.tgz#01b6e8d163637bb2dd6c982ca4ed65863682786e" + integrity sha512-TizTzUddG/xYLA3NXodFM0fSbNizXjOKhqiQQwvhlspadZokn1KDy0NZFS0wuEubIYAV5/c1/lAr0TaaFXEXzw== dependencies: boolbase "^1.0.0" css-what "^6.1.0" @@ -1944,9 +1857,9 @@ css-select@^5.1.0: nth-check "^2.0.1" css-what@^6.1.0: - version "6.1.0" - resolved "https://registry.yarnpkg.com/css-what/-/css-what-6.1.0.tgz#fb5effcf76f1ddea2c81bdfaa4de44e79bac70f4" - integrity sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw== + version "6.2.2" + resolved "https://registry.yarnpkg.com/css-what/-/css-what-6.2.2.tgz#cdcc8f9b6977719fdfbd1de7aec24abf756b9dea" + integrity sha512-u/O3vwbptzhMs3L1fQE82ZSLHQQfto5gyZzwteVIEyeaY5Fc7R4dapF/BvRoSYFeqfBk4m0V1Vafq5Pjv25wvA== cssesc@^3.0.0: version "3.0.0" @@ -1980,7 +1893,14 @@ data-view-byte-offset@^1.0.0: es-errors "^1.3.0" is-data-view "^1.0.1" -debug@^4.1.0, debug@^4.1.1, debug@^4.3.1, debug@^4.3.2, debug@^4.3.4: +debug@^4.1.0, debug@^4.1.1, debug@^4.3.1, debug@^4.3.4, debug@^4.4.1: + version "4.4.1" + resolved "https://registry.yarnpkg.com/debug/-/debug-4.4.1.tgz#e5a8bc6cbc4c6cd3e64308b0693a3d4fa550189b" + integrity sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ== + dependencies: + ms "^2.1.3" + +debug@^4.3.2: version "4.3.4" resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.4.tgz#1319f6579357f2338d3337d2cdd4914bb5dcc865" integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ== @@ -2063,9 +1983,9 @@ domhandler@^5.0.2, domhandler@^5.0.3: domelementtype "^2.3.0" domutils@^3.0.1: - version "3.1.0" - resolved "https://registry.yarnpkg.com/domutils/-/domutils-3.1.0.tgz#c47f551278d3dc4b0b1ab8cbb42d751a6f0d824e" - integrity sha512-H78uMmQtI2AhgDJjWeQmHwJJ2bLPD3GMmO7Zja/ZZh84wkm+4ut+IUnUdRa8uCGX88DiVx1j6FRe1XfxEgjEZA== + version "3.2.2" + resolved "https://registry.yarnpkg.com/domutils/-/domutils-3.2.2.tgz#edbfe2b668b0c1d97c24baf0f1062b132221bc78" + integrity sha512-6kZKyUajlDuqlHKVX1w7gyslj9MPIXzIFiz/rGu35uC1wMi+kMhQwGhl4lt9unC9Vb9INnY9Z3/ZA3+FhASLaw== dependencies: dom-serializer "^2.0.0" domelementtype "^2.3.0" @@ -2076,10 +1996,10 @@ eastasianwidth@^0.2.0: resolved "https://registry.yarnpkg.com/eastasianwidth/-/eastasianwidth-0.2.0.tgz#696ce2ec0aa0e6ea93a397ffcf24aa7840c827cb" integrity sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA== -electron-to-chromium@^1.4.668: - version "1.4.728" - resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.728.tgz#ac54d9d1b38752b920ec737a48c83dec2bf45ea1" - integrity sha512-Ud1v7hJJYIqehlUJGqR6PF1Ek8l80zWwxA6nGxigBsGJ9f9M2fciHyrIiNMerSHSH3p+0/Ia7jIlnDkt41h5cw== +electron-to-chromium@^1.4.668, electron-to-chromium@^1.5.173: + version "1.5.182" + resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.5.182.tgz#4ab73104f893938acb3ab9c28d7bec170c116b3e" + integrity sha512-Lv65Btwv9W4J9pyODI6EWpdnhfvrve/us5h1WspW8B2Fb0366REPtY3hX7ounk1CkV/TBjWCEvCBBbYbmV0qCA== emoji-regex@^8.0.0: version "8.0.0" @@ -2212,44 +2132,42 @@ es-to-primitive@^1.2.1: is-date-object "^1.0.1" is-symbol "^1.0.2" -esbuild@^0.20.1: - version "0.20.2" - resolved "https://registry.yarnpkg.com/esbuild/-/esbuild-0.20.2.tgz#9d6b2386561766ee6b5a55196c6d766d28c87ea1" - integrity sha512-WdOOppmUNU+IbZ0PaDiTst80zjnrOkyJNHoKupIcVyU8Lvla3Ugx94VzkQ32Ijqd7UhHJy75gNWDMUekcrSJ6g== +esbuild@^0.25.0: + version "0.25.6" + resolved "https://registry.yarnpkg.com/esbuild/-/esbuild-0.25.6.tgz#9b82a3db2fa131aec069ab040fd57ed0a880cdcd" + integrity sha512-GVuzuUwtdsghE3ocJ9Bs8PNoF13HNQ5TXbEi2AhvVb8xU1Iwt9Fos9FEamfoee+u/TOsn7GUWc04lz46n2bbTg== optionalDependencies: - "@esbuild/aix-ppc64" "0.20.2" - "@esbuild/android-arm" "0.20.2" - "@esbuild/android-arm64" "0.20.2" - "@esbuild/android-x64" "0.20.2" - "@esbuild/darwin-arm64" "0.20.2" - "@esbuild/darwin-x64" "0.20.2" - "@esbuild/freebsd-arm64" "0.20.2" - "@esbuild/freebsd-x64" "0.20.2" - "@esbuild/linux-arm" "0.20.2" - "@esbuild/linux-arm64" "0.20.2" - "@esbuild/linux-ia32" "0.20.2" - "@esbuild/linux-loong64" "0.20.2" - "@esbuild/linux-mips64el" "0.20.2" - "@esbuild/linux-ppc64" "0.20.2" - "@esbuild/linux-riscv64" "0.20.2" - "@esbuild/linux-s390x" "0.20.2" - "@esbuild/linux-x64" "0.20.2" - "@esbuild/netbsd-x64" "0.20.2" - "@esbuild/openbsd-x64" "0.20.2" - "@esbuild/sunos-x64" "0.20.2" - "@esbuild/win32-arm64" "0.20.2" - "@esbuild/win32-ia32" "0.20.2" - "@esbuild/win32-x64" "0.20.2" + "@esbuild/aix-ppc64" "0.25.6" + "@esbuild/android-arm" "0.25.6" + "@esbuild/android-arm64" "0.25.6" + "@esbuild/android-x64" "0.25.6" + "@esbuild/darwin-arm64" "0.25.6" + "@esbuild/darwin-x64" "0.25.6" + "@esbuild/freebsd-arm64" "0.25.6" + "@esbuild/freebsd-x64" "0.25.6" + "@esbuild/linux-arm" "0.25.6" + "@esbuild/linux-arm64" "0.25.6" + "@esbuild/linux-ia32" "0.25.6" + "@esbuild/linux-loong64" "0.25.6" + "@esbuild/linux-mips64el" "0.25.6" + "@esbuild/linux-ppc64" "0.25.6" + "@esbuild/linux-riscv64" "0.25.6" + "@esbuild/linux-s390x" "0.25.6" + "@esbuild/linux-x64" "0.25.6" + "@esbuild/netbsd-arm64" "0.25.6" + "@esbuild/netbsd-x64" "0.25.6" + "@esbuild/openbsd-arm64" "0.25.6" + "@esbuild/openbsd-x64" "0.25.6" + "@esbuild/openharmony-arm64" "0.25.6" + "@esbuild/sunos-x64" "0.25.6" + "@esbuild/win32-arm64" "0.25.6" + "@esbuild/win32-ia32" "0.25.6" + "@esbuild/win32-x64" "0.25.6" -escalade@^3.1.1: - version "3.1.2" - resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.1.2.tgz#54076e9ab29ea5bf3d8f1ed62acffbb88272df27" - integrity sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA== - -escape-string-regexp@^1.0.5: - version "1.0.5" - resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" - integrity sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg== +escalade@^3.2.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.2.0.tgz#011a3f69856ba189dffa7dc8fcce99d2a87903e5" + integrity sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA== escape-string-regexp@^4.0.0: version "4.0.0" @@ -2471,6 +2389,11 @@ fastq@^1.6.0: dependencies: reusify "^1.0.4" +fdir@^6.4.4, fdir@^6.4.6: + version "6.4.6" + resolved "https://registry.yarnpkg.com/fdir/-/fdir-6.4.6.tgz#2b268c0232697063111bbf3f64810a2a741ba281" + integrity sha512-hiFoqpyZcfNm1yc4u8oWCf9A2c4D3QjCrks3zmoVKVxpQRzmPNar1hUJcBG2RQHvEVGDN+Jm81ZheVLAQMK6+w== + file-entry-cache@^6.0.1: version "6.0.1" resolved "https://registry.yarnpkg.com/file-entry-cache/-/file-entry-cache-6.0.1.tgz#211b2dd9659cb0394b073e7323ac3c933d522027" @@ -2619,11 +2542,6 @@ glob@^7.1.3: once "^1.3.0" path-is-absolute "^1.0.0" -globals@^11.1.0: - version "11.12.0" - resolved "https://registry.yarnpkg.com/globals/-/globals-11.12.0.tgz#ab8795338868a0babd8525758018c2a7eb95c42e" - integrity sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA== - globals@^13.19.0: version "13.24.0" resolved "https://registry.yarnpkg.com/globals/-/globals-13.24.0.tgz#8432a19d78ce0c1e833949c36adb345400bb1171" @@ -2672,11 +2590,6 @@ has-bigints@^1.0.1, has-bigints@^1.0.2: resolved "https://registry.yarnpkg.com/has-bigints/-/has-bigints-1.0.2.tgz#0871bd3e3d51626f6ca0966668ba35d5602d6eaa" integrity sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ== -has-flag@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd" - integrity sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw== - has-flag@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b" @@ -2807,6 +2720,13 @@ is-core-module@^2.13.0: dependencies: hasown "^2.0.0" +is-core-module@^2.16.0: + version "2.16.1" + resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.16.1.tgz#2a98801a849f43e2add644fbb6bc6229b19a4ef4" + integrity sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w== + dependencies: + hasown "^2.0.2" + is-data-view@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/is-data-view/-/is-data-view-1.0.1.tgz#4b4d3a511b70f3dc26d42c03ca9ca515d847759f" @@ -2992,15 +2912,15 @@ js-yaml@^4.1.0: dependencies: argparse "^2.0.1" -jsesc@^2.5.1: - version "2.5.2" - resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-2.5.2.tgz#80564d2e483dacf6e8ef209650a67df3f0c283a4" - integrity sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA== +jsesc@^3.0.2: + version "3.1.0" + resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-3.1.0.tgz#74d335a234f67ed19907fdadfac7ccf9d409825d" + integrity sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA== -jsesc@~0.5.0: - version "0.5.0" - resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-0.5.0.tgz#e7dee66e35d6fc16f710fe91d5cf69f70f08911d" - integrity sha512-uZz5UnB7u4T9LvwmFqXii7pZSouaRPorGs5who1Ip7VO0wxanFvBL7GkM6dTHlgX+jhBApRetaWpnDabOeTcnA== +jsesc@~3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-3.0.2.tgz#bb8b09a6597ba426425f2e4a07245c3d00b9343e" + integrity sha512-xKqzzWXDttJuOcawBt4KnKHHIf5oQ/Cxax+0PWFG+DFDgHNAdi+TXECADI+RYiFUMmx8792xsMbbgXj4CwnP4g== json-buffer@3.0.1: version "3.0.1" @@ -3039,7 +2959,7 @@ keyv@^4.5.3: dependencies: json-buffer "3.0.1" -kolorist@^1.8.0: +kolorist@^1.6.0, kolorist@^1.8.0: version "1.8.0" resolved "https://registry.yarnpkg.com/kolorist/-/kolorist-1.8.0.tgz#edddbbbc7894bc13302cdf740af6374d4a04743c" integrity sha512-Y+60/zizpJ3HRH8DCss+q95yr6145JXZo46OTpFvDZWLfRCE4qChOyk1b26nMaNpfHHgxagk9dXT5OP0Tfe+dQ== @@ -3115,19 +3035,12 @@ lru-cache@^6.0.0: dependencies: yallist "^4.0.0" -magic-string@0.30.5: - version "0.30.5" - resolved "https://registry.yarnpkg.com/magic-string/-/magic-string-0.30.5.tgz#1994d980bd1c8835dc6e78db7cbd4ae4f24746f9" - integrity sha512-7xlpfBaQaP/T6Vh8MO/EqXSW5En6INHEvEXQiuff7Gku0PWjU3uf6w/j9o7O+SpB5fOAkrI5HeoNgwjEO0pFsA== +"magic-string@0.x >= 0.26.0", magic-string@^0.30.17: + version "0.30.17" + resolved "https://registry.yarnpkg.com/magic-string/-/magic-string-0.30.17.tgz#450a449673d2460e5bbcfba9a61916a1714c7453" + integrity sha512-sNPKHvyjVf7gyjwS4xGTaW/mCnF8wnjtifKBEhxfZ7E/S8tQ0rssrwGNn6q8JH/ohItJfSQp9mBtQYuTlH5QnA== dependencies: - "@jridgewell/sourcemap-codec" "^1.4.15" - -magic-string@^0.30.7: - version "0.30.9" - resolved "https://registry.yarnpkg.com/magic-string/-/magic-string-0.30.9.tgz#8927ae21bfdd856310e07a1bc8dd5e73cb6c251d" - integrity sha512-S1+hd+dIrC8EZqKyT9DstTH/0Z+f76kmmvZnkfQVmOpDEF9iVgdYif3Q/pIWHmCoo59bQVGW0kVL3e2nl+9+Sw== - dependencies: - "@jridgewell/sourcemap-codec" "^1.4.15" + "@jridgewell/sourcemap-codec" "^1.5.0" meow@^13.0.0: version "13.2.0" @@ -3171,6 +3084,11 @@ ms@2.1.2: resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== +ms@^2.1.3: + version "2.1.3" + resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2" + integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA== + multiformats@^9.4.2, multiformats@^9.9.0: version "9.9.0" resolved "https://registry.yarnpkg.com/multiformats/-/multiformats-9.9.0.tgz#c68354e7d21037a8f1f8833c8ccd68618e8f1d37" @@ -3185,6 +3103,11 @@ mz@^2.7.0: object-assign "^4.0.1" thenify-all "^1.0.0" +nanoid@^3.3.11: + version "3.3.11" + resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.11.tgz#4f4f112cefbe303202f2199838128936266d185b" + integrity sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w== + nanoid@^3.3.7: version "3.3.7" resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.7.tgz#d0c301a691bc8d54efa0a2226ccf3fe2fd656bd8" @@ -3195,7 +3118,7 @@ natural-compare@^1.4.0: resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7" integrity sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw== -node-html-parser@^6.1.10: +node-html-parser@^6.1.12: version "6.1.13" resolved "https://registry.yarnpkg.com/node-html-parser/-/node-html-parser-6.1.13.tgz#a1df799b83df5c6743fcd92740ba14682083b7e4" integrity sha512-qIsTMOY4C/dAa5Q5vsobRpOOvPfC4pB61UVW2uSwZNUp0QU/jCekTal1vMmbO0DgdHeLUJpv/ARmDqErVxA3Sg== @@ -3203,10 +3126,10 @@ node-html-parser@^6.1.10: css-select "^5.1.0" he "1.2.0" -node-releases@^2.0.14: - version "2.0.14" - resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.14.tgz#2ffb053bceb8b2be8495ece1ab6ce600c4461b0b" - integrity sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw== +node-releases@^2.0.14, node-releases@^2.0.19: + version "2.0.19" + resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.19.tgz#9e445a52950951ec4d177d843af370b411caf314" + integrity sha512-xxOWJsBKtzAq7DY0J+DTzuz58K8e7sJbdgwkbMWQe8UYB6ekmsQ45q0M/tJDsGaZmbC+l7n57UV8Hl5tHxO9uw== normalize-path@^3.0.0, normalize-path@~3.0.0: version "3.0.0" @@ -3365,16 +3288,21 @@ path-type@^4.0.0: resolved "https://registry.yarnpkg.com/path-type/-/path-type-4.0.0.tgz#84ed01c0a7ba380afe09d90a8c180dcd9d03043b" integrity sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw== -picocolors@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.0.0.tgz#cb5bdc74ff3f51892236eaf79d68bc44564ab81c" - integrity sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ== +picocolors@^1.0.0, picocolors@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.1.1.tgz#3d321af3eab939b083c8f929a1d12cda81c26b6b" + integrity sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA== picomatch@^2.0.4, picomatch@^2.2.1, picomatch@^2.2.2, picomatch@^2.3.1: version "2.3.1" resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.1.tgz#3ba3833733646d9d3e4995946c1365a67fb07a42" integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA== +picomatch@^4.0.2: + version "4.0.2" + resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-4.0.2.tgz#77c742931e8f3b8820946c76cd0c1f13730d1dab" + integrity sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg== + pify@^2.3.0: version "2.3.0" resolved "https://registry.yarnpkg.com/pify/-/pify-2.3.0.tgz#ed141a6ac043a849ea588498e7dca8b15330e90c" @@ -3443,6 +3371,15 @@ postcss@^8.4.23, postcss@^8.4.38: picocolors "^1.0.0" source-map-js "^1.2.0" +postcss@^8.5.6: + version "8.5.6" + resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.5.6.tgz#2825006615a619b4f62a9e7426cc120b349a8f3c" + integrity sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg== + dependencies: + nanoid "^3.3.11" + picocolors "^1.1.1" + source-map-js "^1.2.1" + preact@^10.4.8: version "10.20.1" resolved "https://registry.yarnpkg.com/preact/-/preact-10.20.1.tgz#1bc598ab630d8612978f7533da45809a8298542b" @@ -3504,10 +3441,10 @@ reflect.getprototypeof@^1.0.4: globalthis "^1.0.3" which-builtin-type "^1.1.3" -regenerate-unicode-properties@^10.1.0: - version "10.1.1" - resolved "https://registry.yarnpkg.com/regenerate-unicode-properties/-/regenerate-unicode-properties-10.1.1.tgz#6b0e05489d9076b04c436f318d9b067bba459480" - integrity sha512-X007RyZLsCJVVrjgEFVpLUTZwyOZk3oiL75ZcuYjlIWd6rNJtOjkBwQc5AsRrpbKVkxN6sklw/k/9m2jJYOf8Q== +regenerate-unicode-properties@^10.2.0: + version "10.2.0" + resolved "https://registry.yarnpkg.com/regenerate-unicode-properties/-/regenerate-unicode-properties-10.2.0.tgz#626e39df8c372338ea9b8028d1f99dc3fd9c3db0" + integrity sha512-DqHn3DwbmmPVzeKj9woBadqmXxLvQoQIwu7nopMc72ztvxVmVk2SBhSnx67zuye5TP+lJsb/TBQsjLKhnDf3MA== dependencies: regenerate "^1.4.2" @@ -3516,18 +3453,11 @@ regenerate@^1.4.2: resolved "https://registry.yarnpkg.com/regenerate/-/regenerate-1.4.2.tgz#b9346d8827e8f5a32f7ba29637d398b69014848a" integrity sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A== -regenerator-runtime@^0.14.0, regenerator-runtime@^0.14.1: +regenerator-runtime@^0.14.1: version "0.14.1" resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz#356ade10263f685dda125100cd862c1db895327f" integrity sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw== -regenerator-transform@^0.15.2: - version "0.15.2" - resolved "https://registry.yarnpkg.com/regenerator-transform/-/regenerator-transform-0.15.2.tgz#5bbae58b522098ebdf09bca2f83838929001c7a4" - integrity sha512-hfMp2BoF0qOk3uc5V20ALGDS2ddjQaLrdl7xrGXvAIow7qeWRM2VA2HuCHkUKk9slq3VwEwLNK3DFBqDfPGYtg== - dependencies: - "@babel/runtime" "^7.8.4" - regexp.prototype.flags@^1.5.2: version "1.5.2" resolved "https://registry.yarnpkg.com/regexp.prototype.flags/-/regexp.prototype.flags-1.5.2.tgz#138f644a3350f981a858c44f6bb1a61ff59be334" @@ -3538,31 +3468,36 @@ regexp.prototype.flags@^1.5.2: es-errors "^1.3.0" set-function-name "^2.0.1" -regexpu-core@^5.3.1: - version "5.3.2" - resolved "https://registry.yarnpkg.com/regexpu-core/-/regexpu-core-5.3.2.tgz#11a2b06884f3527aec3e93dbbf4a3b958a95546b" - integrity sha512-RAM5FlZz+Lhmo7db9L298p2vHP5ZywrVXmVXpmAD9GuL5MPH6t9ROw1iA/wfHkQ76Qe7AaPF0nGuim96/IrQMQ== +regexpu-core@^6.2.0: + version "6.2.0" + resolved "https://registry.yarnpkg.com/regexpu-core/-/regexpu-core-6.2.0.tgz#0e5190d79e542bf294955dccabae04d3c7d53826" + integrity sha512-H66BPQMrv+V16t8xtmq+UC0CBpiTBA60V8ibS1QVReIp8T1z8hwFxqcGzm9K6lgsN7sB5edVH8a+ze6Fqm4weA== dependencies: - "@babel/regjsgen" "^0.8.0" regenerate "^1.4.2" - regenerate-unicode-properties "^10.1.0" - regjsparser "^0.9.1" + regenerate-unicode-properties "^10.2.0" + regjsgen "^0.8.0" + regjsparser "^0.12.0" unicode-match-property-ecmascript "^2.0.0" unicode-match-property-value-ecmascript "^2.1.0" -regjsparser@^0.9.1: - version "0.9.1" - resolved "https://registry.yarnpkg.com/regjsparser/-/regjsparser-0.9.1.tgz#272d05aa10c7c1f67095b1ff0addae8442fc5709" - integrity sha512-dQUtn90WanSNl+7mQKcXAgZxvUe7Z0SqXlgzv0za4LwiUhyzBC58yQO3liFoUgu8GiJVInAhJjkj1N0EtQ5nkQ== +regjsgen@^0.8.0: + version "0.8.0" + resolved "https://registry.yarnpkg.com/regjsgen/-/regjsgen-0.8.0.tgz#df23ff26e0c5b300a6470cad160a9d090c3a37ab" + integrity sha512-RvwtGe3d7LvWiDQXeQw8p5asZUmfU1G/l6WbUXeHta7Y2PEIvBTwH6E2EfmYUK8pxcxEdEmaomqyp0vZZ7C+3Q== + +regjsparser@^0.12.0: + version "0.12.0" + resolved "https://registry.yarnpkg.com/regjsparser/-/regjsparser-0.12.0.tgz#0e846df6c6530586429377de56e0475583b088dc" + integrity sha512-cnE+y8bz4NhMjISKbgeVJtqNbtf5QpjZP+Bslo+UqkIt9QPnX9q095eiRRASJG1/tz6dlNr6Z5NsBiWYokp6EQ== dependencies: - jsesc "~0.5.0" + jsesc "~3.0.2" resolve-from@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-4.0.0.tgz#4abcd852ad32dd7baabfe9b40e00a36db5f392e6" integrity sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g== -resolve@^1.1.7, resolve@^1.14.2, resolve@^1.22.2, resolve@^1.22.8: +resolve@^1.1.7, resolve@^1.22.2: version "1.22.8" resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.8.tgz#b6c87a9f2aa06dfab52e3d70ac8cde321fa5a48d" integrity sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw== @@ -3571,6 +3506,15 @@ resolve@^1.1.7, resolve@^1.14.2, resolve@^1.22.2, resolve@^1.22.8: path-parse "^1.0.7" supports-preserve-symlinks-flag "^1.0.0" +resolve@^1.22.10: + version "1.22.10" + resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.10.tgz#b663e83ffb09bbf2386944736baae803029b8b39" + integrity sha512-NPRy+/ncIMeDlTAsuqwKIiferiawhefFJtkNSW0qZJEqMEb+qBt/77B/jGeeek+F0uOeN05CDa6HXbbIgtVX4w== + dependencies: + is-core-module "^2.16.0" + path-parse "^1.0.7" + supports-preserve-symlinks-flag "^1.0.0" + resolve@^2.0.0-next.5: version "2.0.0-next.5" resolved "https://registry.yarnpkg.com/resolve/-/resolve-2.0.0-next.5.tgz#6b0ec3107e671e52b68cd068ef327173b90dc03c" @@ -3592,28 +3536,33 @@ rimraf@^3.0.2: dependencies: glob "^7.1.3" -rollup@^4.13.0: - version "4.14.1" - resolved "https://registry.yarnpkg.com/rollup/-/rollup-4.14.1.tgz#228d5159c3f4d8745bd24819d734bc6c6ca87c09" - integrity sha512-4LnHSdd3QK2pa1J6dFbfm1HN0D7vSK/ZuZTsdyUAlA6Rr1yTouUTL13HaDOGJVgby461AhrNGBS7sCGXXtT+SA== +rollup@^4.40.0: + version "4.45.0" + resolved "https://registry.yarnpkg.com/rollup/-/rollup-4.45.0.tgz#92d1b164eca1c6f2cb399ae7a1a8ee78967b6e33" + integrity sha512-WLjEcJRIo7i3WDDgOIJqVI2d+lAC3EwvOGy+Xfq6hs+GQuAA4Di/H72xmXkOhrIWFg2PFYSKZYfH0f4vfKXN4A== dependencies: - "@types/estree" "1.0.5" + "@types/estree" "1.0.8" optionalDependencies: - "@rollup/rollup-android-arm-eabi" "4.14.1" - "@rollup/rollup-android-arm64" "4.14.1" - "@rollup/rollup-darwin-arm64" "4.14.1" - "@rollup/rollup-darwin-x64" "4.14.1" - "@rollup/rollup-linux-arm-gnueabihf" "4.14.1" - "@rollup/rollup-linux-arm64-gnu" "4.14.1" - "@rollup/rollup-linux-arm64-musl" "4.14.1" - "@rollup/rollup-linux-powerpc64le-gnu" "4.14.1" - "@rollup/rollup-linux-riscv64-gnu" "4.14.1" - "@rollup/rollup-linux-s390x-gnu" "4.14.1" - "@rollup/rollup-linux-x64-gnu" "4.14.1" - "@rollup/rollup-linux-x64-musl" "4.14.1" - "@rollup/rollup-win32-arm64-msvc" "4.14.1" - "@rollup/rollup-win32-ia32-msvc" "4.14.1" - "@rollup/rollup-win32-x64-msvc" "4.14.1" + "@rollup/rollup-android-arm-eabi" "4.45.0" + "@rollup/rollup-android-arm64" "4.45.0" + "@rollup/rollup-darwin-arm64" "4.45.0" + "@rollup/rollup-darwin-x64" "4.45.0" + "@rollup/rollup-freebsd-arm64" "4.45.0" + "@rollup/rollup-freebsd-x64" "4.45.0" + "@rollup/rollup-linux-arm-gnueabihf" "4.45.0" + "@rollup/rollup-linux-arm-musleabihf" "4.45.0" + "@rollup/rollup-linux-arm64-gnu" "4.45.0" + "@rollup/rollup-linux-arm64-musl" "4.45.0" + "@rollup/rollup-linux-loongarch64-gnu" "4.45.0" + "@rollup/rollup-linux-powerpc64le-gnu" "4.45.0" + "@rollup/rollup-linux-riscv64-gnu" "4.45.0" + "@rollup/rollup-linux-riscv64-musl" "4.45.0" + "@rollup/rollup-linux-s390x-gnu" "4.45.0" + "@rollup/rollup-linux-x64-gnu" "4.45.0" + "@rollup/rollup-linux-x64-musl" "4.45.0" + "@rollup/rollup-win32-arm64-msvc" "4.45.0" + "@rollup/rollup-win32-ia32-msvc" "4.45.0" + "@rollup/rollup-win32-x64-msvc" "4.45.0" fsevents "~2.3.2" run-parallel@^1.1.9: @@ -3703,6 +3652,13 @@ signal-exit@^4.0.1: resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-4.1.0.tgz#952188c1cbd546070e2dd20d0f41c0ae0530cb04" integrity sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw== +simple-code-frame@^1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/simple-code-frame/-/simple-code-frame-1.3.0.tgz#11dd319656a09445639b9c26a0fcb7102c0de00e" + integrity sha512-MB4pQmETUBlNs62BBeRjIFGeuy/x6gGKh7+eRUemn1rCFhqo7K+4slPqsyizCbcbYLnaYqaoZ2FWsZ/jN06D8w== + dependencies: + kolorist "^1.6.0" + slash@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/slash/-/slash-3.0.0.tgz#6539be870c165adbd5240220dbe361f1bc4d4634" @@ -3713,6 +3669,11 @@ source-map-js@^1.2.0: resolved "https://registry.yarnpkg.com/source-map-js/-/source-map-js-1.2.0.tgz#16b809c162517b5b8c3e7dcd315a2a5c2612b2af" integrity sha512-itJW8lvSA0TXEphiRoawsCksnlf8SyvmFzIhltqAHluXd88pkCd+cXJVHTDwdCr0IzwptSm035IHQktUu1QUMg== +source-map-js@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/source-map-js/-/source-map-js-1.2.1.tgz#1ce5650fddd87abc099eda37dcff024c2667ae46" + integrity sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA== + source-map-support@~0.5.20: version "0.5.21" resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.21.tgz#04fe7c7f9e1ed2d662233c28cb2b35b9f63f6e4f" @@ -3848,13 +3809,6 @@ sucrase@^3.32.0: pirates "^4.0.1" ts-interface-checker "^0.1.9" -supports-color@^5.3.0: - version "5.5.0" - resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f" - integrity sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow== - dependencies: - has-flag "^3.0.0" - supports-color@^7.1.0: version "7.2.0" resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-7.2.0.tgz#1b7dcdcb32b8138801b3e478ba6a51caa89648da" @@ -3867,10 +3821,10 @@ supports-preserve-symlinks-flag@^1.0.0: resolved "https://registry.yarnpkg.com/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz#6eda4bd344a3c94aea376d4cc31bc77311039e09" integrity sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w== -systemjs@^6.14.3: - version "6.14.3" - resolved "https://registry.yarnpkg.com/systemjs/-/systemjs-6.14.3.tgz#c1d6e4ff5f9ff7106e5bb3d451360b1a066bde8a" - integrity sha512-hQv45irdhXudAOr8r6SVSpJSGtogdGZUbJBRKCE5nsIS7tsxxvnIHqT4IOPWj+P+HcSzeWzHlGCGpmhPDIKe+w== +systemjs@^6.15.1: + version "6.15.1" + resolved "https://registry.yarnpkg.com/systemjs/-/systemjs-6.15.1.tgz#74175b6810e27a79e1177d21db5f0e3057118cea" + integrity sha512-Nk8c4lXvMB98MtbmjX7JwJRgJOL8fluecYCfCeYBznwmpOs8Bf15hLM6z4z71EDAhQVrQrI+wt1aLWSXZq+hXA== tailwindcss@^3.4.3: version "3.4.3" @@ -3900,13 +3854,13 @@ tailwindcss@^3.4.3: resolve "^1.22.2" sucrase "^3.32.0" -terser@^5.30.3: - version "5.30.3" - resolved "https://registry.yarnpkg.com/terser/-/terser-5.30.3.tgz#f1bb68ded42408c316b548e3ec2526d7dd03f4d2" - integrity sha512-STdUgOUx8rLbMGO9IOwHLpCqolkDITFFQSMYYwKE1N2lY6MVSaeoi10z/EhWxRc6ybqoVmKSkhKYH/XUpl7vSA== +terser@^5.43.1: + version "5.43.1" + resolved "https://registry.yarnpkg.com/terser/-/terser-5.43.1.tgz#88387f4f9794ff1a29e7ad61fb2932e25b4fdb6d" + integrity sha512-+6erLbBm0+LROX2sPXlUYx/ux5PyE9K/a92Wrt6oA+WDAoFTdpHE5tCYCI5PNzq2y8df4rA+QgHLJuR4jNymsg== dependencies: "@jridgewell/source-map" "^0.3.3" - acorn "^8.8.2" + acorn "^8.14.0" commander "^2.20.0" source-map-support "~0.5.20" @@ -3929,16 +3883,19 @@ thenify-all@^1.0.0: dependencies: any-promise "^1.0.0" +tinyglobby@^0.2.14: + version "0.2.14" + resolved "https://registry.yarnpkg.com/tinyglobby/-/tinyglobby-0.2.14.tgz#5280b0cf3f972b050e74ae88406c0a6a58f4079d" + integrity sha512-tX5e7OM1HnYr2+a2C/4V0htOcSQcoSTH9KgJnVvNm5zm/cyEWKJ7j7YutsH9CxMdtOkkLFy2AHrMci9IM8IPZQ== + dependencies: + fdir "^6.4.4" + picomatch "^4.0.2" + tlds@^1.234.0: version "1.252.0" resolved "https://registry.yarnpkg.com/tlds/-/tlds-1.252.0.tgz#71d9617f4ef4cc7347843bee72428e71b8b0f419" integrity sha512-GA16+8HXvqtfEnw/DTcwB0UU354QE1n3+wh08oFjr6Znl7ZLAeUgYzCcK+/CCrOyE0vnHR8/pu3XXG3vDijXpQ== -to-fast-properties@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-2.0.0.tgz#dc5e698cbd079265bc73e0377681a4e4e83f616e" - integrity sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog== - to-regex-range@^5.0.1: version "5.0.1" resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-5.0.1.tgz#1648c44aae7c8d988a326018ed72f5b4dd0392e4" @@ -3952,9 +3909,9 @@ ts-interface-checker@^0.1.9: integrity sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA== tsconfck@^3.0.3: - version "3.0.3" - resolved "https://registry.yarnpkg.com/tsconfck/-/tsconfck-3.0.3.tgz#d9bda0e87d05b1c360e996c9050473c7e6f8084f" - integrity sha512-4t0noZX9t6GcPTfBAbIbbIU4pfpCwh0ueq3S4O/5qXI1VwK1outmxhe9dOiEWqMz3MW2LKgDTpqWV+37IWuVbA== + version "3.1.6" + resolved "https://registry.yarnpkg.com/tsconfck/-/tsconfck-3.1.6.tgz#da1f0b10d82237ac23422374b3fce1edb23c3ead" + integrity sha512-ks6Vjr/jEw0P1gmOVwutM3B7fWxoWBL2KRDb1JfqGVawBmO5UsvmWOQFGHBPl5yxYz4eERr19E6L7NMv+Fej4w== tslib@^1.8.1: version "1.14.1" @@ -4024,10 +3981,10 @@ typed-array-length@^1.0.6: is-typed-array "^1.1.13" possible-typed-array-names "^1.0.0" -typescript@^5.5.4: - version "5.5.4" - resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.5.4.tgz#d9852d6c82bad2d2eda4fd74a5762a8f5909e9ba" - integrity sha512-Mtq29sKDAEYP7aljRgtPOpTvOfbwRWlS6dPRzwjdE+C0R4brX/GUyhHSecbHMFLNBLcJIPt9nl9yG5TZ1weH+Q== +typescript@^5.8.3: + version "5.8.3" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.8.3.tgz#92f8a3e5e3cf497356f4178c34cd65a7f5e8440e" + integrity sha512-p1diW6TqL9L07nNxvRMM7hMMw4c5XOo/1ibL4aAIGmSAt9slTE1Xgw5KWuof2uTOvCg9BY7ZRi+GaF+7sfgPeQ== uint8arrays@3.0.0: version "3.0.0" @@ -4047,9 +4004,9 @@ unbox-primitive@^1.0.2: which-boxed-primitive "^1.0.2" unicode-canonical-property-names-ecmascript@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-2.0.0.tgz#301acdc525631670d39f6146e0e77ff6bbdebddc" - integrity sha512-yY5PpDlfVIU5+y/BSCxAJRBIS1Zc2dDG3Ujq+sR0U+JjUevW2JhocOF+soROYDSaAezOzOKuyyixhD6mBknSmQ== + version "2.0.1" + resolved "https://registry.yarnpkg.com/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-2.0.1.tgz#cb3173fe47ca743e228216e4a3ddc4c84d628cc2" + integrity sha512-dA8WbNeb2a6oQzAQ55YlT5vQAWGV9WXOsi3SskE3bcCdM0P4SDd+24zS/OCacdRq5BkdsRj9q3Pg6YyQoxIGqg== unicode-match-property-ecmascript@^2.0.0: version "2.0.0" @@ -4060,22 +4017,22 @@ unicode-match-property-ecmascript@^2.0.0: unicode-property-aliases-ecmascript "^2.0.0" unicode-match-property-value-ecmascript@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-2.1.0.tgz#cb5fffdcd16a05124f5a4b0bf7c3770208acbbe0" - integrity sha512-qxkjQt6qjg/mYscYMC0XKRn3Rh0wFPlfxB0xkt9CfyTvpX1Ra0+rAmdX2QyAobptSEvuy4RtpPRui6XkV+8wjA== + version "2.2.0" + resolved "https://registry.yarnpkg.com/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-2.2.0.tgz#a0401aee72714598f739b68b104e4fe3a0cb3c71" + integrity sha512-4IehN3V/+kkr5YeSSDDQG8QLqO26XpL2XP3GQtqwlT/QYSECAwFztxVHjlbh0+gjJ3XmNLS0zDsbgs9jWKExLg== unicode-property-aliases-ecmascript@^2.0.0: version "2.1.0" resolved "https://registry.yarnpkg.com/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-2.1.0.tgz#43d41e3be698bd493ef911077c9b131f827e8ccd" integrity sha512-6t3foTQI9qne+OZoVQB/8x8rk2k1eVy1gRXhV3oFQ5T6R1dqQ1xtin3XqSlx3+ATBkliTaR/hHyJBm+LVPNM8w== -update-browserslist-db@^1.0.13: - version "1.0.13" - resolved "https://registry.yarnpkg.com/update-browserslist-db/-/update-browserslist-db-1.0.13.tgz#3c5e4f5c083661bd38ef64b6328c26ed6c8248c4" - integrity sha512-xebP81SNcPuNpPP3uzeW1NYXxI3rxyJzF3pD6sH4jE7o/IX+WtSpwnVU+qIsDPyk0d3hmFQ7mjqc6AtV604hbg== +update-browserslist-db@^1.0.13, update-browserslist-db@^1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/update-browserslist-db/-/update-browserslist-db-1.1.3.tgz#348377dd245216f9e7060ff50b15a1b740b75420" + integrity sha512-UxhIZQ+QInVdunkDAaiazvvT/+fXL5Osr0JZlJulepYu6Jd7qJtDZjlur0emRlT71EN3ScPoE7gvsuIKKNavKw== dependencies: - escalade "^3.1.1" - picocolors "^1.0.0" + escalade "^3.2.0" + picocolors "^1.1.1" uri-js@^4.2.2: version "4.4.1" @@ -4089,23 +4046,38 @@ util-deprecate@^1.0.2: resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" integrity sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw== -vite-tsconfig-paths@^4.3.2: - version "4.3.2" - resolved "https://registry.yarnpkg.com/vite-tsconfig-paths/-/vite-tsconfig-paths-4.3.2.tgz#321f02e4b736a90ff62f9086467faf4e2da857a9" - integrity sha512-0Vd/a6po6Q+86rPlntHye7F31zA2URZMbH8M3saAZ/xR9QoGN/L21bxEGfXdWmFdNkqPpRdxFT7nmNe12e9/uA== +vite-prerender-plugin@^0.5.3: + version "0.5.11" + resolved "https://registry.yarnpkg.com/vite-prerender-plugin/-/vite-prerender-plugin-0.5.11.tgz#83e4f29e03269dceb763fb5ec2376dcc502aa79f" + integrity sha512-xWOhb8Ef2zoJIiinYVunIf3omRfUbEXcPEvrkQcrDpJ2yjDokxhvQ26eSJbkthRhymntWx6816jpATrJphh+ug== + dependencies: + kolorist "^1.8.0" + magic-string "0.x >= 0.26.0" + node-html-parser "^6.1.12" + simple-code-frame "^1.3.0" + source-map "^0.7.4" + stack-trace "^1.0.0-pre2" + +vite-tsconfig-paths@^5.1.4: + version "5.1.4" + resolved "https://registry.yarnpkg.com/vite-tsconfig-paths/-/vite-tsconfig-paths-5.1.4.tgz#d9a71106a7ff2c1c840c6f1708042f76a9212ed4" + integrity sha512-cYj0LRuLV2c2sMqhqhGpaO3LretdtMn/BVX4cPLanIZuwwrkVl+lK84E/miEXkCHWXuq65rhNN4rXsBcOB3S4w== dependencies: debug "^4.1.1" globrex "^0.1.2" tsconfck "^3.0.3" -vite@^5.2.8: - version "5.2.8" - resolved "https://registry.yarnpkg.com/vite/-/vite-5.2.8.tgz#a99e09939f1a502992381395ce93efa40a2844aa" - integrity sha512-OyZR+c1CE8yeHw5V5t59aXsUPPVTHMDjEZz8MgguLL/Q7NblxhZUlTu9xSPqlsUO/y+X7dlU05jdhvyycD55DA== +vite@^7.0.4: + version "7.0.4" + resolved "https://registry.yarnpkg.com/vite/-/vite-7.0.4.tgz#481204416277cfa7c93384c55984475c4276b18f" + integrity sha512-SkaSguuS7nnmV7mfJ8l81JGBFV7Gvzp8IzgE8A8t23+AxuNX61Q5H1Tpz5efduSN7NHC8nQXD3sKQKZAu5mNEA== dependencies: - esbuild "^0.20.1" - postcss "^8.4.38" - rollup "^4.13.0" + esbuild "^0.25.0" + fdir "^6.4.6" + picomatch "^4.0.2" + postcss "^8.5.6" + rollup "^4.40.0" + tinyglobby "^0.2.14" optionalDependencies: fsevents "~2.3.3" @@ -4209,7 +4181,7 @@ yocto-queue@^0.1.0: resolved "https://registry.yarnpkg.com/yocto-queue/-/yocto-queue-0.1.0.tgz#0294eb3dee05028d31ee1a5fa2c556a6aaf10a1b" integrity sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q== -zod@^3.21.4, zod@^3.23.8: +zod@^3.23.8: version "3.23.8" resolved "https://registry.yarnpkg.com/zod/-/zod-3.23.8.tgz#e37b957b5d52079769fb8097099b592f0ef4067d" integrity sha512-XBx9AXhXktjUqnepgTiE5flcKIYWi/rme0Eaj+5Y0lftuGBq+jyRu/md4WnuxqgP1ubdpNCsYEYPxrzVHD8d6g== diff --git a/bskyweb/cmd/bskyweb/filters.go b/bskyweb/cmd/bskyweb/filters.go new file mode 100644 index 0000000000..a92cc606bf --- /dev/null +++ b/bskyweb/cmd/bskyweb/filters.go @@ -0,0 +1,28 @@ +package main + +import ( + "net/url" + + "github.com/flosch/pongo2/v6" +) + +func init() { + pongo2.RegisterFilter("canonicalize_url", filterCanonicalizeURL) +} + +func filterCanonicalizeURL(in *pongo2.Value, param *pongo2.Value) (*pongo2.Value, *pongo2.Error) { + urlStr := in.String() + + parsedURL, err := url.Parse(urlStr) + if err != nil { + // If parsing fails, return the original URL + return in, nil + } + + // Remove query parameters and fragment + parsedURL.RawQuery = "" + parsedURL.Fragment = "" + + // Return the cleaned URL + return pongo2.AsValue(parsedURL.String()), nil +} diff --git a/bskyweb/cmd/bskyweb/filters_test.go b/bskyweb/cmd/bskyweb/filters_test.go new file mode 100644 index 0000000000..a63ad03175 --- /dev/null +++ b/bskyweb/cmd/bskyweb/filters_test.go @@ -0,0 +1,61 @@ +package main + +import ( + "testing" + + "github.com/flosch/pongo2/v6" +) + +func TestCanonicalizeURLFilter(t *testing.T) { + tests := []struct { + name string + input string + expected string + }{ + { + name: "clean URL", + input: "https://bsky.app/profile/user", + expected: "https://bsky.app/profile/user", + }, + { + name: "URL with query params", + input: "https://bsky.app/profile/user?utm_source=test", + expected: "https://bsky.app/profile/user", + }, + { + name: "URL with multiple params", + input: "https://bsky.app/profile/user?utm_source=twitter&utm_campaign=test", + expected: "https://bsky.app/profile/user", + }, + { + name: "URL with fragment", + input: "https://bsky.app/profile/user#section", + expected: "https://bsky.app/profile/user", + }, + { + name: "URL with both params and fragment", + input: "https://bsky.app/profile/user?param=1#section", + expected: "https://bsky.app/profile/user", + }, + { + name: "malformed URL", + input: "not-a-url", + expected: "not-a-url", // Should return original on error + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + inputValue := pongo2.AsValue(tt.input) + result, err := filterCanonicalizeURL(inputValue, nil) + if err != nil { + t.Errorf("filterCanonicalizeURL() error = %v", err) + return + } + + if result.String() != tt.expected { + t.Errorf("filterCanonicalizeURL() = %v, want %v", result.String(), tt.expected) + } + }) + } +} diff --git a/bskyweb/cmd/bskyweb/server.go b/bskyweb/cmd/bskyweb/server.go index 4208eea2d8..89cd112cd7 100644 --- a/bskyweb/cmd/bskyweb/server.go +++ b/bskyweb/cmd/bskyweb/server.go @@ -606,10 +606,10 @@ type IPCCRequest struct { type IPCCResponse struct { CC string `json:"countryCode"` AgeRestrictedGeo bool `json:"isAgeRestrictedGeo,omitempty"` + AgeBlockedGeo bool `json:"isAgeBlockedGeo,omitempty"` } -// IP address data is powered by IPinfo -// https://ipinfo.io +// This product includes GeoLite2 Data created by MaxMind, available from https://www.maxmind.com. func (srv *Server) WebIpCC(c echo.Context) error { realIP := c.RealIP() addr, err := netip.ParseAddr(realIP) diff --git a/bskyweb/templates/base.html b/bskyweb/templates/base.html index d72494da1a..715b39fd24 100644 --- a/bskyweb/templates/base.html +++ b/bskyweb/templates/base.html @@ -95,6 +95,7 @@ + {% block html_head_extra -%}{%- endblock %} diff --git a/bskyweb/templates/home.html b/bskyweb/templates/home.html index 5d3fbad85a..0e148b37ea 100644 --- a/bskyweb/templates/home.html +++ b/bskyweb/templates/home.html @@ -12,11 +12,11 @@ + - {%- endblock %} diff --git a/bskyweb/templates/post.html b/bskyweb/templates/post.html index f6f03c7ee7..6473bc284f 100644 --- a/bskyweb/templates/post.html +++ b/bskyweb/templates/post.html @@ -14,6 +14,7 @@ {%- if requestURI %} + {% endif -%} {%- if postView.Author.DisplayName %} @@ -23,15 +24,18 @@ {%- if postText %} + {% endif -%} {%- if imgThumbUrls %} {% for imgThumbUrl in imgThumbUrls %} + {% endfor %} {%- elif postView.Author.Avatar %} - {# Don't use avatar image in cards; usually looks bad #} + + {% endif %} diff --git a/bskyweb/templates/profile.html b/bskyweb/templates/profile.html index ab84dd157e..8506a9cff7 100644 --- a/bskyweb/templates/profile.html +++ b/bskyweb/templates/profile.html @@ -15,6 +15,7 @@ {%- if requestURI %} + {% endif -%} {%- if profileView.DisplayName %} diff --git a/jest/test-pds.ts b/jest/test-pds.ts index 962bb7b48e..98933a0633 100644 --- a/jest/test-pds.ts +++ b/jest/test-pds.ts @@ -1,5 +1,5 @@ import {AtUri, BskyAgent} from '@atproto/api' -import {TestBsky, TestNetwork} from '@atproto/dev-env' +import {type TestBsky, TestNetwork} from '@atproto/dev-env' import fs from 'fs' import net from 'net' import path from 'path' @@ -13,6 +13,7 @@ export interface TestUser { } export interface TestPDS { + appviewDid: string pdsUrl: string mocker: Mocker close: () => Promise @@ -112,6 +113,7 @@ export async function createServer( ) return { + appviewDid: testNet.bsky.serverDid, pdsUrl, mocker: new Mocker(testNet, pdsUrl, pic), async close() { diff --git a/package.json b/package.json index 0f3f685713..9aa41e9422 100644 --- a/package.json +++ b/package.json @@ -21,7 +21,7 @@ "scripts": { "prepare": "is-ci || husky install", "postinstall": "patch-package && yarn intl:compile-if-needed", - "prebuild": "expo prebuild --clean", + "prebuild": "EXPO_NO_GIT_STATUS=1 expo prebuild --clean", "android": "expo run:android", "android:prod": "expo run:android --variant release", "android:profile": "BSKY_PROFILE=1 expo run:android --variant release", @@ -92,7 +92,7 @@ "@lingui/react": "^4.14.1", "@mattermost/react-native-paste-input": "mattermost/react-native-paste-input", "@miblanchard/react-native-slider": "^2.6.0", - "@mozzius/expo-dynamic-app-icon": "1.5.0", + "@mozzius/expo-dynamic-app-icon": "^1.7.1", "@react-native-async-storage/async-storage": "2.1.2", "@react-native-menu/menu": "^1.2.3", "@react-native-picker/picker": "2.11.0", @@ -146,7 +146,7 @@ "expo-image": "^2.4.0", "expo-image-crop-tool": "^0.1.8", "expo-image-manipulator": "~13.1.7", - "expo-image-picker": "^17.0.2", + "expo-image-picker": "17.0.5", "expo-intent-launcher": "^12.1.5", "expo-linear-gradient": "~14.1.5", "expo-linking": "~7.1.5", @@ -224,7 +224,7 @@ "zod": "^3.20.2" }, "devDependencies": { - "@atproto/dev-env": "^0.3.160", + "@atproto/dev-env": "^0.3.167", "@babel/core": "^7.26.0", "@babel/preset-env": "^7.26.0", "@babel/runtime": "^7.26.0", diff --git a/src/Navigation.tsx b/src/Navigation.tsx index 97c351bc86..7af38105be 100644 --- a/src/Navigation.tsx +++ b/src/Navigation.tsx @@ -55,7 +55,6 @@ import {DebugModScreen} from '#/view/screens/DebugMod' import {FeedsScreen} from '#/view/screens/Feeds' import {HomeScreen} from '#/view/screens/Home' import {ListsScreen} from '#/view/screens/Lists' -import {LogScreen} from '#/view/screens/Log' import {ModerationBlockedAccounts} from '#/view/screens/ModerationBlockedAccounts' import {ModerationModlistsScreen} from '#/view/screens/ModerationModlists' import {ModerationMutedAccounts} from '#/view/screens/ModerationMutedAccounts' @@ -74,6 +73,7 @@ import {BottomBar} from '#/view/shell/bottom-bar/BottomBar' import {createNativeStackNavigatorWithAuth} from '#/view/shell/createNativeStackNavigatorWithAuth' import {SharedPreferencesTesterScreen} from '#/screens/E2E/SharedPreferencesTesterScreen' import HashtagScreen from '#/screens/Hashtag' +import {LogScreen} from '#/screens/Log' import {MessagesScreen} from '#/screens/Messages/ChatList' import {MessagesConversationScreen} from '#/screens/Messages/Conversation' import {MessagesInboxScreen} from '#/screens/Messages/Inbox' diff --git a/src/alf/atoms.ts b/src/alf/atoms.ts index 5b7c5c87ea..ae88f457dc 100644 --- a/src/alf/atoms.ts +++ b/src/alf/atoms.ts @@ -70,9 +70,21 @@ export const atoms = { overflow_visible: { overflow: 'visible', }, + overflow_x_visible: { + overflowX: 'visible', + }, + overflow_y_visible: { + overflowY: 'visible', + }, overflow_hidden: { overflow: 'hidden', }, + overflow_x_hidden: { + overflowX: 'hidden', + }, + overflow_y_hidden: { + overflowY: 'hidden', + }, /** * @platform web */ @@ -363,6 +375,14 @@ export const atoms = { border_r_0: { borderRightWidth: 0, }, + border_x_0: { + borderLeftWidth: 0, + borderRightWidth: 0, + }, + border_y_0: { + borderTopWidth: 0, + borderBottomWidth: 0, + }, border: { borderWidth: StyleSheet.hairlineWidth, }, @@ -378,6 +398,14 @@ export const atoms = { border_r: { borderRightWidth: StyleSheet.hairlineWidth, }, + border_x: { + borderLeftWidth: StyleSheet.hairlineWidth, + borderRightWidth: StyleSheet.hairlineWidth, + }, + border_y: { + borderTopWidth: StyleSheet.hairlineWidth, + borderBottomWidth: StyleSheet.hairlineWidth, + }, border_transparent: { borderColor: 'transparent', }, @@ -988,6 +1016,9 @@ export const atoms = { block: web({ display: 'block', }), + contents: web({ + display: 'contents', + }), /* * Transition diff --git a/src/components/BlockedGeoOverlay.tsx b/src/components/BlockedGeoOverlay.tsx new file mode 100644 index 0000000000..ae5790da92 --- /dev/null +++ b/src/components/BlockedGeoOverlay.tsx @@ -0,0 +1,109 @@ +import {useEffect} from 'react' +import {ScrollView, View} from 'react-native' +import {useSafeAreaInsets} from 'react-native-safe-area-context' +import {msg, Trans} from '@lingui/macro' +import {useLingui} from '@lingui/react' + +import {logger} from '#/logger' +import {isWeb} from '#/platform/detection' +import {atoms as a, useBreakpoints, useTheme, web} from '#/alf' +import {Full as Logo, Mark} from '#/components/icons/Logo' +import {SimpleInlineLinkText as InlineLinkText} from '#/components/Link' +import {Text} from '#/components/Typography' + +export function BlockedGeoOverlay() { + const t = useTheme() + const {_} = useLingui() + const {gtPhone} = useBreakpoints() + const insets = useSafeAreaInsets() + + useEffect(() => { + // just counting overall hits here + logger.metric(`blockedGeoOverlay:shown`, {}) + }, []) + + const textStyles = [a.text_md, a.leading_normal] + const links = { + blog: { + to: `https://bsky.social/about/blog/08-22-2025-mississippi-hb1126`, + label: _(msg`Read our blog post`), + overridePresentation: false, + disableMismatchWarning: true, + style: textStyles, + }, + } + + const blocks = [ + _(msg`Unfortunately, Bluesky is unavailable in Mississippi right now.`), + _( + msg`A new Mississippi law requires us to implement age verification for all users before they can access Bluesky. We think this law creates challenges that go beyond its child safety goals, and creates significant barriers that limit free speech and disproportionately harm smaller platforms and emerging technologies.`, + ), + _( + msg`As a small team, we cannot justify building the expensive infrastructure this requirement demands while legal challenges to this law are pending.`, + ), + _( + msg`For now, we have made the difficult decision to block access to Bluesky in the state of Mississippi.`, + ), + <> + To learn more, read our{' '} + blog post. + , + ] + + return ( + + + + + + + Announcement + + + + + + {blocks.map((block, index) => ( + + {block} + + ))} + + + + + + ) +} diff --git a/src/components/Dialog/index.tsx b/src/components/Dialog/index.tsx index 4795385eec..de8287a53c 100644 --- a/src/components/Dialog/index.tsx +++ b/src/components/Dialog/index.tsx @@ -12,9 +12,13 @@ import { import { KeyboardAwareScrollView, useKeyboardHandler, + useReanimatedKeyboardAnimation, } from 'react-native-keyboard-controller' -import {runOnJS} from 'react-native-reanimated' -import {type ReanimatedScrollEvent} from 'react-native-reanimated/lib/typescript/hook/commonTypes' +import Animated, { + runOnJS, + type ScrollEvent, + useAnimatedStyle, +} from 'react-native-reanimated' import {useSafeAreaInsets} from 'react-native-safe-area-context' import {msg} from '@lingui/macro' import {useLingui} from '@lingui/react' @@ -26,7 +30,7 @@ import {isAndroid, isIOS} from '#/platform/detection' import {useA11y} from '#/state/a11y' import {useDialogStateControlContext} from '#/state/dialogs' import {List, type ListMethods, type ListProps} from '#/view/com/util/List' -import {atoms as a, tokens, useTheme} from '#/alf' +import {atoms as a, ios, platform, tokens, useTheme} from '#/alf' import {useThemeName} from '#/alf/util/useColorModeTheme' import {Context, useDialogContext} from '#/components/Dialog/context' import { @@ -256,6 +260,7 @@ export const ScrollableInner = React.forwardRef( contentContainerStyle, ]} ref={ref} + showsVerticalScrollIndicator={isAndroid ? false : undefined} {...props} bounces={nativeSnapPoint === BottomSheetSnapPoint.Full} bottomOffset={30} @@ -275,12 +280,15 @@ export const InnerFlatList = React.forwardRef< ListProps & { webInnerStyle?: StyleProp webInnerContentContainerStyle?: StyleProp + footer?: React.ReactNode } ->(function InnerFlatList({style, ...props}, ref) { +>(function InnerFlatList({footer, style, ...props}, ref) { const insets = useSafeAreaInsets() const {nativeSnapPoint, disableDrag, setDisableDrag} = useDialogContext() - const onScroll = (e: ReanimatedScrollEvent) => { + useEnableKeyboardController(isIOS) + + const onScroll = (e: ScrollEvent) => { 'worklet' if (!isAndroid) { return @@ -300,13 +308,54 @@ export const InnerFlatList = React.forwardRef< bounces={nativeSnapPoint === BottomSheetSnapPoint.Full} ListFooterComponent={} ref={ref} + showsVerticalScrollIndicator={isAndroid ? false : undefined} {...props} - style={[style]} + style={[a.h_full, style]} /> + {footer} ) }) +export function FlatListFooter({children}: {children: React.ReactNode}) { + const t = useTheme() + const {top, bottom} = useSafeAreaInsets() + const {height} = useReanimatedKeyboardAnimation() + + const animatedStyle = useAnimatedStyle(() => { + if (!isIOS) return {} + return { + transform: [{translateY: Math.min(0, height.get() + bottom - 10)}], + } + }) + + return ( + + {children} + + ) +} + export function Handle({difference = false}: {difference?: boolean}) { const t = useTheme() const {_} = useLingui() diff --git a/src/components/Dialog/index.web.tsx b/src/components/Dialog/index.web.tsx index 12bd8819b1..1d62cbfdcd 100644 --- a/src/components/Dialog/index.web.tsx +++ b/src/components/Dialog/index.web.tsx @@ -2,6 +2,7 @@ import React, {useImperativeHandle} from 'react' import { FlatList, type FlatListProps, + type GestureResponderEvent, type StyleProp, TouchableWithoutFeedback, View, @@ -32,6 +33,9 @@ export * from '#/components/Dialog/types' export * from '#/components/Dialog/utils' export {Input} from '#/components/forms/TextField' +// 100 minus 10vh of paddingVertical +export const WEB_DIALOG_HEIGHT = '80vh' + const stopPropagation = (e: any) => e.stopPropagation() const preventDefault = (e: any) => e.preventDefault() @@ -75,9 +79,12 @@ export function Outer({ [control.id, onClose, setDialogIsOpen], ) - const handleBackgroundPress = React.useCallback(async () => { - close() - }, [close]) + const handleBackgroundPress = React.useCallback( + async (e: GestureResponderEvent) => { + webOptions?.onBackgroundPress ? webOptions.onBackgroundPress(e) : close() + }, + [webOptions, close], + ) useImperativeHandle( control.ref, @@ -193,7 +200,7 @@ export function Inner({ onInteractOutside={preventDefault} onFocusOutside={preventDefault} onDismiss={close} - style={{display: 'flex', flexDirection: 'column'}}> + style={{height: '100%', display: 'flex', flexDirection: 'column'}}> {header} {children} @@ -211,9 +218,17 @@ export const InnerFlatList = React.forwardRef< FlatListProps & {label: string} & { webInnerStyle?: StyleProp webInnerContentContainerStyle?: StyleProp + footer?: React.ReactNode } >(function InnerFlatList( - {label, style, webInnerStyle, webInnerContentContainerStyle, ...props}, + { + label, + style, + webInnerStyle, + webInnerContentContainerStyle, + footer, + ...props + }, ref, ) { const {gtMobile} = useBreakpoints() @@ -223,20 +238,41 @@ export const InnerFlatList = React.forwardRef< style={[ a.overflow_hidden, a.px_0, - // 100 minus 10vh of paddingVertical - web({maxHeight: '80vh'}), + web({maxHeight: WEB_DIALOG_HEIGHT}), webInnerStyle, ]} - contentContainerStyle={[a.px_0, webInnerContentContainerStyle]}> + contentContainerStyle={[a.h_full, a.px_0, webInnerContentContainerStyle]}> + {footer} ) }) +export function FlatListFooter({children}: {children: React.ReactNode}) { + const t = useTheme() + + return ( + + {children} + + ) +} + export function Close() { const {_} = useLingui() const {close} = React.useContext(Context) diff --git a/src/components/Dialog/shared.tsx b/src/components/Dialog/shared.tsx index 40d0408788..b5513b19c4 100644 --- a/src/components/Dialog/shared.tsx +++ b/src/components/Dialog/shared.tsx @@ -5,7 +5,6 @@ import { View, type ViewStyle, } from 'react-native' -import type React from 'react' import {atoms as a, useTheme} from '#/alf' import {Text} from '#/components/Typography' @@ -28,6 +27,8 @@ export function Header({ }) { return ( - + {children} ) diff --git a/src/components/Dialog/types.ts b/src/components/Dialog/types.ts index 3ca64a3214..1308e625c5 100644 --- a/src/components/Dialog/types.ts +++ b/src/components/Dialog/types.ts @@ -1,15 +1,15 @@ -import React from 'react' -import type { - AccessibilityProps, - GestureResponderEvent, - ScrollViewProps, +import { + type AccessibilityProps, + type GestureResponderEvent, + type ScrollViewProps, + type StyleProp, + type ViewStyle, } from 'react-native' -import {ViewStyle} from 'react-native' -import {StyleProp} from 'react-native' +import type React from 'react' -import {ViewStyleProp} from '#/alf' -import {BottomSheetViewProps} from '../../../modules/bottom-sheet' -import {BottomSheetSnapPoint} from '../../../modules/bottom-sheet/src/BottomSheet.types' +import {type ViewStyleProp} from '#/alf' +import {type BottomSheetViewProps} from '../../../modules/bottom-sheet' +import {type BottomSheetSnapPoint} from '../../../modules/bottom-sheet/src/BottomSheet.types' type A11yProps = Required @@ -64,6 +64,7 @@ export type DialogOuterProps = { nativeOptions?: Omit webOptions?: { alignCenter?: boolean + onBackgroundPress?: (e: GestureResponderEvent) => void } testID?: string } diff --git a/src/components/FeedInterstitials.tsx b/src/components/FeedInterstitials.tsx index 18da12b22c..6278449a07 100644 --- a/src/components/FeedInterstitials.tsx +++ b/src/components/FeedInterstitials.tsx @@ -1,6 +1,5 @@ import React from 'react' -import {View} from 'react-native' -import {ScrollView} from 'react-native-gesture-handler' +import {ScrollView, View} from 'react-native' import {type AppBskyFeedDefs, AtUri} from '@atproto/api' import {msg, Trans} from '@lingui/macro' import {useLingui} from '@lingui/react' @@ -9,6 +8,7 @@ import {useNavigation} from '@react-navigation/native' import {type NavigationProp} from '#/lib/routes/types' import {logEvent} from '#/lib/statsig/statsig' import {logger} from '#/logger' +import {isIOS} from '#/platform/detection' import {useModerationOpts} from '#/state/preferences/moderation-opts' import {useGetPopularFeedsQuery} from '#/state/queries/feed' import {type FeedDescriptor} from '#/state/queries/post-feed' @@ -25,17 +25,18 @@ import { type ViewStyleProp, web, } from '#/alf' -import {Button, ButtonText} from '#/components/Button' +import {Button, ButtonIcon, ButtonText} from '#/components/Button' import * as FeedCard from '#/components/FeedCard' -import {ArrowRight_Stroke2_Corner0_Rounded as Arrow} from '#/components/icons/Arrow' +import {ArrowRight_Stroke2_Corner0_Rounded as ArrowRight} from '#/components/icons/Arrow' import {Hashtag_Stroke2_Corner0_Rounded as Hashtag} from '#/components/icons/Hashtag' -import {InlineLinkText} from '#/components/Link' +import {InlineLinkText, Link} from '#/components/Link' import * as ProfileCard from '#/components/ProfileCard' import {Text} from '#/components/Typography' import type * as bsky from '#/types/bsky' import {ProgressGuideList} from './ProgressGuide/List' const MOBILE_CARD_WIDTH = 165 +const FINAL_CARD_WIDTH = 120 function CardOuter({ children, @@ -46,11 +47,13 @@ function CardOuter({ return ( + @@ -78,24 +78,15 @@ export function SuggestedFollowPlaceholder() { - + ) } export function SuggestedFeedsCardPlaceholder() { - const t = useTheme() return ( - + @@ -253,129 +244,133 @@ export function ProfileGrid({ profiles: bsky.profile.AnyProfileView[] recId?: number error: Error | null - viewContext: 'profile' | 'feed' + viewContext: 'profile' | 'profileHeader' | 'feed' }) { const t = useTheme() const {_} = useLingui() const moderationOpts = useModerationOpts() const {gtMobile} = useBreakpoints() - const isLoading = isSuggestionsLoading || !moderationOpts - const maxLength = gtMobile ? 3 : 6 - const content = isLoading ? ( - Array(maxLength) - .fill(0) - .map((_, i) => ( - - - - )) - ) : error || !profiles.length ? null : ( - <> - {profiles.slice(0, maxLength).map((profile, index) => ( - { - logEvent('suggestedUser:press', { - logContext: - viewContext === 'feed' + const isLoading = isSuggestionsLoading || !moderationOpts + const isProfileHeaderContext = viewContext === 'profileHeader' + const isFeedContext = viewContext === 'feed' + + const maxLength = gtMobile ? 3 : isProfileHeaderContext ? 12 : 6 + const minLength = gtMobile ? 3 : 4 + + const content = isLoading + ? Array(maxLength) + .fill(0) + .map((_, i) => ( + + + + )) + : error || !profiles.length + ? null + : profiles.slice(0, maxLength).map((profile, index) => ( + { + logEvent('suggestedUser:press', { + logContext: isFeedContext ? 'InterstitialDiscover' : 'InterstitialProfile', - recId, - position: index, - }) - }} - style={[ - a.flex_1, - gtMobile && - web([ - a.flex_0, - a.flex_grow, - {width: `calc(30% - ${a.gap_md.gap / 2}px)`}, - ]), - ]}> - {({hovered, pressed}) => ( - - - - - - + {({hovered, pressed}) => ( + + + + - + + + + - - { - logEvent('suggestedUser:follow', { - logContext: - viewContext === 'feed' + { + logEvent('suggestedUser:follow', { + logContext: isFeedContext ? 'InterstitialDiscover' : 'InterstitialProfile', - location: 'Card', - recId, - position: index, - }) - }} - /> - - - )} - - ))} - - ) + location: 'Card', + recId, + position: index, + }) + }} + /> + + + )} + + )) - if (error || (!isLoading && profiles.length < 4)) { + if (error || (!isLoading && profiles.length < minLength)) { logger.debug(`Not enough profiles to show suggested follows`) return null } return ( + style={[ + !isProfileHeaderContext && a.border_t, + t.atoms.border_contrast_low, + t.atoms.bg_contrast_25, + ]} + pointerEvents={isIOS ? 'auto' : 'box-none'}> + ]} + pointerEvents={isIOS ? 'auto' : 'box-none'}> - {viewContext === 'profile' ? ( - Similar accounts - ) : ( + {isFeedContext ? ( Suggested for you + ) : ( + Similar accounts )} - - See more - + {!isProfileHeaderContext && ( + + See more + + )} {gtMobile ? ( @@ -406,19 +404,16 @@ export function ProfileGrid({ ) : ( - - - - {content} + + {content} - - - - + {!isProfileHeaderContext && } + )} @@ -426,29 +421,30 @@ export function ProfileGrid({ } function SeeMoreSuggestedProfilesCard() { - const navigation = useNavigation() const t = useTheme() const {_} = useLingui() return ( - + style={[ + a.flex_col, + a.align_center, + a.justify_center, + a.gap_sm, + a.p_md, + a.rounded_lg, + t.atoms.shadow_sm, + {width: FINAL_CARD_WIDTH}, + ]}> + + + See more + + ) } @@ -491,10 +487,7 @@ export function SuggestedFeeds() { }}> {({hovered, pressed}) => ( + style={[(hovered || pressed) && t.atoms.border_contrast_high]}> @@ -549,7 +542,7 @@ export function SuggestedFeeds() { style={[t.atoms.text_contrast_medium]}> Browse more suggestions - + ) : ( @@ -568,7 +561,7 @@ export function SuggestedFeeds() { navigation.navigate('SearchTab') }} style={[a.flex_col]}> - + @@ -577,7 +570,7 @@ export function SuggestedFeeds() { - + diff --git a/src/components/InterestTabs.tsx b/src/components/InterestTabs.tsx new file mode 100644 index 0000000000..b61157ed82 --- /dev/null +++ b/src/components/InterestTabs.tsx @@ -0,0 +1,390 @@ +import {useEffect, useRef, useState} from 'react' +import { + type ScrollView, + type StyleProp, + View, + type ViewStyle, +} from 'react-native' +import {msg} from '@lingui/macro' +import {useLingui} from '@lingui/react' + +import {useNonReactiveCallback} from '#/lib/hooks/useNonReactiveCallback' +import {isWeb} from '#/platform/detection' +import {DraggableScrollView} from '#/view/com/pager/DraggableScrollView' +import {atoms as a, tokens, useTheme, web} from '#/alf' +import {transparentifyColor} from '#/alf/util/colorGeneration' +import {Button, ButtonIcon} from '#/components/Button' +import { + ArrowLeft_Stroke2_Corner0_Rounded as ArrowLeft, + ArrowRight_Stroke2_Corner0_Rounded as ArrowRight, +} from '#/components/icons/Arrow' +import {Text} from '#/components/Typography' + +/** + * Tab component that automatically scrolls the selected tab into view - used for interests + * in the Find Follows dialog, Explore screen, etc. + */ +export function InterestTabs({ + onSelectTab, + interests, + selectedInterest, + disabled, + interestsDisplayNames, + TabComponent = Tab, + contentContainerStyle, + gutterWidth = tokens.space.lg, +}: { + onSelectTab: (tab: string) => void + interests: string[] + selectedInterest: string + interestsDisplayNames: Record + /** still allows changing tab, but removes the active state from the selected tab */ + disabled?: boolean + TabComponent?: React.ComponentType> + contentContainerStyle?: StyleProp + gutterWidth?: number +}) { + const t = useTheme() + const {_} = useLingui() + const listRef = useRef(null) + const [totalWidth, setTotalWidth] = useState(0) + const [scrollX, setScrollX] = useState(0) + const [contentWidth, setContentWidth] = useState(0) + const pendingTabOffsets = useRef<{x: number; width: number}[]>([]) + const [tabOffsets, setTabOffsets] = useState<{x: number; width: number}[]>([]) + + const onInitialLayout = useNonReactiveCallback(() => { + const index = interests.indexOf(selectedInterest) + scrollIntoViewIfNeeded(index) + }) + + useEffect(() => { + if (tabOffsets) { + onInitialLayout() + } + }, [tabOffsets, onInitialLayout]) + + function scrollIntoViewIfNeeded(index: number) { + const btnLayout = tabOffsets[index] + if (!btnLayout) return + listRef.current?.scrollTo({ + // centered + x: btnLayout.x - (totalWidth / 2 - btnLayout.width / 2), + animated: true, + }) + } + + function handleSelectTab(index: number) { + const tab = interests[index] + onSelectTab(tab) + scrollIntoViewIfNeeded(index) + } + + function handleTabLayout(index: number, x: number, width: number) { + if (!tabOffsets.length) { + pendingTabOffsets.current[index] = {x, width} + if (pendingTabOffsets.current.length === interests.length) { + setTabOffsets(pendingTabOffsets.current) + } + } + } + + const canScrollLeft = scrollX > 0 + const canScrollRight = scrollX < contentWidth - totalWidth + + const cleanupRef = useRef<(() => void) | null>(null) + + function scrollLeft() { + if (isContinuouslyScrollingRef.current) { + return + } + if (listRef.current && canScrollLeft) { + const newScrollX = Math.max(0, scrollX - 200) + listRef.current.scrollTo({x: newScrollX, animated: true}) + } + } + + function scrollRight() { + if (isContinuouslyScrollingRef.current) { + return + } + if (listRef.current && canScrollRight) { + const maxScroll = contentWidth - totalWidth + const newScrollX = Math.min(maxScroll, scrollX + 200) + listRef.current.scrollTo({x: newScrollX, animated: true}) + } + } + + const isContinuouslyScrollingRef = useRef(false) + + function startContinuousScroll(direction: 'left' | 'right') { + // Clear any existing continuous scroll + if (cleanupRef.current) { + cleanupRef.current() + } + + let holdTimeout: NodeJS.Timeout | null = null + let animationFrame: number | null = null + let isActive = true + isContinuouslyScrollingRef.current = false + + const cleanup = () => { + isActive = false + if (holdTimeout) clearTimeout(holdTimeout) + if (animationFrame) cancelAnimationFrame(animationFrame) + cleanupRef.current = null + // Reset flag after a delay to prevent onPress from firing + setTimeout(() => { + isContinuouslyScrollingRef.current = false + }, 100) + } + + cleanupRef.current = cleanup + + // Start continuous scrolling after hold delay + holdTimeout = setTimeout(() => { + if (!isActive) return + + isContinuouslyScrollingRef.current = true + let currentScrollPosition = scrollX + + const scroll = () => { + if (!isActive || !listRef.current) return + + const scrollAmount = 3 + const maxScroll = contentWidth - totalWidth + + let newScrollX: number + let canContinue = false + + if (direction === 'left' && currentScrollPosition > 0) { + newScrollX = Math.max(0, currentScrollPosition - scrollAmount) + canContinue = newScrollX > 0 + } else if (direction === 'right' && currentScrollPosition < maxScroll) { + newScrollX = Math.min(maxScroll, currentScrollPosition + scrollAmount) + canContinue = newScrollX < maxScroll + } else { + return + } + + currentScrollPosition = newScrollX + listRef.current.scrollTo({x: newScrollX, animated: false}) + + if (canContinue && isActive) { + animationFrame = requestAnimationFrame(scroll) + } + } + + scroll() + }, 500) + } + + function stopContinuousScroll() { + if (cleanupRef.current) { + cleanupRef.current() + } + } + + useEffect(() => { + return () => { + if (cleanupRef.current) { + cleanupRef.current() + } + } + }, []) + + return ( + + o.x - tokens.space.xl) + : undefined + } + onLayout={evt => setTotalWidth(evt.nativeEvent.layout.width)} + onContentSizeChange={width => setContentWidth(width)} + onScroll={evt => { + const newScrollX = evt.nativeEvent.contentOffset.x + setScrollX(newScrollX) + }} + scrollEventThrottle={16}> + {interests.map((interest, i) => { + const active = interest === selectedInterest && !disabled + return ( + + ) + })} + + {isWeb && canScrollLeft && ( + + + + )} + {isWeb && canScrollRight && ( + + + + )} + + ) +} + +function Tab({ + onSelectTab, + interest, + active, + index, + interestsDisplayName, + onLayout, +}: { + onSelectTab: (index: number) => void + interest: string + active: boolean + index: number + interestsDisplayName: string + onLayout: (index: number, x: number, width: number) => void +}) { + const t = useTheme() + const {_} = useLingui() + const label = active + ? _( + msg({ + message: `"${interestsDisplayName}" category (active)`, + comment: + 'Accessibility label for a category (e.g. Art, Video Games, Sports, etc.) that shows suggested accounts for the user to follow. The tab is currently selected.', + }), + ) + : _( + msg({ + message: `Select "${interestsDisplayName}" category`, + comment: + 'Accessibility label for a category (e.g. Art, Video Games, Sports, etc.) that shows suggested accounts for the user to follow. The tab is not currently active and can be selected.', + }), + ) + + return ( + + onLayout(index, e.nativeEvent.layout.x, e.nativeEvent.layout.width) + }> + + + ) +} + +export function boostInterests(boosts?: string[]) { + return (_a: string, _b: string) => { + const indexA = boosts?.indexOf(_a) ?? -1 + const indexB = boosts?.indexOf(_b) ?? -1 + const rankA = indexA === -1 ? Infinity : indexA + const rankB = indexB === -1 ? Infinity : indexB + return rankA - rankB + } +} diff --git a/src/components/Layout/const.ts b/src/components/Layout/const.ts index 2b5d3a1fc8..2721bed21e 100644 --- a/src/components/Layout/const.ts +++ b/src/components/Layout/const.ts @@ -13,7 +13,7 @@ export const BUTTON_VISUAL_ALIGNMENT_OFFSET = 3 /** * Corresponds to the width of a small square or round button */ -export const HEADER_SLOT_SIZE = 34 +export const HEADER_SLOT_SIZE = 33 /** * How far to shift the center column when in the tablet breakpoint diff --git a/src/components/Link.tsx b/src/components/Link.tsx index 6954be6a89..421a7fe9d6 100644 --- a/src/components/Link.tsx +++ b/src/components/Link.tsx @@ -1,5 +1,5 @@ import React, {useMemo} from 'react' -import {type GestureResponderEvent} from 'react-native' +import {type GestureResponderEvent, Linking} from 'react-native' import {sanitizeUrl} from '@braintree/sanitize-url' import { type LinkProps as RNLinkProps, @@ -13,6 +13,7 @@ import {type AllNavigatorParams, type RouteParams} from '#/lib/routes/types' import {shareUrl} from '#/lib/sharing' import { convertBskyAppUrlIfNeeded, + createProxiedUrl, isBskyDownloadUrl, isExternalUrl, linkRequiresWarning, @@ -407,6 +408,91 @@ export function InlineLinkText({ ) } +/** + * A barebones version of `InlineLinkText`, for use outside a + * `react-navigation` context. + */ +export function SimpleInlineLinkText({ + children, + to, + style, + download, + selectable, + label, + disableUnderline, + shouldProxy, + ...rest +}: Omit< + InlineLinkProps, + | 'to' + | 'action' + | 'disableMismatchWarning' + | 'overridePresentation' + | 'onPress' + | 'onLongPress' + | 'shareOnLongPress' +> & { + to: string +}) { + const t = useTheme() + const { + state: hovered, + onIn: onHoverIn, + onOut: onHoverOut, + } = useInteractionState() + const flattenedStyle = flatten(style) || {} + const isExternal = isExternalUrl(to) + + let href = to + if (shouldProxy) { + href = createProxiedUrl(href) + } + + const onPress = () => { + Linking.openURL(href) + } + + return ( + + {children} + + ) +} + export function WebOnlyInlineLinkText({ children, to, diff --git a/src/components/LoggedOutCTA.tsx b/src/components/LoggedOutCTA.tsx new file mode 100644 index 0000000000..0bafbd45f1 --- /dev/null +++ b/src/components/LoggedOutCTA.tsx @@ -0,0 +1,82 @@ +import {View, type ViewStyle} from 'react-native' +import {msg, Trans} from '@lingui/macro' +import {useLingui} from '@lingui/react' + +import {type Gate} from '#/lib/statsig/gates' +import {useGate} from '#/lib/statsig/statsig' +import {isWeb} from '#/platform/detection' +import {useSession} from '#/state/session' +import {useLoggedOutViewControls} from '#/state/shell/logged-out' +import {Logo} from '#/view/icons/Logo' +import {atoms as a, useTheme} from '#/alf' +import {Button, ButtonText} from '#/components/Button' +import {Text} from '#/components/Typography' + +interface LoggedOutCTAProps { + style?: ViewStyle + gateName: Gate +} + +export function LoggedOutCTA({style, gateName}: LoggedOutCTAProps) { + const {hasSession} = useSession() + const {requestSwitchToAccount} = useLoggedOutViewControls() + const gate = useGate() + const t = useTheme() + const {_} = useLingui() + + // Only show for logged-out users on web + if (hasSession || !isWeb) { + return null + } + + // Check gate at the last possible moment to avoid counting users as exposed when they won't see the element + if (!gate(gateName)) { + return null + } + + return ( + + + + + + + Join Bluesky + + + The open social network. + + + + + + + ) +} diff --git a/src/components/MediaPreview.tsx b/src/components/MediaPreview.tsx index 208973cc95..c2603a4d78 100644 --- a/src/components/MediaPreview.tsx +++ b/src/components/MediaPreview.tsx @@ -1,7 +1,6 @@ -import React from 'react' -import {StyleProp, StyleSheet, View, ViewStyle} from 'react-native' +import {type StyleProp, StyleSheet, View, type ViewStyle} from 'react-native' import {Image} from 'expo-image' -import {AppBskyFeedDefs} from '@atproto/api' +import {type AppBskyFeedDefs} from '@atproto/api' import {Trans} from '@lingui/macro' import {isTenorGifUri} from '#/lib/strings/embed-player' @@ -92,12 +91,11 @@ export function ImageItem({ {alt} {children} diff --git a/src/components/PolicyUpdateOverlay/context.tsx b/src/components/PolicyUpdateOverlay/context.tsx index abb058d3c5..3c65ae3753 100644 --- a/src/components/PolicyUpdateOverlay/context.tsx +++ b/src/components/PolicyUpdateOverlay/context.tsx @@ -12,6 +12,7 @@ import { type PolicyUpdateState, usePolicyUpdateState, } from '#/components/PolicyUpdateOverlay/usePolicyUpdateState' +import {ENV} from '#/env' const Context = createContext<{ state: PolicyUpdateState @@ -45,8 +46,7 @@ export function Provider({children}: {children?: ReactNode}) { const [isReadyToShowOverlay, setIsReadyToShowOverlay] = useState(false) const state = usePolicyUpdateState({ // only enable the policy update overlay in non-test environments - enabled: - isReadyToShowOverlay && hasSession && process.env.NODE_ENV !== 'test', + enabled: isReadyToShowOverlay && hasSession && ENV !== 'e2e', }) const ctx = useMemo( diff --git a/src/components/Post/Embed/index.tsx b/src/components/Post/Embed/index.tsx index 9c5444b27d..8566c2fe6f 100644 --- a/src/components/Post/Embed/index.tsx +++ b/src/components/Post/Embed/index.tsx @@ -87,14 +87,18 @@ function MediaEmbed({ switch (embed.type) { case 'images': { return ( - + ) } case 'link': { return ( - + + ) diff --git a/src/components/PostControls/PostMenu/PostMenuItems.tsx b/src/components/PostControls/PostMenu/PostMenuItems.tsx index 3fd919cd3e..2ec0c6a4cd 100644 --- a/src/components/PostControls/PostMenu/PostMenuItems.tsx +++ b/src/components/PostControls/PostMenu/PostMenuItems.tsx @@ -266,7 +266,9 @@ let PostMenuItems = ({ feedContext: postFeedContext, reqId: postReqId, }) - Toast.show(_(msg({message: 'Feedback sent!', context: 'toast'}))) + Toast.show( + _(msg({message: 'Feedback sent to feed operator', context: 'toast'})), + ) } const onPressShowLess = () => { @@ -282,7 +284,9 @@ let PostMenuItems = ({ feedContext: postFeedContext, }) } else { - Toast.show(_(msg({message: 'Feedback sent!', context: 'toast'}))) + Toast.show( + _(msg({message: 'Feedback sent to feed operator', context: 'toast'})), + ) } } @@ -486,13 +490,16 @@ let PostMenuItems = ({ )} {isDiscoverDebugUser && ( - - {_(msg`Assign topic for algo`)} - - + <> + + + {_(msg`Assign topic for algo`)} + + + )} {hasSession && ( diff --git a/src/components/ProfileCard.tsx b/src/components/ProfileCard.tsx index f12d922fd3..095b621679 100644 --- a/src/components/ProfileCard.tsx +++ b/src/components/ProfileCard.tsx @@ -513,12 +513,19 @@ export function FollowButtonInner({ comment: 'User is following this account, click to unfollow', }), ) - const followLabel = _( - msg({ - message: 'Follow', - comment: 'User is not following this account, click to follow', - }), - ) + const followLabel = profile.viewer?.followedBy + ? _( + msg({ + message: 'Follow back', + comment: 'User is not following this account, click to follow back', + }), + ) + : _( + msg({ + message: 'Follow', + comment: 'User is not following this account, click to follow', + }), + ) if (!profile.viewer) return null if ( @@ -561,6 +568,24 @@ export function FollowButtonInner({ ) } +export function FollowButtonPlaceholder({style}: ViewStyleProp) { + const t = useTheme() + + return ( + + ) +} + export function Labels({ profile, moderationOpts, diff --git a/src/components/ProgressGuide/FollowDialog.tsx b/src/components/ProgressGuide/FollowDialog.tsx index 20ebb0abf8..f2eb4fa3d1 100644 --- a/src/components/ProgressGuide/FollowDialog.tsx +++ b/src/components/ProgressGuide/FollowDialog.tsx @@ -1,17 +1,9 @@ import {memo, useCallback, useEffect, useMemo, useRef, useState} from 'react' -import { - ScrollView, - type StyleProp, - TextInput, - useWindowDimensions, - View, - type ViewStyle, -} from 'react-native' +import {TextInput, useWindowDimensions, View} from 'react-native' import {type ModerationOpts} from '@atproto/api' import {msg, Trans} from '@lingui/macro' import {useLingui} from '@lingui/react' -import {useNonReactiveCallback} from '#/lib/hooks/useNonReactiveCallback' import {logEvent} from '#/lib/statsig/statsig' import {isWeb} from '#/platform/detection' import {useModerationOpts} from '#/state/preferences/moderation-opts' @@ -28,7 +20,6 @@ import { import { atoms as a, native, - tokens, useBreakpoints, useTheme, type ViewStyleProp, @@ -40,6 +31,7 @@ import {useInteractionState} from '#/components/hooks/useInteractionState' import {MagnifyingGlass2_Stroke2_Corner0_Rounded as SearchIcon} from '#/components/icons/MagnifyingGlass2' import {PersonGroup_Stroke2_Corner2_Rounded as PersonGroupIcon} from '#/components/icons/Person' import {TimesLarge_Stroke2_Corner0_Rounded as X} from '#/components/icons/Times' +import {boostInterests, InterestTabs} from '#/components/InterestTabs' import * as ProfileCard from '#/components/ProfileCard' import {Text} from '#/components/Typography' import type * as bsky from '#/types/bsky' @@ -337,12 +329,13 @@ let Header = ({ }} onEscape={control.close} /> - @@ -403,99 +396,6 @@ function HeaderTop({guide}: {guide: Follow10ProgressGuide}) { ) } -let Tabs = ({ - onSelectTab, - interests, - selectedInterest, - hasSearchText, - interestsDisplayNames, - TabComponent = Tab, - contentContainerStyle, -}: { - onSelectTab: (tab: string) => void - interests: string[] - selectedInterest: string - hasSearchText: boolean - interestsDisplayNames: Record - TabComponent?: React.ComponentType> - contentContainerStyle?: StyleProp -}): React.ReactNode => { - const listRef = useRef(null) - const [totalWidth, setTotalWidth] = useState(0) - const pendingTabOffsets = useRef<{x: number; width: number}[]>([]) - const [tabOffsets, setTabOffsets] = useState<{x: number; width: number}[]>([]) - - const onInitialLayout = useNonReactiveCallback(() => { - const index = interests.indexOf(selectedInterest) - scrollIntoViewIfNeeded(index) - }) - - useEffect(() => { - if (tabOffsets) { - onInitialLayout() - } - }, [tabOffsets, onInitialLayout]) - - function scrollIntoViewIfNeeded(index: number) { - const btnLayout = tabOffsets[index] - if (!btnLayout) return - listRef.current?.scrollTo({ - // centered - x: btnLayout.x - (totalWidth / 2 - btnLayout.width / 2), - animated: true, - }) - } - - function handleSelectTab(index: number) { - const tab = interests[index] - onSelectTab(tab) - scrollIntoViewIfNeeded(index) - } - - function handleTabLayout(index: number, x: number, width: number) { - if (!tabOffsets.length) { - pendingTabOffsets.current[index] = {x, width} - if (pendingTabOffsets.current.length === interests.length) { - setTabOffsets(pendingTabOffsets.current) - } - } - } - - return ( - o.x - tokens.space.xl) - : undefined - } - onLayout={evt => setTotalWidth(evt.nativeEvent.layout.width)} - scrollEventThrottle={200} // big throttle - > - {interests.map((interest, i) => { - const active = interest === selectedInterest && !hasSearchText - return ( - - ) - })} - - ) -} -Tabs = memo(Tabs) -export {Tabs} - let Tab = ({ onSelectTab, interest, @@ -513,24 +413,36 @@ let Tab = ({ }): React.ReactNode => { const t = useTheme() const {_} = useLingui() - const activeText = active ? _(msg` (active)`) : '' + const label = active + ? _( + msg({ + message: `Search for "${interestsDisplayName}" (active)`, + comment: + 'Accessibility label for a tab that searches for accounts in a category (e.g. Art, Video Games, Sports, etc.) that are suggested for the user to follow. The tab is currently selected.', + }), + ) + : _( + msg({ + message: `Search for "${interestsDisplayName}"`, + comment: + 'Accessibility label for a tab that searches for accounts in a category (e.g. Art, Video Games, Sports, etc.) that are suggested for the user to follow. The tab is not currently active and can be selected.', + }), + ) return ( onLayout(index, e.nativeEvent.layout.x, e.nativeEvent.layout.width) }> - + + ) +} + +/** + * Vibes-based number, provides t `top` value to wrap the text to compensate + * for different type sizes and keep the first line of text aligned with the + * icon. - esb + */ +function useToastFontScaleCompensation() { + const {fonts} = useAlf() const fontScaleCompensation = useMemo( () => parseInt(fonts.scale) * -1 * 0.65, [fonts.scale], ) - - return ( - ({type}), [type])}> - - - - - {typeof content === 'string' ? ( - {content} - ) : ( - content - )} - - - - ) -} - -export function ToastText({children}: {children: React.ReactNode}) { - const {type} = useContext(Context) - const {textColor} = useToastStyles({type}) - return ( - - {children} - + return useMemo( + () => ({ + fontScaleCompensation, + }), + [fontScaleCompensation], ) } diff --git a/src/components/Toast/index.e2e.tsx b/src/components/Toast/index.e2e.tsx index 357bd8dda9..a4056323dd 100644 --- a/src/components/Toast/index.e2e.tsx +++ b/src/components/Toast/index.e2e.tsx @@ -1,3 +1,11 @@ +export const DURATION = 0 + +export const Action = () => null +export const Icon = () => null +export const Outer = () => null +export const Text = () => null +export const ToastConfigProvider = () => null + export function ToastOutlet() { return null } diff --git a/src/components/Toast/index.tsx b/src/components/Toast/index.tsx index 286d414a14..d70a8ad164 100644 --- a/src/components/Toast/index.tsx +++ b/src/components/Toast/index.tsx @@ -1,15 +1,21 @@ +import React from 'react' import {View} from 'react-native' +import {nanoid} from 'nanoid/non-secure' import {toast as sonner, Toaster} from 'sonner-native' import {atoms as a} from '#/alf' import {DURATION} from '#/components/Toast/const' import { - Toast as BaseToast, - type ToastComponentProps, + Icon as ToastIcon, + Outer as BaseOuter, + Text as ToastText, + ToastConfigProvider, } from '#/components/Toast/Toast' import {type BaseToastOptions} from '#/components/Toast/types' export {DURATION} from '#/components/Toast/const' +export {Action, Icon, Text, ToastConfigProvider} from '#/components/Toast/Toast' +export {type ToastType} from '#/components/Toast/types' /** * Toasts are rendered in a global outlet, which is placed at the top of the @@ -19,13 +25,10 @@ export function ToastOutlet() { return } -/** - * The toast UI component - */ -export function Toast({type, content}: ToastComponentProps) { +export function Outer({children}: {children: React.ReactNode}) { return ( - + {children} ) } @@ -40,10 +43,38 @@ export const api = sonner */ export function show( content: React.ReactNode, - {type, ...options}: BaseToastOptions = {}, + {type = 'default', ...options}: BaseToastOptions = {}, ) { - sonner.custom(, { - ...options, - duration: options?.duration ?? DURATION, - }) + const id = nanoid() + + if (typeof content === 'string') { + sonner.custom( + + + + {content} + + , + { + ...options, + id, + duration: options?.duration ?? DURATION, + }, + ) + } else if (React.isValidElement(content)) { + sonner.custom( + + {content} + , + { + ...options, + id, + duration: options?.duration ?? DURATION, + }, + ) + } else { + throw new Error( + `Toast can be a string or a React element, got ${typeof content}`, + ) + } } diff --git a/src/components/Toast/index.web.tsx b/src/components/Toast/index.web.tsx index 857ed7b39a..8b2028db98 100644 --- a/src/components/Toast/index.web.tsx +++ b/src/components/Toast/index.web.tsx @@ -1,10 +1,21 @@ +import React from 'react' +import {nanoid} from 'nanoid/non-secure' import {toast as sonner, Toaster} from 'sonner' import {atoms as a} from '#/alf' import {DURATION} from '#/components/Toast/const' -import {Toast} from '#/components/Toast/Toast' +import { + Icon as ToastIcon, + Outer as ToastOuter, + Text as ToastText, + ToastConfigProvider, +} from '#/components/Toast/Toast' import {type BaseToastOptions} from '#/components/Toast/types' +export {DURATION} from '#/components/Toast/const' +export * from '#/components/Toast/Toast' +export {type ToastType} from '#/components/Toast/types' + /** * Toasts are rendered in a global outlet, which is placed at the top of the * component tree. @@ -30,11 +41,40 @@ export const api = sonner */ export function show( content: React.ReactNode, - {type, ...options}: BaseToastOptions = {}, + {type = 'default', ...options}: BaseToastOptions = {}, ) { - sonner(, { - unstyled: true, // required on web - ...options, - duration: options?.duration ?? DURATION, - }) + const id = nanoid() + + if (typeof content === 'string') { + sonner( + + + + {content} + + , + { + ...options, + unstyled: true, // required on web + id, + duration: options?.duration ?? DURATION, + }, + ) + } else if (React.isValidElement(content)) { + sonner( + + {content} + , + { + ...options, + unstyled: true, // required on web + id, + duration: options?.duration ?? DURATION, + }, + ) + } else { + throw new Error( + `Toast can be a string or a React element, got ${typeof content}`, + ) + } } diff --git a/src/components/Toast/sonner/index.ts b/src/components/Toast/sonner/index.ts new file mode 100644 index 0000000000..35f8552c72 --- /dev/null +++ b/src/components/Toast/sonner/index.ts @@ -0,0 +1,3 @@ +import {toast} from 'sonner-native' + +export const dismiss = toast.dismiss diff --git a/src/components/Toast/sonner/index.web.ts b/src/components/Toast/sonner/index.web.ts new file mode 100644 index 0000000000..12c4741d60 --- /dev/null +++ b/src/components/Toast/sonner/index.web.ts @@ -0,0 +1,3 @@ +import {toast} from 'sonner' + +export const dismiss = toast.dismiss diff --git a/src/components/dialogs/BirthDateSettings.tsx b/src/components/dialogs/BirthDateSettings.tsx index fecfc43bc1..0b8dfb5405 100644 --- a/src/components/dialogs/BirthDateSettings.tsx +++ b/src/components/dialogs/BirthDateSettings.tsx @@ -4,21 +4,23 @@ import {msg, Trans} from '@lingui/macro' import {useLingui} from '@lingui/react' import {cleanError} from '#/lib/strings/errors' -import {getDateAgo} from '#/lib/strings/time' +import {getAge, getDateAgo} from '#/lib/strings/time' import {logger} from '#/logger' import {isIOS, isWeb} from '#/platform/detection' import { usePreferencesQuery, - UsePreferencesQueryResponse, + type UsePreferencesQueryResponse, usePreferencesSetBirthDateMutation, } from '#/state/queries/preferences' import {ErrorMessage} from '#/view/com/util/error/ErrorMessage' -import {atoms as a, useTheme} from '#/alf' +import {atoms as a, useTheme, web} from '#/alf' +import {Admonition} from '#/components/Admonition' +import {Button, ButtonIcon, ButtonText} from '#/components/Button' import * as Dialog from '#/components/Dialog' import {DateField} from '#/components/forms/DateField' +import {InlineLinkText} from '#/components/Link' import {Loader} from '#/components/Loader' import {Text} from '#/components/Typography' -import {Button, ButtonIcon, ButtonText} from '../Button' export function BirthDateSettingsDialog({ control, @@ -32,31 +34,35 @@ export function BirthDateSettingsDialog({ return ( - - - + + + My Birthday - - This information is not shared with other users. + + + This information is private and not shared with other users. + - - {isLoading ? ( - - ) : error || !preferences ? ( - - ) : ( - - )} + {isLoading ? ( + + ) : error || !preferences ? ( + + ) : ( + + )} + @@ -72,7 +78,9 @@ function BirthdayInner({ preferences: UsePreferencesQueryResponse }) { const {_} = useLingui() - const [date, setDate] = React.useState(preferences.birthDate || new Date()) + const [date, setDate] = React.useState( + preferences.birthDate || getDateAgo(18), + ) const { isPending, isError, @@ -81,6 +89,10 @@ function BirthdayInner({ } = usePreferencesSetBirthDateMutation() const hasChanged = date !== preferences.birthDate + const age = getAge(new Date(date)) + const isUnder13 = age < 13 + const isUnder18 = age >= 13 && age < 18 + const onSave = React.useCallback(async () => { try { // skip if date is the same @@ -102,10 +114,32 @@ function BirthdayInner({ onChangeDate={newDate => setDate(new Date(newDate))} label={_(msg`Birthday`)} accessibilityHint={_(msg`Enter your birth date`)} - maximumDate={getDateAgo(13)} /> + {isUnder18 && hasChanged && ( + + + The birthdate you've entered means you are under 18 years old. + Certain content and features may be unavailable to you. + + + )} + + {isUnder13 && ( + + + You must be at least 13 years old to use Bluesky. Read our{' '} + + Terms of Service + {' '} + for more information. + + + )} + {isError ? ( ) : undefined} @@ -116,7 +150,8 @@ function BirthdayInner({ size="large" onPress={onSave} variant="solid" - color="primary"> + color="primary" + disabled={isUnder13}> {hasChanged ? Save : Done} diff --git a/src/components/dialogs/GifSelect.tsx b/src/components/dialogs/GifSelect.tsx index e18fdf2dba..15c1ba26e8 100644 --- a/src/components/dialogs/GifSelect.tsx +++ b/src/components/dialogs/GifSelect.tsx @@ -1,4 +1,4 @@ -import React, { +import { useCallback, useImperativeHandle, useMemo, @@ -119,7 +119,7 @@ function GifList({ [onSelectGif], ) - const onEndReached = React.useCallback(() => { + const onEndReached = useCallback(() => { if (isFetchingNextPage || !hasNextPage || error) return fetchNextPage() }, [isFetchingNextPage, hasNextPage, error, fetchNextPage]) @@ -172,7 +172,7 @@ function GifList({ )} - + {listHeader} diff --git a/src/components/dialogs/StarterPackDialog.tsx b/src/components/dialogs/StarterPackDialog.tsx new file mode 100644 index 0000000000..c4b8a72c4d --- /dev/null +++ b/src/components/dialogs/StarterPackDialog.tsx @@ -0,0 +1,395 @@ +import {useCallback, useState} from 'react' +import {View} from 'react-native' +import { + type AppBskyGraphGetStarterPacksWithMembership, + AppBskyGraphStarterpack, +} from '@atproto/api' +import {msg, Plural, Trans} from '@lingui/macro' +import {useLingui} from '@lingui/react' +import {useNavigation} from '@react-navigation/native' +import {useQueryClient} from '@tanstack/react-query' + +import {useRequireEmailVerification} from '#/lib/hooks/useRequireEmailVerification' +import {type NavigationProp} from '#/lib/routes/types' +import {isWeb} from '#/platform/detection' +import { + invalidateActorStarterPacksWithMembershipQuery, + useActorStarterPacksWithMembershipsQuery, +} from '#/state/queries/actor-starter-packs' +import { + useListMembershipAddMutation, + useListMembershipRemoveMutation, +} from '#/state/queries/list-memberships' +import * as Toast from '#/view/com/util/Toast' +import {atoms as a, useTheme} from '#/alf' +import {AvatarStack} from '#/components/AvatarStack' +import {Button, ButtonIcon, ButtonText} from '#/components/Button' +import * as Dialog from '#/components/Dialog' +import {Divider} from '#/components/Divider' +import {PlusLarge_Stroke2_Corner0_Rounded as PlusIcon} from '#/components/icons/Plus' +import {StarterPack} from '#/components/icons/StarterPack' +import {TimesLarge_Stroke2_Corner0_Rounded as XIcon} from '#/components/icons/Times' +import {Loader} from '#/components/Loader' +import {Text} from '#/components/Typography' +import * as bsky from '#/types/bsky' + +type StarterPackWithMembership = + AppBskyGraphGetStarterPacksWithMembership.StarterPackWithMembership + +export type StarterPackDialogProps = { + control: Dialog.DialogControlProps + targetDid: string + enabled?: boolean +} + +export function StarterPackDialog({ + control, + targetDid, + enabled, +}: StarterPackDialogProps) { + const {_} = useLingui() + const navigation = useNavigation() + const requireEmailVerification = useRequireEmailVerification() + + const navToWizard = useCallback(() => { + control.close() + navigation.navigate('StarterPackWizard', { + fromDialog: true, + targetDid: targetDid, + onSuccess: () => { + setTimeout(() => { + if (!control.isOpen) { + control.open() + } + }, 0) + }, + }) + }, [navigation, control, targetDid]) + + const wrappedNavToWizard = requireEmailVerification(navToWizard, { + instructions: [ + + Before creating a starter pack, you must first verify your email. + , + ], + }) + + return ( + + + + + ) +} + +function Empty({onStartWizard}: {onStartWizard: () => void}) { + const {_} = useLingui() + const t = useTheme() + + return ( + + + + + You have no starter packs. + + + + + + + + ) +} + +function StarterPackList({ + control, + onStartWizard, + targetDid, + enabled, +}: { + control: Dialog.DialogControlProps + onStartWizard: () => void + targetDid: string + enabled?: boolean +}) { + const {_} = useLingui() + + const { + data, + refetch, + isError, + isLoading, + hasNextPage, + isFetchingNextPage, + fetchNextPage, + } = useActorStarterPacksWithMembershipsQuery({did: targetDid, enabled}) + + const membershipItems = + data?.pages.flatMap(page => page.starterPacksWithMembership) || [] + + const _onRefresh = useCallback(async () => { + try { + await refetch() + } catch (err) { + // Error handling is optional since this is just a refresh + } + }, [refetch]) + + const _onEndReached = useCallback(async () => { + if (isFetchingNextPage || !hasNextPage || isError) return + try { + await fetchNextPage() + } catch (err) { + // Error handling is optional since this is just pagination + } + }, [isFetchingNextPage, hasNextPage, isError, fetchNextPage]) + + const renderItem = useCallback( + ({item}: {item: StarterPackWithMembership}) => ( + + ), + [targetDid], + ) + + const onClose = useCallback(() => { + control.close() + }, [control]) + + const listHeader = ( + <> + + + Add to starter packs + + + + {membershipItems.length > 0 && ( + <> + + + New starter pack + + + + + + )} + + ) + + return ( + ( + + + + ) + : renderItem + } + keyExtractor={ + isLoading + ? () => 'starter_pack_dialog_loader' + : (item: StarterPackWithMembership) => item.starterPack.uri + } + refreshing={false} + onRefresh={_onRefresh} + onEndReached={_onEndReached} + onEndReachedThreshold={0.1} + ListHeaderComponent={listHeader} + ListEmptyComponent={} + style={isWeb ? [a.px_md, {minHeight: 500}] : [a.px_2xl, a.pt_lg]} + /> + ) +} + +function StarterPackItem({ + starterPackWithMembership, + targetDid, +}: { + starterPackWithMembership: StarterPackWithMembership + targetDid: string +}) { + const {_} = useLingui() + const t = useTheme() + const queryClient = useQueryClient() + + const starterPack = starterPackWithMembership.starterPack + const isInPack = !!starterPackWithMembership.listItem + + const [isPendingRefresh, setIsPendingRefresh] = useState(false) + + const {mutate: addMembership} = useListMembershipAddMutation({ + onSuccess: () => { + Toast.show(_(msg`Added to starter pack`)) + // Use a timeout to wait for the appview to update, matching the pattern + // in list-memberships.ts + setTimeout(() => { + invalidateActorStarterPacksWithMembershipQuery({ + queryClient, + did: targetDid, + }) + setIsPendingRefresh(false) + }, 1e3) + }, + onError: () => { + Toast.show(_(msg`Failed to add to starter pack`), 'xmark') + setIsPendingRefresh(false) + }, + }) + + const {mutate: removeMembership} = useListMembershipRemoveMutation({ + onSuccess: () => { + Toast.show(_(msg`Removed from starter pack`)) + // Use a timeout to wait for the appview to update, matching the pattern + // in list-memberships.ts + setTimeout(() => { + invalidateActorStarterPacksWithMembershipQuery({ + queryClient, + did: targetDid, + }) + setIsPendingRefresh(false) + }, 1e3) + }, + onError: () => { + Toast.show(_(msg`Failed to remove from starter pack`), 'xmark') + setIsPendingRefresh(false) + }, + }) + + const handleToggleMembership = () => { + if (!starterPack.list?.uri || isPendingRefresh) return + + const listUri = starterPack.list.uri + + setIsPendingRefresh(true) + + if (!isInPack) { + addMembership({ + listUri: listUri, + actorDid: targetDid, + }) + } else { + if (!starterPackWithMembership.listItem?.uri) { + console.error('Cannot remove: missing membership URI') + setIsPendingRefresh(false) + return + } + removeMembership({ + listUri: listUri, + actorDid: targetDid, + membershipUri: starterPackWithMembership.listItem.uri, + }) + } + } + + const {record} = starterPack + + if ( + !bsky.dangerousIsType( + record, + AppBskyGraphStarterpack.isRecord, + ) + ) { + return null + } + + return ( + + + + {record.name} + + + + {starterPack.listItemsSample && + starterPack.listItemsSample.length > 0 && ( + <> + p.subject)} + /> + + {starterPack.list?.listItemCount && + starterPack.list.listItemCount > 4 && ( + + + + + + )} + + )} + + + + + + ) +} diff --git a/src/components/dms/ConvoMenu.tsx b/src/components/dms/ConvoMenu.tsx index 8aa2335d0c..1b1ebbcd59 100644 --- a/src/components/dms/ConvoMenu.tsx +++ b/src/components/dms/ConvoMenu.tsx @@ -1,12 +1,12 @@ import React, {useCallback} from 'react' -import {Keyboard, Pressable, View} from 'react-native' -import {ChatBskyConvoDefs, ModerationCause} from '@atproto/api' +import {Keyboard, View} from 'react-native' +import {type ChatBskyConvoDefs, type ModerationCause} from '@atproto/api' import {msg, Trans} from '@lingui/macro' import {useLingui} from '@lingui/react' import {useNavigation} from '@react-navigation/native' -import {NavigationProp} from '#/lib/routes/types' -import {Shadow} from '#/state/cache/types' +import {type NavigationProp} from '#/lib/routes/types' +import {type Shadow} from '#/state/cache/types' import { useConvoQuery, useMarkAsReadMutation, @@ -14,11 +14,15 @@ import { import {useMuteConvo} from '#/state/queries/messages/mute-conversation' import {useProfileBlockMutationQueue} from '#/state/queries/profile' import * as Toast from '#/view/com/util/Toast' -import {atoms as a, useTheme, ViewStyleProp} from '#/alf' +import {type ViewStyleProp} from '#/alf' +import {atoms as a} from '#/alf' +import {Button, ButtonIcon} from '#/components/Button' import {BlockedByListDialog} from '#/components/dms/BlockedByListDialog' import {LeaveConvoPrompt} from '#/components/dms/LeaveConvoPrompt' import {ReportConversationPrompt} from '#/components/dms/ReportConversationPrompt' +import {ReportDialog} from '#/components/dms/ReportDialog' import {ArrowBoxLeft_Stroke2_Corner0_Rounded as ArrowBoxLeft} from '#/components/icons/ArrowBoxLeft' +import {Bubble_Stroke2_Corner2_Rounded as Bubble} from '#/components/icons/Bubble' import {DotGrid_Stroke2_Corner0_Rounded as DotsHorizontal} from '#/components/icons/DotGrid' import {Flag_Stroke2_Corner0_Rounded as Flag} from '#/components/icons/Flag' import {Mute_Stroke2_Corner0_Rounded as Mute} from '#/components/icons/Mute' @@ -30,9 +34,7 @@ import { import {SpeakerVolumeFull_Stroke2_Corner0_Rounded as Unmute} from '#/components/icons/Speaker' import * as Menu from '#/components/Menu' import * as Prompt from '#/components/Prompt' -import * as bsky from '#/types/bsky' -import {Bubble_Stroke2_Corner2_Rounded as Bubble} from '../icons/Bubble' -import {ReportDialog} from './ReportDialog' +import type * as bsky from '#/types/bsky' let ConvoMenu = ({ convo, @@ -59,7 +61,6 @@ let ConvoMenu = ({ style?: ViewStyleProp['style'] }): React.ReactNode => { const {_} = useLingui() - const t = useTheme() const leaveConvoControl = Prompt.usePromptControl() const reportControl = Prompt.usePromptControl() @@ -73,22 +74,21 @@ let ConvoMenu = ({ {!hideTrigger && ( - {({props, state}) => ( - ( + )} diff --git a/src/components/dms/MessagesListHeader.tsx b/src/components/dms/MessagesListHeader.tsx index c8ed98f88b..d37e4a34a5 100644 --- a/src/components/dms/MessagesListHeader.tsx +++ b/src/components/dms/MessagesListHeader.tsx @@ -1,48 +1,42 @@ -import React, {useCallback} from 'react' -import {TouchableOpacity, View} from 'react-native' +import {useMemo} from 'react' +import {View} from 'react-native' import { type AppBskyActorDefs, type ModerationCause, type ModerationDecision, } from '@atproto/api' -import {FontAwesomeIcon} from '@fortawesome/react-native-fontawesome' import {msg} from '@lingui/macro' import {useLingui} from '@lingui/react' -import {useNavigation} from '@react-navigation/native' -import {BACK_HITSLOP} from '#/lib/constants' import {makeProfileLink} from '#/lib/routes/links' -import {type NavigationProp} from '#/lib/routes/types' import {sanitizeDisplayName} from '#/lib/strings/display-names' import {isWeb} from '#/platform/detection' import {type Shadow} from '#/state/cache/profile-shadow' import {isConvoActive, useConvo} from '#/state/messages/convo' import {type ConvoItem} from '#/state/messages/convo/types' import {PreviewableUserAvatar} from '#/view/com/util/UserAvatar' -import {atoms as a, useBreakpoints, useTheme, web} from '#/alf' +import {atoms as a, useTheme, web} from '#/alf' import {ConvoMenu} from '#/components/dms/ConvoMenu' import {Bell2Off_Filled_Corner0_Rounded as BellStroke} from '#/components/icons/Bell2' +import * as Layout from '#/components/Layout' import {Link} from '#/components/Link' import {PostAlerts} from '#/components/moderation/PostAlerts' import {Text} from '#/components/Typography' import {useSimpleVerificationState} from '#/components/verification' import {VerificationCheck} from '#/components/verification/VerificationCheck' -const PFP_SIZE = isWeb ? 40 : 34 +const PFP_SIZE = isWeb ? 40 : Layout.HEADER_SLOT_SIZE -export let MessagesListHeader = ({ +export function MessagesListHeader({ profile, moderation, }: { profile?: Shadow moderation?: ModerationDecision -}): React.ReactNode => { +}) { const t = useTheme() - const {_} = useLingui() - const {gtTablet} = useBreakpoints() - const navigation = useNavigation() - const blockInfo = React.useMemo(() => { + const blockInfo = useMemo(() => { if (!moderation) return const modui = moderation.ui('profileView') const blocks = modui.alerts.filter(alert => alert.type === 'blocking') @@ -54,87 +48,54 @@ export let MessagesListHeader = ({ } }, [moderation]) - const onPressBack = useCallback(() => { - if (navigation.canGoBack()) { - navigation.goBack() - } else { - navigation.navigate('Messages', {}) - } - }, [navigation]) - return ( - - - - - - {profile && moderation && blockInfo ? ( - - ) : ( - <> - - - + + + + + + {profile && moderation && blockInfo ? ( + + ) : ( + <> + - + + + + - - - - )} - + + + )} + + ) } -MessagesListHeader = React.memo(MessagesListHeader) function HeaderReady({ profile, @@ -181,15 +142,13 @@ function HeaderReady({ label={_(msg`View ${displayName}'s profile`)} style={[a.flex_row, a.align_start, a.gap_md, a.flex_1, a.pr_md]} to={makeProfileLink(profile)}> - - - - + + @@ -235,15 +194,19 @@ function HeaderReady({ - {isConvoActive(convoState) && ( - - )} + + + {isConvoActive(convoState) && ( + + )} + + +export type RootProps = React.PropsWithChildren< + {isInvalid?: boolean} & TextStyleProp +> -export function Root({children, isInvalid = false}: RootProps) { +export function Root({children, isInvalid = false, style}: RootProps) { const inputRef = useRef(null) const { state: hovered, @@ -85,7 +87,14 @@ export function Root({children, isInvalid = false}: RootProps) { return ( inputRef.current?.focus(), onMouseOver: onHoverIn, diff --git a/src/components/forms/Toggle.tsx b/src/components/forms/Toggle.tsx index 9c3564aa54..bb9fde2e11 100644 --- a/src/components/forms/Toggle.tsx +++ b/src/components/forms/Toggle.tsx @@ -1,5 +1,5 @@ import React from 'react' -import {Pressable, View, type ViewStyle} from 'react-native' +import {Pressable, type StyleProp, View, type ViewStyle} from 'react-native' import Animated, {LinearTransition} from 'react-native-reanimated' import {HITSLOP_10} from '#/lib/constants' @@ -59,6 +59,7 @@ export type GroupProps = React.PropsWithChildren<{ disabled?: boolean onChange: (value: string[]) => void label: string + style?: StyleProp }> export type ItemProps = ViewStyleProp & { @@ -84,6 +85,7 @@ export function Group({ type = 'checkbox', maxSelections, label, + style, }: GroupProps) { const groupRole = type === 'radio' ? 'radiogroup' : undefined const values = type === 'radio' ? providedValues.slice(0, 1) : providedValues @@ -136,7 +138,7 @@ export function Group({ return ( & { + markFill?: Props['fill'] + textFill?: Props['fill'] + }, +) { + const {fill, size, style, gradient, ...rest} = useCommonSVGProps(props) + const ratio = 123 / 555 + + return ( + + {gradient} + + + + ) +} diff --git a/src/components/interstitials/TrendingVideos.tsx b/src/components/interstitials/TrendingVideos.tsx index 4d59e2fb5c..6be64335a2 100644 --- a/src/components/interstitials/TrendingVideos.tsx +++ b/src/components/interstitials/TrendingVideos.tsx @@ -1,4 +1,4 @@ -import React, {useEffect} from 'react' +import {useCallback, useEffect, useMemo} from 'react' import {ScrollView, View} from 'react-native' import {AppBskyEmbedVideo, AtUri} from '@atproto/api' import {msg, Trans} from '@lingui/macro' @@ -55,7 +55,7 @@ export function TrendingVideos() { const {setTrendingVideoDisabled} = useTrendingSettingsApi() const trendingPrompt = Prompt.usePromptControl() - const onConfirmHide = React.useCallback(() => { + const onConfirmHide = useCallback(() => { setTrendingVideoDisabled(true) logEvent('trendingVideos:hide', {context: 'interstitial:discover'}) }, [setTrendingVideoDisabled]) @@ -147,9 +147,7 @@ function VideoCards({ }: { data: Exclude['data'], undefined> }) { - const t = useTheme() - const {_} = useLingui() - const items = React.useMemo(() => { + const items = useMemo(() => { return data.pages .flatMap(page => page.slices) .map(slice => slice.items[0]) @@ -157,10 +155,6 @@ function VideoCards({ .filter(item => AppBskyEmbedVideo.isView(item.post.embed)) .slice(0, 8) }, [data]) - const href = React.useMemo(() => { - const urip = new AtUri(VIDEO_FEED_URI) - return makeCustomFeedLink(urip.host, urip.rkey, undefined, 'discover') - }, []) return ( <> @@ -183,50 +177,58 @@ function VideoCards({ ))} - - - {({pressed}) => ( - - - View more - - - - - - )} - - + ) } + +function ViewMoreCard() { + const t = useTheme() + const {_} = useLingui() + + const href = useMemo(() => { + const urip = new AtUri(VIDEO_FEED_URI) + return makeCustomFeedLink(urip.host, urip.rkey, undefined, 'discover') + }, []) + + return ( + + + {({pressed}) => ( + + + View more + + + + )} + + + ) +} diff --git a/src/components/moderation/ContentHider.tsx b/src/components/moderation/ContentHider.tsx index 549a1b9f0a..79756c5613 100644 --- a/src/components/moderation/ContentHider.tsx +++ b/src/components/moderation/ContentHider.tsx @@ -215,7 +215,7 @@ function ContentHiderActive({ control.open() }} label={_( - msg`Learn more about the moderation applied to this content.`, + msg`Learn more about the moderation applied to this content`, )} style={[a.pt_sm]}> {state => ( diff --git a/src/components/verification/VerificationsDialog.tsx b/src/components/verification/VerificationsDialog.tsx index 447e39e970..99ed00eeba 100644 --- a/src/components/verification/VerificationsDialog.tsx +++ b/src/components/verification/VerificationsDialog.tsx @@ -147,7 +147,12 @@ function Inner({ - Learn more + Learn more diff --git a/src/components/verification/VerifierDialog.tsx b/src/components/verification/VerifierDialog.tsx index c62f018325..b4756a85b3 100644 --- a/src/components/verification/VerifierDialog.tsx +++ b/src/components/verification/VerifierDialog.tsx @@ -114,7 +114,12 @@ function Inner({ - Learn more + Learn more )} - + { - if (isNative) { - if (Keyboard.isVisible()) { - Keyboard.dismiss() - } - } - openModal({name: 'post-languages-settings'}) - }, [openModal]) - - const postLanguagesPref = toPostLanguages(langPrefs.postLanguage) - const items: DropdownItem[] = useMemo(() => { - let arr: DropdownItemButton[] = [] - - function add(commaSeparatedLangCodes: string) { - const langCodes = commaSeparatedLangCodes.split(',') - const langName = langCodes - .map(code => codeToLanguageName(code, langPrefs.appLanguage)) - .join(' + ') - - /* - * Filter out any duplicates - */ - if (arr.find((item: DropdownItemButton) => item.label === langName)) { - return - } - - arr.push({ - icon: - langCodes.every(code => - hasPostLanguage(langPrefs.postLanguage, code), - ) && langCodes.length === postLanguagesPref.length - ? ['fas', 'circle-dot'] - : ['far', 'circle'], - label: langName, - onPress() { - setLangPrefs.setPostLanguage(commaSeparatedLangCodes) - }, - }) - } - - if (postLanguagesPref.length) { - /* - * Re-join here after sanitization bc postLanguageHistory is an array of - * comma-separated strings too - */ - add(langPrefs.postLanguage) - } - - // comma-separted strings of lang codes that have been used in the past - for (const lang of langPrefs.postLanguageHistory) { - add(lang) - } - - return [ - {heading: true, label: _(msg`Post language`)}, - ...arr.slice(0, 6), - {sep: true}, - { - label: _(msg`Other...`), - onPress: onPressMore, - }, - ] - }, [onPressMore, langPrefs, setLangPrefs, postLanguagesPref, _]) - - return ( - - {postLanguagesPref.length > 0 ? ( - - {postLanguagesPref - .map(lang => codeToLanguageName(lang, langPrefs.appLanguage)) - .join(', ')} - - ) : ( - - )} - - ) -} - -const styles = StyleSheet.create({ - button: { - marginHorizontal: 15, - }, - label: { - maxWidth: 100, - }, -}) diff --git a/src/view/com/composer/select-language/SelectPostLanguagesDialog.tsx b/src/view/com/composer/select-language/SelectPostLanguagesDialog.tsx new file mode 100644 index 0000000000..c8ecc2b89b --- /dev/null +++ b/src/view/com/composer/select-language/SelectPostLanguagesDialog.tsx @@ -0,0 +1,382 @@ +import {useCallback, useMemo, useState} from 'react' +import {Keyboard, useWindowDimensions, View} from 'react-native' +import {useSafeAreaInsets} from 'react-native-safe-area-context' +import {msg, Trans} from '@lingui/macro' +import {useLingui} from '@lingui/react' + +import {LANG_DROPDOWN_HITSLOP} from '#/lib/constants' +import {languageName} from '#/locale/helpers' +import {codeToLanguageName} from '#/locale/helpers' +import {type Language, LANGUAGES, LANGUAGES_MAP_CODE2} from '#/locale/languages' +import {isNative, isWeb} from '#/platform/detection' +import { + toPostLanguages, + useLanguagePrefs, + useLanguagePrefsApi, +} from '#/state/preferences/languages' +import {ErrorScreen} from '#/view/com/util/error/ErrorScreen' +import {ErrorBoundary} from '#/view/com/util/ErrorBoundary' +import {atoms as a, useTheme, web} from '#/alf' +import {Button, ButtonIcon, ButtonText} from '#/components/Button' +import * as Dialog from '#/components/Dialog' +import {SearchInput} from '#/components/forms/SearchInput' +import * as Toggle from '#/components/forms/Toggle' +import {Globe_Stroke2_Corner0_Rounded as GlobeIcon} from '#/components/icons/Globe' +import {TimesLarge_Stroke2_Corner0_Rounded as XIcon} from '#/components/icons/Times' +import {Text} from '#/components/Typography' + +export function SelectPostLanguagesBtn() { + const {_} = useLingui() + const langPrefs = useLanguagePrefs() + const t = useTheme() + const control = Dialog.useDialogControl() + + const onPressMore = useCallback(async () => { + if (isNative) { + if (Keyboard.isVisible()) { + Keyboard.dismiss() + } + } + control.open() + }, [control]) + + const postLanguagesPref = toPostLanguages(langPrefs.postLanguage) + + return ( + <> + + + + + ) +} + +function LanguageDialog({control}: {control: Dialog.DialogControlProps}) { + const {height} = useWindowDimensions() + const insets = useSafeAreaInsets() + + const renderErrorBoundary = useCallback( + (error: any) => , + [], + ) + + return ( + + + + + + + ) +} + +export function PostLanguagesSettingsDialogInner() { + const control = Dialog.useDialogContext() + const [headerHeight, setHeaderHeight] = useState(0) + + const allowedLanguages = useMemo(() => { + const uniqueLanguagesMap = LANGUAGES.filter(lang => !!lang.code2).reduce( + (acc, lang) => { + acc[lang.code2] = lang + return acc + }, + {} as Record, + ) + + return Object.values(uniqueLanguagesMap) + }, []) + + const langPrefs = useLanguagePrefs() + const [checkedLanguagesCode2, setCheckedLanguagesCode2] = useState( + langPrefs.postLanguage.split(',') || [langPrefs.primaryLanguage], + ) + const [search, setSearch] = useState('') + + const setLangPrefs = useLanguagePrefsApi() + const t = useTheme() + const {_} = useLingui() + + const handleClose = () => { + control.close(() => { + let langsString = checkedLanguagesCode2.join(',') + if (!langsString) { + langsString = langPrefs.primaryLanguage + } + setLangPrefs.setPostLanguage(langsString) + }) + } + + // NOTE(@elijaharita): Displayed languages are split into 3 lists for + // ordering. + const displayedLanguages = useMemo(() => { + function mapCode2List(code2List: string[]) { + return code2List.map(code2 => LANGUAGES_MAP_CODE2[code2]).filter(Boolean) + } + + // NOTE(@elijaharita): Get recent language codes and map them to language + // objects. Both the user account's saved language history and the current + // checked languages are displayed here. + const recentLanguagesCode2 = + Array.from( + new Set([...checkedLanguagesCode2, ...langPrefs.postLanguageHistory]), + ).slice(0, 5) || [] + const recentLanguages = mapCode2List(recentLanguagesCode2) + + // NOTE(@elijaharita): helper functions + const matchesSearch = (lang: Language) => + lang.name.toLowerCase().includes(search.toLowerCase()) + const isChecked = (lang: Language) => + checkedLanguagesCode2.includes(lang.code2) + const isInRecents = (lang: Language) => + recentLanguagesCode2.includes(lang.code2) + + const checkedRecent = recentLanguages.filter(isChecked) + + if (search) { + // NOTE(@elijaharita): if a search is active, we ALWAYS show checked + // items, as well as any items that match the search. + const uncheckedRecent = recentLanguages + .filter(lang => !isChecked(lang)) + .filter(matchesSearch) + const unchecked = allowedLanguages.filter(lang => !isChecked(lang)) + const all = unchecked + .filter(matchesSearch) + .filter(lang => !isInRecents(lang)) + + return { + all, + checkedRecent, + uncheckedRecent, + } + } else { + // NOTE(@elijaharita): if no search is active, we show everything. + const uncheckedRecent = recentLanguages.filter(lang => !isChecked(lang)) + const all = allowedLanguages + .filter(lang => !recentLanguagesCode2.includes(lang.code2)) + .filter(lang => !isInRecents(lang)) + + return { + all, + checkedRecent, + uncheckedRecent, + } + } + }, [ + allowedLanguages, + search, + langPrefs.postLanguageHistory, + checkedLanguagesCode2, + ]) + + const listHeader = ( + setHeaderHeight(evt.nativeEvent.layout.height)}> + + + + Choose Post Languages + + + Select up to 3 languages used in this post + + + + {isWeb && ( + + )} + + + + setSearch('')} + /> + + + ) + + const isCheckedRecentEmpty = + displayedLanguages.checkedRecent.length > 0 || + displayedLanguages.uncheckedRecent.length > 0 + + const isDisplayedLanguagesEmpty = displayedLanguages.all.length === 0 + + const flatListData = [ + ...(isCheckedRecentEmpty + ? [{type: 'header', label: _(msg`Recently used`)}] + : []), + ...displayedLanguages.checkedRecent.map(lang => ({type: 'item', lang})), + ...displayedLanguages.uncheckedRecent.map(lang => ({type: 'item', lang})), + ...(isDisplayedLanguagesEmpty + ? [] + : [{type: 'header', label: _(msg`All languages`)}]), + ...displayedLanguages.all.map(lang => ({type: 'item', lang})), + ] + + return ( + + { + if (item.type === 'header') { + return ( + + {item.label} + + ) + } + const lang = item.lang + + return ( + + + {languageName(lang, langPrefs.appLanguage)} + + + + ) + }} + footer={ + + + + } + /> + + ) +} + +function DialogError({details}: {details?: string}) { + const {_} = useLingui() + const control = Dialog.useDialogContext() + + return ( + + + + + + ) +} diff --git a/src/view/com/composer/text-input/TextInput.tsx b/src/view/com/composer/text-input/TextInput.tsx index ea92d0b913..8b3e61b0e9 100644 --- a/src/view/com/composer/text-input/TextInput.tsx +++ b/src/view/com/composer/text-input/TextInput.tsx @@ -1,7 +1,6 @@ -import React, { - type ComponentProps, - forwardRef, +import { useCallback, + useImperativeHandle, useMemo, useRef, useState, @@ -9,7 +8,6 @@ import React, { import { type NativeSyntheticEvent, Text as RNText, - type TextInput as RNTextInput, type TextInputSelectionChangeEventData, View, } from 'react-native' @@ -33,57 +31,38 @@ import { import {atoms as a, useAlf} from '#/alf' import {normalizeTextStyles} from '#/alf/typography' import {Autocomplete} from './mobile/Autocomplete' - -export interface TextInputRef { - focus: () => void - blur: () => void - getCursorPosition: () => DOMRect | undefined -} - -interface TextInputProps extends ComponentProps { - richtext: RichText - placeholder: string - webForceMinHeight: boolean - hasRightPadding: boolean - isActive: boolean - setRichText: (v: RichText) => void - onPhotoPasted: (uri: string) => void - onPressPublish: (richtext: RichText) => void - onNewLink: (uri: string) => void - onError: (err: string) => void -} +import {type TextInputProps} from './TextInput.types' interface Selection { start: number end: number } -export const TextInput = forwardRef(function TextInputImpl( - { - richtext, - placeholder, - hasRightPadding, - setRichText, - onPhotoPasted, - onNewLink, - onError, - ...props - }: TextInputProps, +export function TextInput({ ref, -) { + richtext, + placeholder, + hasRightPadding, + setRichText, + onPhotoPasted, + onNewLink, + onError, + ...props +}: TextInputProps) { const {theme: t, fonts} = useAlf() const textInput = useRef(null) const textInputSelection = useRef({start: 0, end: 0}) const theme = useTheme() const [autocompletePrefix, setAutocompletePrefix] = useState('') - const prevLength = React.useRef(richtext.length) + const prevLength = useRef(richtext.length) - React.useImperativeHandle(ref, () => ({ + useImperativeHandle(ref, () => ({ focus: () => textInput.current?.focus(), blur: () => { textInput.current?.blur() }, getCursorPosition: () => undefined, // Not implemented on native + maybeClosePopup: () => false, // Not needed on native })) const pastSuggestedUris = useRef(new Set()) @@ -185,7 +164,7 @@ export const TextInput = forwardRef(function TextInputImpl( [onChangeText, richtext, setAutocompletePrefix], ) - const inputTextStyle = React.useMemo(() => { + const inputTextStyle = useMemo(() => { const style = normalizeTextStyles( [a.text_lg, a.leading_snug, t.atoms.text], { @@ -277,4 +256,4 @@ export const TextInput = forwardRef(function TextInputImpl( /> ) -}) +} diff --git a/src/view/com/composer/text-input/TextInput.types.ts b/src/view/com/composer/text-input/TextInput.types.ts new file mode 100644 index 0000000000..fab2bc32f8 --- /dev/null +++ b/src/view/com/composer/text-input/TextInput.types.ts @@ -0,0 +1,42 @@ +import {type TextInput} from 'react-native' +import {type RichText} from '@atproto/api' + +export type TextInputRef = { + focus: () => void + blur: () => void + /** + * @platform web + */ + getCursorPosition: () => + | {left: number; right: number; top: number; bottom: number} + | undefined + /** + * Closes the autocomplete popup if it is open. + * Returns `true` if the popup was closed, `false` otherwise. + * + * @platform web + */ + maybeClosePopup: () => boolean +} + +export type TextInputProps = { + ref: React.Ref + richtext: RichText + webForceMinHeight: boolean + hasRightPadding: boolean + isActive: boolean + setRichText: (v: RichText) => void + onPhotoPasted: (uri: string) => void + onPressPublish: (richtext: RichText) => void + onNewLink: (uri: string) => void + onError: (err: string) => void + onFocus: () => void +} & Pick< + React.ComponentProps, + | 'placeholder' + | 'autoFocus' + | 'style' + | 'accessible' + | 'accessibilityLabel' + | 'accessibilityHint' +> diff --git a/src/view/com/composer/text-input/TextInput.web.tsx b/src/view/com/composer/text-input/TextInput.web.tsx index cb7ed194ac..9f6cc6ae22 100644 --- a/src/view/com/composer/text-input/TextInput.web.tsx +++ b/src/view/com/composer/text-input/TextInput.web.tsx @@ -1,4 +1,11 @@ -import React, {useRef} from 'react' +import { + useCallback, + useEffect, + useImperativeHandle, + useMemo, + useRef, + useState, +} from 'react' import {StyleSheet, View} from 'react-native' import Animated, {FadeIn, FadeOut} from 'react-native-reanimated' import {AppBskyRichtextFacet, RichText} from '@atproto/api' @@ -16,7 +23,6 @@ import {EditorContent, type JSONContent, useEditor} from '@tiptap/react' import Graphemer from 'graphemer' import {useColorSchemeStyle} from '#/lib/hooks/useColorSchemeStyle' -import {usePalette} from '#/lib/hooks/usePalette' import {blobToDataUri, isUriImage} from '#/lib/media/util' import {useActorAutocompleteFn} from '#/state/queries/actor-autocomplete' import { @@ -27,57 +33,34 @@ import {textInputWebEmitter} from '#/view/com/composer/text-input/textInputWebEm import {atoms as a, useAlf} from '#/alf' import {normalizeTextStyles} from '#/alf/typography' import {Portal} from '#/components/Portal' -import {Text} from '../../util/text/Text' -import {createSuggestion} from './web/Autocomplete' +import {Text} from '#/components/Typography' +import {type TextInputProps} from './TextInput.types' +import {type AutocompleteRef, createSuggestion} from './web/Autocomplete' import {type Emoji} from './web/EmojiPicker' import {LinkDecorator} from './web/LinkDecorator' import {TagDecorator} from './web/TagDecorator' -export interface TextInputRef { - focus: () => void - blur: () => void - getCursorPosition: () => DOMRect | undefined -} - -interface TextInputProps { - richtext: RichText - placeholder: string - suggestedLinks: Set - webForceMinHeight: boolean - hasRightPadding: boolean - isActive: boolean - setRichText: (v: RichText | ((v: RichText) => RichText)) => void - onPhotoPasted: (uri: string) => void - onPressPublish: (richtext: RichText) => void - onNewLink: (uri: string) => void - onError: (err: string) => void - onFocus: () => void -} - -export const TextInput = React.forwardRef(function TextInputImpl( - { - richtext, - placeholder, - webForceMinHeight, - hasRightPadding, - isActive, - setRichText, - onPhotoPasted, - onPressPublish, - onNewLink, - onFocus, - }: // onError, TODO - TextInputProps, +export function TextInput({ ref, -) { + richtext, + placeholder, + webForceMinHeight, + hasRightPadding, + isActive, + setRichText, + onPhotoPasted, + onPressPublish, + onNewLink, + onFocus, +}: TextInputProps) { const {theme: t, fonts} = useAlf() const autocomplete = useActorAutocompleteFn() - const pal = usePalette('default') const modeClass = useColorSchemeStyle('ProseMirror-light', 'ProseMirror-dark') - const [isDropping, setIsDropping] = React.useState(false) + const [isDropping, setIsDropping] = useState(false) + const autocompleteRef = useRef(null) - const extensions = React.useMemo( + const extensions = useMemo( () => [ Document, LinkDecorator, @@ -86,7 +69,7 @@ export const TextInput = React.forwardRef(function TextInputImpl( HTMLAttributes: { class: 'mention', }, - suggestion: createSuggestion({autocomplete}), + suggestion: createSuggestion({autocomplete, autocompleteRef}), }), Paragraph, Placeholder.configure({ @@ -99,7 +82,7 @@ export const TextInput = React.forwardRef(function TextInputImpl( [autocomplete, placeholder], ) - React.useEffect(() => { + useEffect(() => { if (!isActive) { return } @@ -109,7 +92,7 @@ export const TextInput = React.forwardRef(function TextInputImpl( } }, [onPressPublish, isActive]) - React.useEffect(() => { + useEffect(() => { if (!isActive) { return } @@ -119,7 +102,7 @@ export const TextInput = React.forwardRef(function TextInputImpl( } }, [isActive, onPhotoPasted]) - React.useEffect(() => { + useEffect(() => { if (!isActive) { return } @@ -296,13 +279,13 @@ export const TextInput = React.forwardRef(function TextInputImpl( [modeClass], ) - const onEmojiInserted = React.useCallback( + const onEmojiInserted = useCallback( (emoji: Emoji) => { editor?.chain().focus().insertContent(emoji.native).run() }, [editor], ) - React.useEffect(() => { + useEffect(() => { if (!isActive) { return } @@ -312,7 +295,7 @@ export const TextInput = React.forwardRef(function TextInputImpl( } }, [onEmojiInserted, isActive]) - React.useImperativeHandle(ref, () => ({ + useImperativeHandle(ref, () => ({ focus: () => { editor?.chain().focus() }, @@ -323,9 +306,10 @@ export const TextInput = React.forwardRef(function TextInputImpl( const pos = editor?.state.selection.$anchor.pos return pos ? editor?.view.coordsAtPos(pos) : undefined }, + maybeClosePopup: () => autocompleteRef.current?.maybeClose() ?? false, })) - const inputStyle = React.useMemo(() => { + const inputStyle = useMemo(() => { const style = normalizeTextStyles( [a.text_lg, a.leading_snug, t.atoms.text], { @@ -360,10 +344,20 @@ export const TextInput = React.forwardRef(function TextInputImpl( style={styles.dropContainer} entering={FadeIn.duration(80)} exiting={FadeOut.duration(80)}> - + + style={[ + a.text_lg, + a.font_bold, + t.atoms.text_contrast_medium, + t.atoms.border_contrast_high, + styles.dropText, + ]}> Drop to add images @@ -372,7 +366,7 @@ export const TextInput = React.forwardRef(function TextInputImpl( )} ) -}) +} function editorJsonToText( json: JSONContent, diff --git a/src/view/com/composer/text-input/web/Autocomplete.tsx b/src/view/com/composer/text-input/web/Autocomplete.tsx index 94ecb53ccb..1a95736c3d 100644 --- a/src/view/com/composer/text-input/web/Autocomplete.tsx +++ b/src/view/com/composer/text-input/web/Autocomplete.tsx @@ -1,6 +1,6 @@ import {forwardRef, useEffect, useImperativeHandle, useState} from 'react' -import {Pressable, StyleSheet, View} from 'react-native' -import {type AppBskyActorDefs} from '@atproto/api' +import {Pressable, View} from 'react-native' +import {type AppBskyActorDefs, type ModerationOpts} from '@atproto/api' import {Trans} from '@lingui/macro' import {ReactRenderer} from '@tiptap/react' import { @@ -10,25 +10,26 @@ import { } from '@tiptap/suggestion' import tippy, {type Instance as TippyInstance} from 'tippy.js' -import {usePalette} from '#/lib/hooks/usePalette' -import {sanitizeDisplayName} from '#/lib/strings/display-names' -import {sanitizeHandle} from '#/lib/strings/handles' +import {useModerationOpts} from '#/state/preferences/moderation-opts' import {type ActorAutocompleteFn} from '#/state/queries/actor-autocomplete' -import {Text} from '#/view/com/util/text/Text' -import {UserAvatar} from '#/view/com/util/UserAvatar' -import {atoms as a} from '#/alf' -import {useSimpleVerificationState} from '#/components/verification' -import {VerificationCheck} from '#/components/verification/VerificationCheck' -import {useGrapheme} from '../hooks/useGrapheme' +import {atoms as a, useTheme} from '#/alf' +import * as ProfileCard from '#/components/ProfileCard' +import {Text} from '#/components/Typography' interface MentionListRef { onKeyDown: (props: SuggestionKeyDownProps) => boolean } +export interface AutocompleteRef { + maybeClose: () => boolean +} + export function createSuggestion({ autocomplete, + autocompleteRef, }: { autocomplete: ActorAutocompleteFn + autocompleteRef: React.Ref }): Omit { return { async items({query}) { @@ -40,10 +41,15 @@ export function createSuggestion({ let component: ReactRenderer | undefined let popup: TippyInstance[] | undefined + const hide = () => { + popup?.[0]?.destroy() + component?.destroy() + } + return { onStart: props => { component = new ReactRenderer(MentionList, { - props, + props: {...props, autocompleteRef, hide}, editor: props.editor, }) @@ -78,204 +84,163 @@ export function createSuggestion({ onKeyDown(props) { if (props.event.key === 'Escape') { - popup?.[0]?.hide() - - return true + return false } return component?.ref?.onKeyDown(props) || false }, onExit() { - popup?.[0]?.destroy() - component?.destroy() + hide() }, } }, } } -const MentionList = forwardRef( - function MentionListImpl(props: SuggestionProps, ref) { - const [selectedIndex, setSelectedIndex] = useState(0) - const pal = usePalette('default') +const MentionList = forwardRef< + MentionListRef, + SuggestionProps & { + autocompleteRef: React.Ref + hide: () => void + } +>(function MentionListImpl({items, command, hide, autocompleteRef}, ref) { + const [selectedIndex, setSelectedIndex] = useState(0) + const t = useTheme() + const moderationOpts = useModerationOpts() - const selectItem = (index: number) => { - const item = props.items[index] + const selectItem = (index: number) => { + const item = items[index] - if (item) { - props.command({id: item.handle}) + if (item) { + command({id: item.handle}) + } + } + + const upHandler = () => { + setSelectedIndex((selectedIndex + items.length - 1) % items.length) + } + + const downHandler = () => { + setSelectedIndex((selectedIndex + 1) % items.length) + } + + const enterHandler = () => { + selectItem(selectedIndex) + } + + useEffect(() => setSelectedIndex(0), [items]) + + useImperativeHandle(autocompleteRef, () => ({ + maybeClose: () => { + hide() + return true + }, + })) + + useImperativeHandle(ref, () => ({ + onKeyDown: ({event}) => { + if (event.key === 'ArrowUp') { + upHandler() + return true } - } - const upHandler = () => { - setSelectedIndex( - (selectedIndex + props.items.length - 1) % props.items.length, - ) - } + if (event.key === 'ArrowDown') { + downHandler() + return true + } - const downHandler = () => { - setSelectedIndex((selectedIndex + 1) % props.items.length) - } + if (event.key === 'Enter' || event.key === 'Tab') { + enterHandler() + return true + } - const enterHandler = () => { - selectItem(selectedIndex) - } + return false + }, + })) - useEffect(() => setSelectedIndex(0), [props.items]) + if (!moderationOpts) return null - useImperativeHandle(ref, () => ({ - onKeyDown: ({event}) => { - if (event.key === 'ArrowUp') { - upHandler() - return true - } + return ( +
+ + {items.length > 0 ? ( + items.map((item, index) => { + const isSelected = selectedIndex === index - if (event.key === 'ArrowDown') { - downHandler() - return true - } - - if (event.key === 'Enter' || event.key === 'Tab') { - enterHandler() - return true - } - - return false - }, - })) - - const {items} = props - - return ( -
- - {items.length > 0 ? ( - items.map((item, index) => { - const isSelected = selectedIndex === index - - return ( - { - selectItem(index) - }} - /> - ) - }) - ) : ( - - No result - - )} - -
- ) - }, -) + return ( + selectItem(index)} + onHover={() => setSelectedIndex(index)} + moderationOpts={moderationOpts} + /> + ) + }) + ) : ( + + No result + + )} +
+
+ ) +}) function AutocompleteProfileCard({ profile, isSelected, - itemIndex, - totalItems, onPress, + onHover, + moderationOpts, }: { profile: AppBskyActorDefs.ProfileViewBasic isSelected: boolean - itemIndex: number - totalItems: number onPress: () => void + onHover: () => void + moderationOpts: ModerationOpts }) { - const pal = usePalette('default') - const {getGraphemeString} = useGrapheme() - const {name: displayName} = getGraphemeString( - sanitizeDisplayName(profile.displayName || sanitizeHandle(profile.handle)), - 30, // Heuristic value; can be modified - ) - const state = useSimpleVerificationState({ - profile, - }) + const t = useTheme() + return ( - - - - - {displayName} - - {state.isVerified && ( - - - - )} - - - - - {sanitizeHandle(profile.handle, '@')} - + + + + + ) } - -const styles = StyleSheet.create({ - container: { - width: 500, - borderRadius: 6, - borderWidth: 1, - borderStyle: 'solid', - padding: 4, - }, - mentionContainer: { - display: 'flex', - alignItems: 'center', - justifyContent: 'space-between', - flexDirection: 'row', - paddingHorizontal: 12, - paddingVertical: 8, - gap: 16, - }, - firstMention: { - borderTopLeftRadius: 2, - borderTopRightRadius: 2, - }, - lastMention: { - borderBottomLeftRadius: 2, - borderBottomRightRadius: 2, - }, - avatarAndDisplayName: { - display: 'flex', - flexDirection: 'row', - alignItems: 'center', - gap: 6, - }, - noResult: { - paddingHorizontal: 12, - paddingVertical: 8, - }, -}) diff --git a/src/view/com/feeds/FeedPage.tsx b/src/view/com/feeds/FeedPage.tsx index e8a177a8d8..0f93e66e37 100644 --- a/src/view/com/feeds/FeedPage.tsx +++ b/src/view/com/feeds/FeedPage.tsx @@ -6,7 +6,7 @@ import {useLingui} from '@lingui/react' import {type NavigationProp, useNavigation} from '@react-navigation/native' import {useQueryClient} from '@tanstack/react-query' -import {VIDEO_FEED_URIS} from '#/lib/constants' +import {DISCOVER_FEED_URI, VIDEO_FEED_URIS} from '#/lib/constants' import {useOpenComposer} from '#/lib/hooks/useOpenComposer' import {ComposeIcon2} from '#/lib/icons' import {getRootNavigation, getTabState, TabState} from '#/lib/routes/helpers' @@ -17,9 +17,12 @@ import {isNative} from '#/platform/detection' import {listenSoftReset} from '#/state/events' import {FeedFeedbackProvider, useFeedFeedback} from '#/state/feed-feedback' import {useSetHomeBadge} from '#/state/home-badge' -import {type SavedFeedSourceInfo} from '#/state/queries/feed' -import {RQKEY as FEED_RQKEY} from '#/state/queries/post-feed' -import {type FeedDescriptor, type FeedParams} from '#/state/queries/post-feed' +import {type FeedSourceInfo} from '#/state/queries/feed' +import { + type FeedDescriptor, + type FeedParams, + RQKEY as FEED_RQKEY, +} from '#/state/queries/post-feed' import {truncateAndInvalidate} from '#/state/queries/util' import {useSession} from '#/state/session' import {useSetMinimalShellMode} from '#/state/shell' @@ -51,7 +54,7 @@ export function FeedPage({ renderEmptyState: () => JSX.Element renderEndOfFeed?: () => JSX.Element savedFeedConfig?: AppBskyActorDefs.SavedFeed - feedInfo: SavedFeedSourceInfo + feedInfo: FeedSourceInfo }) { const {hasSession} = useSession() const {_} = useLingui() @@ -61,7 +64,7 @@ export function FeedPage({ const [isScrolledDown, setIsScrolledDown] = useState(false) const setMinimalShellMode = useSetMinimalShellMode() const headerOffset = useHeaderOffset() - const feedFeedback = useFeedFeedback(feed, hasSession) + const feedFeedback = useFeedFeedback(feedInfo, hasSession) const scrollElRef = useRef(null) const [hasNew, setHasNew] = useState(false) const setHomeBadge = useSetHomeBadge() @@ -127,8 +130,12 @@ export function FeedPage({ }, [scrollToTop, feed, queryClient]) const shouldPrefetch = isNative && isPageAdjacent + const isDiscoverFeed = feedInfo.uri === DISCOVER_FEED_URI return ( - + (Stages.RequestCode) - const [isProcessing, setIsProcessing] = useState(false) - const [resetCode, setResetCode] = useState('') - const [newPassword, setNewPassword] = useState('') - const [error, setError] = useState('') - const {isMobile} = useWebMediaQueries() - const {closeModal} = useModalControls() - - const onRequestCode = async () => { - if ( - !currentAccount?.email || - !EmailValidator.validate(currentAccount.email) - ) { - return setError(_(msg`Your email appears to be invalid.`)) - } - - setError('') - setIsProcessing(true) - try { - await agent.com.atproto.server.requestPasswordReset({ - email: currentAccount.email, - }) - setStage(Stages.ChangePassword) - } catch (e: any) { - const errMsg = e.toString() - logger.warn('Failed to request password reset', {error: e}) - if (isNetworkError(e)) { - setError( - _( - msg`Unable to contact your service. Please check your Internet connection.`, - ), - ) - } else { - setError(cleanError(errMsg)) - } - } finally { - setIsProcessing(false) - } - } - - const onChangePassword = async () => { - const formattedCode = checkAndFormatResetCode(resetCode) - if (!formattedCode) { - setError( - _( - msg`You have entered an invalid code. It should look like XXXXX-XXXXX.`, - ), - ) - return - } - if (!newPassword) { - setError( - _(msg`Please enter a password. It must be at least 8 characters long.`), - ) - return - } - if (newPassword.length < 8) { - setError(_(msg`Password must be at least 8 characters long.`)) - return - } - - setError('') - setIsProcessing(true) - try { - await agent.com.atproto.server.resetPassword({ - token: formattedCode, - password: newPassword, - }) - setStage(Stages.Done) - } catch (e: any) { - const errMsg = e.toString() - logger.warn('Failed to set new password', {error: e}) - if (isNetworkError(e)) { - setError( - _( - msg`Unable to contact your service. Please check your Internet connection.`, - ), - ) - } else { - setError(cleanError(errMsg)) - } - } finally { - setIsProcessing(false) - } - } - - const onBlur = () => { - const formattedCode = checkAndFormatResetCode(resetCode) - if (!formattedCode) { - setError( - _( - msg`You have entered an invalid code. It should look like XXXXX-XXXXX.`, - ), - ) - return - } - setResetCode(formattedCode) - } - - return ( - - - - - - {stage !== Stages.Done - ? _(msg`Change Password`) - : _(msg`Password Changed`)} - - - - - {stage === Stages.RequestCode ? ( - - If you want to change your password, we will send you a code to - verify that this is your account. - - ) : stage === Stages.ChangePassword ? ( - - Enter the code you received to change your password. - - ) : ( - Your password has been changed successfully! - )} - - - {stage === Stages.RequestCode && ( - - setStage(Stages.ChangePassword)} - accessibilityRole="button" - accessibilityLabel={_(msg`Go to next`)} - accessibilityHint={_(msg`Navigates to the next screen`)}> - - Already have a code? - - - - )} - {stage === Stages.ChangePassword && ( - - - - setError('')} - onBlur={onBlur} - accessible={true} - accessibilityLabel={_(msg`Reset Code`)} - accessibilityHint="" - autoCapitalize="none" - autoCorrect={false} - autoComplete="off" - /> - - - - - - - )} - {error ? ( - - ) : undefined} - - - {isProcessing ? ( - - - - ) : ( - - {stage === Stages.RequestCode && ( - - )} - - - - Show replies as - - - { - setTreeViewEnabled(false) - }}> - - Linear - - - - { - setTreeViewEnabled(true) - }}> - - Threaded - - - - - - - Reply sorting - - - { - setSortReplies('hotness') - }}> - - Hot replies first - - - - { - setSortReplies('oldest') - }}> - - Oldest replies first - - - - { - setSortReplies('newest') - }}> - - Newest replies first - - - - { - setSortReplies('most-likes') - }}> - - Most-liked replies first - - - - { - setSortReplies('random') - }}> - - Random (aka "Poster's Roulette") - - - - - - - ) -} -ThreadMenu = memo(ThreadMenu) - -function MobileComposePrompt({onPressReply}: {onPressReply: () => unknown}) { - const {footerHeight} = useShellLayout() - - const animatedStyle = useAnimatedStyle(() => { - return { - bottom: footerHeight.get(), - } - }) - - return ( - - - - ) -} - -function isThreadPost(v: unknown): v is ThreadPost { - return !!v && typeof v === 'object' && 'type' in v && v.type === 'post' -} - -function isThreadNotFound(v: unknown): v is ThreadNotFound { - return !!v && typeof v === 'object' && 'type' in v && v.type === 'not-found' -} - -function isThreadBlocked(v: unknown): v is ThreadBlocked { - return !!v && typeof v === 'object' && 'type' in v && v.type === 'blocked' -} - -function createThreadSkeleton( - node: ThreadNode, - currentDid: string | undefined, - treeView: boolean, - modCache: ThreadModerationCache, - showHiddenReplies: boolean, - threadgateRecordHiddenReplies: Set, -): ThreadSkeletonParts | null { - if (!node) return null - - return { - parents: Array.from(flattenThreadParents(node, !!currentDid)), - highlightedPost: node, - replies: Array.from( - flattenThreadReplies( - node, - currentDid, - treeView, - modCache, - showHiddenReplies, - threadgateRecordHiddenReplies, - ), - ), - } -} - -function* flattenThreadParents( - node: ThreadNode, - hasSession: boolean, -): Generator { - if (node.type === 'post') { - if (node.parent) { - yield* flattenThreadParents(node.parent, hasSession) - } - if (!node.ctx.isHighlightedPost) { - yield node - } - } else if (node.type === 'not-found') { - yield node - } else if (node.type === 'blocked') { - yield node - } -} - -// The enum is ordered to make them easy to merge -enum HiddenReplyType { - None = 0, - Muted = 1, - Hidden = 2, -} - -function* flattenThreadReplies( - node: ThreadNode, - currentDid: string | undefined, - treeView: boolean, - modCache: ThreadModerationCache, - showHiddenReplies: boolean, - threadgateRecordHiddenReplies: Set, -): Generator { - if (node.type === 'post') { - // dont show pwi-opted-out posts to logged out users - if (!currentDid && hasPwiOptOut(node)) { - return HiddenReplyType.None - } - - // handle blurred items - if (node.ctx.depth > 0) { - const modui = modCache.get(node)?.ui('contentList') - if (modui?.blur || modui?.filter) { - if (!showHiddenReplies || node.ctx.depth > 1) { - if ((modui.blurs[0] || modui.filters[0]).type === 'muted') { - return HiddenReplyType.Muted - } - return HiddenReplyType.Hidden - } - } - - if (!showHiddenReplies) { - const hiddenByThreadgate = threadgateRecordHiddenReplies.has( - node.post.uri, - ) - const authorIsViewer = node.post.author.did === currentDid - if (hiddenByThreadgate && !authorIsViewer) { - return HiddenReplyType.Hidden - } - } - } - - if (!node.ctx.isHighlightedPost) { - yield node - } - - if (node.replies?.length) { - let hiddenReplies = HiddenReplyType.None - for (const reply of node.replies) { - let hiddenReply = yield* flattenThreadReplies( - reply, - currentDid, - treeView, - modCache, - showHiddenReplies, - threadgateRecordHiddenReplies, - ) - if (hiddenReply > hiddenReplies) { - hiddenReplies = hiddenReply - } - if (!treeView && !node.ctx.isHighlightedPost) { - break - } - } - - // show control to enable hidden replies - if (node.ctx.depth === 0) { - if (hiddenReplies === HiddenReplyType.Muted) { - yield SHOW_MUTED_REPLIES - } else if (hiddenReplies === HiddenReplyType.Hidden) { - yield SHOW_HIDDEN_REPLIES - } - } - } - } else if (node.type === 'not-found') { - yield node - } else if (node.type === 'blocked') { - yield node - } - return HiddenReplyType.None -} - -function hasPwiOptOut(node: ThreadPost) { - return !!node.post.author.labels?.find(l => l.val === '!no-unauthenticated') -} - -function hasBranchingReplies(node?: ThreadNode) { - if (!node) { - return false - } - if (node.type !== 'post') { - return false - } - if (!node.replies) { - return false - } - if (node.replies.length === 1) { - return hasBranchingReplies(node.replies[0]) - } - return true -} diff --git a/src/view/com/post-thread/PostThreadItem.tsx b/src/view/com/post-thread/PostThreadItem.tsx deleted file mode 100644 index 679a506b90..0000000000 --- a/src/view/com/post-thread/PostThreadItem.tsx +++ /dev/null @@ -1,1036 +0,0 @@ -import {memo, useCallback, useMemo, useState} from 'react' -import { - type GestureResponderEvent, - StyleSheet, - Text as RNText, - View, -} from 'react-native' -import { - AppBskyFeedDefs, - AppBskyFeedPost, - type AppBskyFeedThreadgate, - AtUri, - type ModerationDecision, - RichText as RichTextAPI, -} from '@atproto/api' -import {msg, Plural, Trans} from '@lingui/macro' -import {useLingui} from '@lingui/react' - -import {useActorStatus} from '#/lib/actor-status' -import {MAX_POST_LINES} from '#/lib/constants' -import {useOpenComposer} from '#/lib/hooks/useOpenComposer' -import {usePalette} from '#/lib/hooks/usePalette' -import {useTranslate} from '#/lib/hooks/useTranslate' -import {makeProfileLink} from '#/lib/routes/links' -import {sanitizeDisplayName} from '#/lib/strings/display-names' -import {sanitizeHandle} from '#/lib/strings/handles' -import {countLines} from '#/lib/strings/helpers' -import {niceDate} from '#/lib/strings/time' -import {s} from '#/lib/styles' -import {getTranslatorLink, isPostInLanguage} from '#/locale/helpers' -import {logger} from '#/logger' -import { - POST_TOMBSTONE, - type Shadow, - usePostShadow, -} from '#/state/cache/post-shadow' -import {useProfileShadow} from '#/state/cache/profile-shadow' -import {FeedFeedbackProvider, useFeedFeedback} from '#/state/feed-feedback' -import {useLanguagePrefs} from '#/state/preferences' -import {type ThreadPost} from '#/state/queries/post-thread' -import {useSession} from '#/state/session' -import {type OnPostSuccessData} from '#/state/shell/composer' -import {useMergedThreadgateHiddenReplies} from '#/state/threadgate-hidden-replies' -import {type PostSource} from '#/state/unstable-post-source' -import {PostThreadFollowBtn} from '#/view/com/post-thread/PostThreadFollowBtn' -import {ErrorMessage} from '#/view/com/util/error/ErrorMessage' -import {Link} from '#/view/com/util/Link' -import {formatCount} from '#/view/com/util/numeric/format' -import {PostMeta} from '#/view/com/util/PostMeta' -import {PreviewableUserAvatar} from '#/view/com/util/UserAvatar' -import {atoms as a, useTheme} from '#/alf' -import {colors} from '#/components/Admonition' -import {Button} from '#/components/Button' -import {useInteractionState} from '#/components/hooks/useInteractionState' -import {CalendarClock_Stroke2_Corner0_Rounded as CalendarClockIcon} from '#/components/icons/CalendarClock' -import {ChevronRight_Stroke2_Corner0_Rounded as ChevronRightIcon} from '#/components/icons/Chevron' -import {Trash_Stroke2_Corner0_Rounded as TrashIcon} from '#/components/icons/Trash' -import {InlineLinkText} from '#/components/Link' -import {ContentHider} from '#/components/moderation/ContentHider' -import {LabelsOnMyPost} from '#/components/moderation/LabelsOnMe' -import {PostAlerts} from '#/components/moderation/PostAlerts' -import {PostHider} from '#/components/moderation/PostHider' -import {type AppModerationCause} from '#/components/Pills' -import {Embed, PostEmbedViewContext} from '#/components/Post/Embed' -import {ShowMoreTextButton} from '#/components/Post/ShowMoreTextButton' -import {PostControls} from '#/components/PostControls' -import * as Prompt from '#/components/Prompt' -import {RichText} from '#/components/RichText' -import {SubtleWebHover} from '#/components/SubtleWebHover' -import {Text} from '#/components/Typography' -import {VerificationCheckButton} from '#/components/verification/VerificationCheckButton' -import {WhoCanReply} from '#/components/WhoCanReply' -import * as bsky from '#/types/bsky' - -export function PostThreadItem({ - post, - record, - moderation, - treeView, - depth, - prevPost, - nextPost, - isHighlightedPost, - hasMore, - showChildReplyLine, - showParentReplyLine, - hasPrecedingItem, - overrideBlur, - onPostReply, - onPostSuccess, - hideTopBorder, - threadgateRecord, - anchorPostSource, -}: { - post: AppBskyFeedDefs.PostView - record: AppBskyFeedPost.Record - moderation: ModerationDecision | undefined - treeView: boolean - depth: number - prevPost: ThreadPost | undefined - nextPost: ThreadPost | undefined - isHighlightedPost?: boolean - hasMore?: boolean - showChildReplyLine?: boolean - showParentReplyLine?: boolean - hasPrecedingItem: boolean - overrideBlur: boolean - onPostReply: (postUri: string | undefined) => void - onPostSuccess?: (data: OnPostSuccessData) => void - hideTopBorder?: boolean - threadgateRecord?: AppBskyFeedThreadgate.Record - anchorPostSource?: PostSource -}) { - const postShadowed = usePostShadow(post) - const richText = useMemo( - () => - new RichTextAPI({ - text: record.text, - facets: record.facets, - }), - [record], - ) - if (postShadowed === POST_TOMBSTONE) { - return - } - if (richText && moderation) { - return ( - - ) - } - return null -} - -function PostThreadItemDeleted({hideTopBorder}: {hideTopBorder?: boolean}) { - const t = useTheme() - return ( - - - - This post has been deleted. - - - ) -} - -let PostThreadItemLoaded = ({ - post, - record, - richText, - moderation, - treeView, - depth, - prevPost, - nextPost, - isHighlightedPost, - hasMore, - showChildReplyLine, - showParentReplyLine, - hasPrecedingItem, - overrideBlur, - onPostReply, - onPostSuccess, - hideTopBorder, - threadgateRecord, - anchorPostSource, -}: { - post: Shadow - record: AppBskyFeedPost.Record - richText: RichTextAPI - moderation: ModerationDecision - treeView: boolean - depth: number - prevPost: ThreadPost | undefined - nextPost: ThreadPost | undefined - isHighlightedPost?: boolean - hasMore?: boolean - showChildReplyLine?: boolean - showParentReplyLine?: boolean - hasPrecedingItem: boolean - overrideBlur: boolean - onPostReply: (postUri: string | undefined) => void - onPostSuccess?: (data: OnPostSuccessData) => void - hideTopBorder?: boolean - threadgateRecord?: AppBskyFeedThreadgate.Record - anchorPostSource?: PostSource -}): React.ReactNode => { - const {currentAccount, hasSession} = useSession() - const feedFeedback = useFeedFeedback(anchorPostSource?.feed, hasSession) - - const t = useTheme() - const pal = usePalette('default') - const {_, i18n} = useLingui() - const langPrefs = useLanguagePrefs() - const {openComposer} = useOpenComposer() - const [limitLines, setLimitLines] = useState( - () => countLines(richText?.text) >= MAX_POST_LINES, - ) - const shadowedPostAuthor = useProfileShadow(post.author) - const rootUri = record.reply?.root?.uri || post.uri - const postHref = useMemo(() => { - const urip = new AtUri(post.uri) - return makeProfileLink(post.author, 'post', urip.rkey) - }, [post.uri, post.author]) - const itemTitle = _(msg`Post by ${post.author.handle}`) - const authorHref = makeProfileLink(post.author) - const authorTitle = post.author.handle - const isThreadAuthor = getThreadAuthor(post, record) === currentAccount?.did - const likesHref = useMemo(() => { - const urip = new AtUri(post.uri) - return makeProfileLink(post.author, 'post', urip.rkey, 'liked-by') - }, [post.uri, post.author]) - const likesTitle = _(msg`Likes on this post`) - const repostsHref = useMemo(() => { - const urip = new AtUri(post.uri) - return makeProfileLink(post.author, 'post', urip.rkey, 'reposted-by') - }, [post.uri, post.author]) - const repostsTitle = _(msg`Reposts of this post`) - const threadgateHiddenReplies = useMergedThreadgateHiddenReplies({ - threadgateRecord, - }) - const additionalPostAlerts: AppModerationCause[] = useMemo(() => { - const isPostHiddenByThreadgate = threadgateHiddenReplies.has(post.uri) - const isControlledByViewer = new AtUri(rootUri).host === currentAccount?.did - return isControlledByViewer && isPostHiddenByThreadgate - ? [ - { - type: 'reply-hidden', - source: {type: 'user', did: currentAccount?.did}, - priority: 6, - }, - ] - : [] - }, [post, currentAccount?.did, threadgateHiddenReplies, rootUri]) - const quotesHref = useMemo(() => { - const urip = new AtUri(post.uri) - return makeProfileLink(post.author, 'post', urip.rkey, 'quotes') - }, [post.uri, post.author]) - const quotesTitle = _(msg`Quotes of this post`) - const onlyFollowersCanReply = !!threadgateRecord?.allow?.find( - rule => rule.$type === 'app.bsky.feed.threadgate#followerRule', - ) - const showFollowButton = - currentAccount?.did !== post.author.did && !onlyFollowersCanReply - - const needsTranslation = useMemo( - () => - Boolean( - langPrefs.primaryLanguage && - !isPostInLanguage(post, [langPrefs.primaryLanguage]), - ), - [post, langPrefs.primaryLanguage], - ) - - const onPressReply = () => { - if (anchorPostSource && isHighlightedPost) { - feedFeedback.sendInteraction({ - item: post.uri, - event: 'app.bsky.feed.defs#interactionReply', - feedContext: anchorPostSource.post.feedContext, - reqId: anchorPostSource.post.reqId, - }) - } - openComposer({ - replyTo: { - uri: post.uri, - cid: post.cid, - text: record.text, - author: post.author, - embed: post.embed, - moderation, - langs: record.langs, - }, - onPost: onPostReply, - onPostSuccess: onPostSuccess, - }) - } - - const onOpenAuthor = () => { - if (anchorPostSource) { - feedFeedback.sendInteraction({ - item: post.uri, - event: 'app.bsky.feed.defs#clickthroughAuthor', - feedContext: anchorPostSource.post.feedContext, - reqId: anchorPostSource.post.reqId, - }) - } - } - - const onOpenEmbed = () => { - if (anchorPostSource) { - feedFeedback.sendInteraction({ - item: post.uri, - event: 'app.bsky.feed.defs#clickthroughEmbed', - feedContext: anchorPostSource.post.feedContext, - reqId: anchorPostSource.post.reqId, - }) - } - } - - const onPressShowMore = useCallback(() => { - setLimitLines(false) - }, [setLimitLines]) - - const {isActive: live} = useActorStatus(post.author) - - const reason = anchorPostSource?.post.reason - const viaRepost = useMemo(() => { - if (AppBskyFeedDefs.isReasonRepost(reason) && reason.uri && reason.cid) { - return { - uri: reason.uri, - cid: reason.cid, - } - } - }, [reason]) - - if (!record) { - return - } - - if (isHighlightedPost) { - return ( - <> - {rootUri !== post.uri && ( - - - - - - )} - - - - - - - - - {sanitizeDisplayName( - post.author.displayName || - sanitizeHandle(post.author.handle), - moderation.ui('displayName'), - )} - - - - - - - - - - {sanitizeHandle(post.author.handle, '@')} - - - - {showFollowButton && ( - - - - )} - - - - - - {richText?.text ? ( - - ) : undefined} - {post.embed && ( - - - - )} - - - {post.repostCount !== 0 || - post.likeCount !== 0 || - post.quoteCount !== 0 ? ( - // Show this section unless we're *sure* it has no engagement. - - {post.repostCount != null && post.repostCount !== 0 ? ( - - - - {formatCount(i18n, post.repostCount)} - {' '} - - - - ) : null} - {post.quoteCount != null && - post.quoteCount !== 0 && - !post.viewer?.embeddingDisabled ? ( - - - - {formatCount(i18n, post.quoteCount)} - {' '} - - - - ) : null} - {post.likeCount != null && post.likeCount !== 0 ? ( - - - - {formatCount(i18n, post.likeCount)} - {' '} - - - - ) : null} - - ) : null} - - - - - - - - - ) - } else { - const isThreadedChild = treeView && depth > 0 - const isThreadedChildAdjacentTop = - isThreadedChild && prevPost?.ctx.depth === depth && depth !== 1 - const isThreadedChildAdjacentBot = - isThreadedChild && nextPost?.ctx.depth === depth - return ( - - - - - {!isThreadedChild && showParentReplyLine && ( - - )} - - - - - {/* If we are in threaded mode, the avatar is rendered in PostMeta */} - {!isThreadedChild && ( - - - - {showChildReplyLine && ( - - )} - - )} - - - - - - {richText?.text ? ( - - - {limitLines && ( - - )} - - ) : undefined} - {post.embed && ( - - - - )} - - - - {hasMore ? ( - - - More - - - - ) : undefined} - - - ) - } -} -PostThreadItemLoaded = memo(PostThreadItemLoaded) - -function PostOuterWrapper({ - post, - treeView, - depth, - showParentReplyLine, - hasPrecedingItem, - hideTopBorder, - children, -}: React.PropsWithChildren<{ - post: AppBskyFeedDefs.PostView - treeView: boolean - depth: number - showParentReplyLine: boolean - hasPrecedingItem: boolean - hideTopBorder?: boolean -}>) { - const t = useTheme() - const { - state: hover, - onIn: onHoverIn, - onOut: onHoverOut, - } = useInteractionState() - if (treeView && depth > 0) { - return ( - - {Array.from(Array(depth - 1)).map((_, n: number) => ( - - ))} - - - {children} - - - ) - } - return ( - - - {children} - - ) -} - -function ExpandedPostDetails({ - post, - record, - isThreadAuthor, - needsTranslation, -}: { - post: AppBskyFeedDefs.PostView - record: AppBskyFeedPost.Record - isThreadAuthor: boolean - needsTranslation: boolean -}) { - const t = useTheme() - const pal = usePalette('default') - const {_, i18n} = useLingui() - const translate = useTranslate() - const isRootPost = !('reply' in post.record) - const langPrefs = useLanguagePrefs() - - const onTranslatePress = useCallback( - (e: GestureResponderEvent) => { - e.preventDefault() - translate(record.text || '', langPrefs.primaryLanguage) - - if ( - bsky.dangerousIsType( - post.record, - AppBskyFeedPost.isRecord, - ) - ) { - logger.metric( - 'translate', - { - sourceLanguages: post.record.langs ?? [], - targetLanguage: langPrefs.primaryLanguage, - textLength: post.record.text.length, - }, - {statsig: false}, - ) - } - - return false - }, - [translate, record.text, langPrefs, post], - ) - - return ( - - - - - {niceDate(i18n, post.indexedAt)} - - {isRootPost && ( - - )} - {needsTranslation && ( - <> - - · - - - - Translate - - - )} - - - ) -} - -function BackdatedPostIndicator({post}: {post: AppBskyFeedDefs.PostView}) { - const t = useTheme() - const {_, i18n} = useLingui() - const control = Prompt.usePromptControl() - - const indexedAt = new Date(post.indexedAt) - const createdAt = bsky.dangerousIsType( - post.record, - AppBskyFeedPost.isRecord, - ) - ? new Date(post.record.createdAt) - : new Date(post.indexedAt) - - // backdated if createdAt is 24 hours or more before indexedAt - const isBackdated = - indexedAt.getTime() - createdAt.getTime() > 24 * 60 * 60 * 1000 - - if (!isBackdated) return null - - const orange = t.name === 'light' ? colors.warning.dark : colors.warning.light - - return ( - <> - - - - - Archived post - - - - This post claims to have been created on{' '} - {niceDate(i18n, createdAt)}, - but was first seen by Bluesky on{' '} - {niceDate(i18n, indexedAt)}. - - - - - Bluesky cannot confirm the authenticity of the claimed date. - - - - {}} /> - - - - ) -} - -function getThreadAuthor( - post: AppBskyFeedDefs.PostView, - record: AppBskyFeedPost.Record, -): string { - if (!record.reply) { - return post.author.did - } - try { - return new AtUri(record.reply.root.uri).host - } catch { - return '' - } -} - -const styles = StyleSheet.create({ - outer: { - borderTopWidth: StyleSheet.hairlineWidth, - paddingLeft: 8, - }, - noTopBorder: { - borderTopWidth: 0, - }, - meta: { - flexDirection: 'row', - paddingVertical: 2, - }, - metaExpandedLine1: { - paddingVertical: 0, - }, - loadMore: { - flexDirection: 'row', - alignItems: 'center', - justifyContent: 'flex-start', - gap: 4, - paddingHorizontal: 20, - }, - replyLine: { - width: 2, - marginLeft: 'auto', - marginRight: 'auto', - }, - cursor: { - // @ts-ignore web only - cursor: 'pointer', - }, -}) diff --git a/src/view/com/post-thread/PostThreadLoadMore.tsx b/src/view/com/post-thread/PostThreadLoadMore.tsx deleted file mode 100644 index 27e2ea724d..0000000000 --- a/src/view/com/post-thread/PostThreadLoadMore.tsx +++ /dev/null @@ -1,65 +0,0 @@ -import * as React from 'react' -import {View} from 'react-native' -import {AppBskyFeedDefs, AtUri} from '@atproto/api' -import {Trans} from '@lingui/macro' - -import {makeProfileLink} from '#/lib/routes/links' -import {atoms as a, useTheme} from '#/alf' -import {Text} from '#/components/Typography' -import {Link} from '../util/Link' -import {UserAvatar} from '../util/UserAvatar' - -export function PostThreadLoadMore({post}: {post: AppBskyFeedDefs.PostView}) { - const t = useTheme() - - const postHref = React.useMemo(() => { - const urip = new AtUri(post.uri) - return makeProfileLink(post.author, 'post', urip.rkey) - }, [post.uri, post.author]) - - return ( - - - - - - - - - - - - Continue thread... - - - - ) -} diff --git a/src/view/com/post-thread/PostThreadShowHiddenReplies.tsx b/src/view/com/post-thread/PostThreadShowHiddenReplies.tsx deleted file mode 100644 index 7dc75520b5..0000000000 --- a/src/view/com/post-thread/PostThreadShowHiddenReplies.tsx +++ /dev/null @@ -1,62 +0,0 @@ -import {View} from 'react-native' -import {msg} from '@lingui/macro' -import {useLingui} from '@lingui/react' - -import {atoms as a, useTheme} from '#/alf' -import {Button} from '#/components/Button' -import {EyeSlash_Stroke2_Corner0_Rounded as EyeSlash} from '#/components/icons/EyeSlash' -import {Text} from '#/components/Typography' - -export function PostThreadShowHiddenReplies({ - type, - onPress, - hideTopBorder, -}: { - type: 'hidden' | 'muted' - onPress: () => void - hideTopBorder?: boolean -}) { - const {_} = useLingui() - const t = useTheme() - const label = - type === 'muted' ? _(msg`Show muted replies`) : _(msg`Show hidden replies`) - - return ( - - ) -} diff --git a/src/view/com/posts/PostFeedItem.tsx b/src/view/com/posts/PostFeedItem.tsx index c2780a2a5b..2f03a168b5 100644 --- a/src/view/com/posts/PostFeedItem.tsx +++ b/src/view/com/posts/PostFeedItem.tsx @@ -176,7 +176,7 @@ let FeedItemInner = ({ const urip = new AtUri(post.uri) return makeProfileLink(post.author, 'post', urip.rkey) }, [post.uri, post.author]) - const {sendInteraction, feedDescriptor} = useFeedFeedbackContext() + const {sendInteraction, feedSourceInfo} = useFeedFeedbackContext() const onPressReply = () => { sendInteraction({ @@ -234,7 +234,7 @@ let FeedItemInner = ({ }) unstableCacheProfileView(queryClient, post.author) setUnstablePostSource(buildPostSourceKey(post.uri, post.author.handle), { - feed: feedDescriptor, + feedSourceInfo, post: { post, reason: AppBskyFeedDefs.isReasonRepost(reason) ? reason : undefined, diff --git a/src/view/com/profile/FollowButton.tsx b/src/view/com/profile/FollowButton.tsx index 656ed914af..ff9c1cd7b4 100644 --- a/src/view/com/profile/FollowButton.tsx +++ b/src/view/com/profile/FollowButton.tsx @@ -1,11 +1,11 @@ -import {StyleProp, TextStyle, View} from 'react-native' +import {type StyleProp, type TextStyle, View} from 'react-native' import {msg} from '@lingui/macro' import {useLingui} from '@lingui/react' -import {Shadow} from '#/state/cache/types' +import {type Shadow} from '#/state/cache/types' import {useProfileFollowMutationQueue} from '#/state/queries/profile' -import * as bsky from '#/types/bsky' -import {Button, ButtonType} from '../util/forms/Button' +import type * as bsky from '#/types/bsky' +import {Button, type ButtonType} from '../util/forms/Button' import * as Toast from '../util/Toast' export function FollowButton({ @@ -78,7 +78,7 @@ export function FollowButton({ type={unfollowedType} labelStyle={labelStyle} onPress={onPressFollow} - label={_(msg({message: 'Follow Back', context: 'action'}))} + label={_(msg({message: 'Follow back', context: 'action'}))} /> ) } diff --git a/src/view/com/profile/ProfileMenu.tsx b/src/view/com/profile/ProfileMenu.tsx index 879bf22f98..df8b2e4817 100644 --- a/src/view/com/profile/ProfileMenu.tsx +++ b/src/view/com/profile/ProfileMenu.tsx @@ -27,6 +27,7 @@ import {EventStopper} from '#/view/com/util/EventStopper' import * as Toast from '#/view/com/util/Toast' import {Button, ButtonIcon} from '#/components/Button' import {useDialogControl} from '#/components/Dialog' +import {StarterPackDialog} from '#/components/dialogs/StarterPackDialog' import {ArrowOutOfBoxModified_Stroke2_Corner2_Rounded as ArrowOutOfBoxIcon} from '#/components/icons/ArrowOutOfBox' import {ChainLink_Stroke2_Corner0_Rounded as ChainLinkIcon} from '#/components/icons/ChainLink' import {CircleCheck_Stroke2_Corner0_Rounded as CircleCheckIcon} from '#/components/icons/CircleCheck' @@ -45,6 +46,7 @@ import { } from '#/components/icons/Person' import {PlusLarge_Stroke2_Corner0_Rounded as Plus} from '#/components/icons/Plus' import {SpeakerVolumeFull_Stroke2_Corner0_Rounded as Unmute} from '#/components/icons/Speaker' +import {StarterPack} from '#/components/icons/StarterPack' import {EditLiveDialog} from '#/components/live/EditLiveDialog' import {GoLiveDialog} from '#/components/live/GoLiveDialog' import * as Menu from '#/components/Menu' @@ -88,6 +90,7 @@ let ProfileMenu = ({ const blockPromptControl = Prompt.usePromptControl() const loggedOutWarningPromptControl = Prompt.usePromptControl() const goLiveDialogControl = useDialogControl() + const addToStarterPacksDialogControl = useDialogControl() const showLoggedOutWarning = React.useMemo(() => { return ( @@ -300,6 +303,15 @@ let ProfileMenu = ({ )} )} + + + Add to starter packs + + + + + + setProxyHeader(val as any)} + onSubmitEditing={() => { + const header = `${proxyHeader}#bsky_appview` + setBlueskyProxyHeader(header as any) + agent.configureProxy(header as any) + }} + style={BTN} + /> void -} -export interface DropdownItemSeparator { - sep: true -} -export interface DropdownItemHeading { - heading: true - label: string -} -export type DropdownItem = - | DropdownItemButton - | DropdownItemSeparator - | DropdownItemHeading -type MaybeDropdownItem = DropdownItem | false | undefined - -export type DropdownButtonType = ButtonType | 'bare' - -interface DropdownButtonProps { - testID?: string - type?: DropdownButtonType - style?: StyleProp - items: MaybeDropdownItem[] - label?: string - menuWidth?: number - children?: React.ReactNode - openToRight?: boolean - openUpwards?: boolean - rightOffset?: number - bottomOffset?: number - hitSlop?: Insets - accessibilityLabel?: string - accessibilityHint?: string -} - -/** - * @deprecated use Menu from `#/components/Menu.tsx` instead - */ -export function DropdownButton({ - testID, - type = 'bare', - style, - items, - label, - menuWidth, - children, - openToRight = false, - openUpwards = false, - rightOffset = 0, - bottomOffset = 0, - hitSlop = HITSLOP_10, - accessibilityLabel, -}: PropsWithChildren) { - const {_} = useLingui() - - const ref1 = useRef(null) - const ref2 = useRef(null) - - const onPress = (e: GestureResponderEvent) => { - const ref = ref1.current || ref2.current - const {height: winHeight} = Dimensions.get('window') - const pressY = e.nativeEvent.pageY - ref?.measure( - ( - _x: number, - _y: number, - width: number, - _height: number, - pageX: number, - pageY: number, - ) => { - if (!menuWidth) { - menuWidth = 200 - } - let estimatedMenuHeight = 0 - for (const item of items) { - if (item && isSep(item)) { - estimatedMenuHeight += ESTIMATED_SEP_HEIGHT - } else if (item && isBtn(item)) { - estimatedMenuHeight += ESTIMATED_BTN_HEIGHT - } else if (item && isHeading(item)) { - estimatedMenuHeight += ESTIMATED_HEADING_HEIGHT - } - } - const newX = openToRight - ? pageX + width + rightOffset - : pageX + width - menuWidth - - // Add a bit of additional room - let newY = pressY + bottomOffset + 20 - if (openUpwards || newY + estimatedMenuHeight > winHeight) { - newY -= estimatedMenuHeight - } - createDropdownMenu( - newX, - newY, - pageY, - menuWidth, - items.filter(v => !!v) as DropdownItem[], - openUpwards, - ) - }, - ) - } - - const numItems = useMemo( - () => - items.filter(item => { - if (item === undefined || item === false) { - return false - } - - return isBtn(item) - }).length, - [items], - ) - - if (type === 'bare') { - return ( - - {children} - - ) - } - return ( - - - - ) -} - -function createDropdownMenu( - x: number, - y: number, - pageY: number, - width: number, - items: DropdownItem[], - opensUpwards = false, -): RootSiblings { - const onPressItem = (index: number) => { - sibling.destroy() - const item = items[index] - if (isBtn(item)) { - item.onPress() - } - } - const onOuterPress = () => sibling.destroy() - const sibling = new RootSiblings( - ( - - ), - ) - return sibling -} - -type DropDownItemProps = { - onOuterPress: () => void - x: number - y: number - pageY: number - width: number - items: DropdownItem[] - onPressItem: (index: number) => void - openUpwards: boolean -} - -const DropdownItems = ({ - onOuterPress, - x, - y, - pageY, - width, - items, - onPressItem, - openUpwards, -}: DropDownItemProps) => { - const pal = usePalette('default') - const theme = useTheme() - const {_} = useLingui() - const {height: screenHeight} = useWindowDimensions() - const dropDownBackgroundColor = - theme.colorScheme === 'dark' ? pal.btn : pal.view - const separatorColor = - theme.colorScheme === 'dark' ? pal.borderDark : pal.border - - const numItems = items.filter(isBtn).length - - // TODO: Refactor dropdown components to: - // - (On web, if not handled by React Native) use semantic