diff --git a/package.json b/package.json index cb577f5f..c02b1ba6 100644 --- a/package.json +++ b/package.json @@ -17,6 +17,7 @@ "@fortawesome/free-solid-svg-icons": "^6.1.1", "@fortawesome/react-fontawesome": "^0.2.0", "@nitrots/nitro-renderer": "^1.3.4", + "@tanstack/react-virtual": "^3.0.0-beta.18", "animate.css": "^4.1.1", "classnames": "^2.3.1", "cross-env": "^7.0.3", @@ -27,7 +28,6 @@ "react-scripts": "4.0.3", "react-slider": "^2.0.0", "react-transition-group": "^4.4.2", - "react-virtualized": "^9.22.3", "react-youtube": "^7.13.1", "sass": "^1.53.0", "typescript": "^4.3.5", @@ -44,7 +44,6 @@ "@types/react-dom": "^18.0.6", "@types/react-slider": "^1.3.1", "@types/react-transition-group": "^4.4.5", - "@types/react-virtualized": "^9.21.21", "@typescript-eslint/eslint-plugin": "^5.30.7", "@typescript-eslint/parser": "^5.30.7", "eslint": "^8.20.0", diff --git a/src/common/InfiniteScroll.tsx b/src/common/InfiniteScroll.tsx new file mode 100644 index 00000000..6c782593 --- /dev/null +++ b/src/common/InfiniteScroll.tsx @@ -0,0 +1,64 @@ +import { useVirtualizer } from '@tanstack/react-virtual'; +import { FC, ReactElement, useEffect, useRef } from 'react'; +import { Base } from './Base'; + +interface InfiniteScrollProps +{ + rows: T[]; + estimateSize: number; + overscan?: number; + rowRender: (row: T) => ReactElement; +} + +export const InfiniteScroll: FC = props => +{ + const { rows = [], estimateSize = 0, overscan = 5, rowRender = null } = props; + const elementRef = useRef(null); + + const rowVirtualizer = useVirtualizer({ + count: rows.length, + getScrollElement: () => elementRef?.current, + estimateSize: () => estimateSize, + overscan: overscan + }); + + useEffect(() => + { + let timeout: ReturnType = null; + + const resizeObserver = new ResizeObserver(() => + { + if(timeout) clearTimeout(timeout); + + if(!elementRef.current) return; + + timeout = setTimeout(() => rowVirtualizer.getVirtualItems().forEach((virtualItem, index) => virtualItem.measureElement(elementRef?.current?.children?.[0]?.children[index])), 10); + }); + + if(elementRef.current) resizeObserver.observe(elementRef.current); + + return () => + { + if(timeout) clearTimeout(); + + timeout = null; + + resizeObserver.disconnect(); + } + }, [ rowVirtualizer ]); + + return ( + + + { rowVirtualizer.getVirtualItems().map(virtualRow => + { + return ( +
+ { rowRender(rows[virtualRow.index]) } +
+ ); + }) } + + + ); +} diff --git a/src/common/index.ts b/src/common/index.ts index cdcb7512..c9bbd4d0 100644 --- a/src/common/index.ts +++ b/src/common/index.ts @@ -12,6 +12,7 @@ export * from './FormGroup'; export * from './Grid'; export * from './GridContext'; export * from './HorizontalRule'; +export * from './InfiniteScroll'; export * from './layout'; export * from './Text'; export * from './transitions'; diff --git a/src/components/chat-history/ChatHistoryView.tsx b/src/components/chat-history/ChatHistoryView.tsx index 5580bdd9..64892aab 100644 --- a/src/components/chat-history/ChatHistoryView.tsx +++ b/src/components/chat-history/ChatHistoryView.tsx @@ -1,8 +1,7 @@ import { ILinkEventTracker } from '@nitrots/nitro-renderer'; -import { FC, useEffect, useMemo, useRef, useState } from 'react'; -import { AutoSizer, CellMeasurer, CellMeasurerCache, List, ListRowProps, ListRowRenderer } from 'react-virtualized'; +import { FC, useEffect, useMemo, useState } from 'react'; import { AddEventLinkTracker, ChatEntryType, LocalizeText, RemoveLinkEventTracker } from '../../api'; -import { Flex, NitroCardContentView, NitroCardHeaderView, NitroCardView, Text } from '../../common'; +import { Flex, InfiniteScroll, NitroCardContentView, NitroCardHeaderView, NitroCardView, Text } from '../../common'; import { useChatHistory } from '../../hooks'; export const ChatHistoryView: FC<{}> = props => @@ -10,9 +9,6 @@ export const ChatHistoryView: FC<{}> = props => const [ isVisible, setIsVisible ] = useState(false); const [ searchText, setSearchText ] = useState(''); const { chatHistory = [] } = useChatHistory(); - const elementRef = useRef(null); - - const cache = useMemo(() => new CellMeasurerCache({ defaultHeight: 35, fixedWidth: true }), []); const filteredChatHistory = useMemo(() => { @@ -23,10 +19,10 @@ export const ChatHistoryView: FC<{}> = props => return chatHistory.filter(entry => ((entry.message && entry.message.toLowerCase().includes(text))) || (entry.name && entry.name.toLowerCase().includes(text))); }, [ chatHistory, searchText ]); - useEffect(() => + /* useEffect(() => { - if(elementRef && elementRef.current && isVisible) elementRef.current.scrollToRow(-1); - }, [ isVisible ]); + if(elementRef && elementRef.current && isVisible) elementRef.current.scrollTop = elementRef.current.scrollHeight; + }, [ isVisible ]); */ useEffect(() => { @@ -60,68 +56,39 @@ export const ChatHistoryView: FC<{}> = props => if(!isVisible) return null; - const RowRenderer: ListRowRenderer = (props: ListRowProps) => - { - const item = filteredChatHistory[props.index]; - - if (!item) return null; - - return ( - - - { item.timestamp } - { (item.type === ChatEntryType.TYPE_CHAT) && -
- { (item.style === 0) && -
} -
-
- { item.imageUrl && (item.imageUrl.length > 0) && -
} -
-
- - -
-
-
} - { (item.type === ChatEntryType.TYPE_ROOM_INFO) && - <> - - { item.name } - } - - - ); - }; - return ( setIsVisible(false) }/> - - - setSearchText(event.target.value) } /> -
- - { ({ height, width }) => - { - cache.clearAll(); - - return ( - - ) - } } - -
-
+ + setSearchText(event.target.value) } /> + + { + return ( + + { row.timestamp } + { (row.type === ChatEntryType.TYPE_CHAT) && +
+ { (row.style === 0) && +
} +
+
+ { row.imageUrl && (row.imageUrl.length > 0) && +
} +
+
+ + +
+
+
} + { (row.type === ChatEntryType.TYPE_ROOM_INFO) && + <> + + { row.name } + } + + ) + } } /> ); diff --git a/src/components/mod-tools/ModToolsView.scss b/src/components/mod-tools/ModToolsView.scss index 7c79e117..111ceb6b 100644 --- a/src/components/mod-tools/ModToolsView.scss +++ b/src/components/mod-tools/ModToolsView.scss @@ -23,12 +23,12 @@ .table { color: $black; - > :not(caption) > * > * { + > :not(caption)>*>* { box-shadow: none; border-bottom: 1px solid rgba(0, 0, 0, .2); } - &.table-striped > tbody > tr:nth-of-type(odd) { + &.table-striped>tbody>tr:nth-of-type(odd) { color: $black; background: rgba(0, 0, 0, .05); } @@ -41,10 +41,12 @@ .nitro-mod-tools-chatlog { width: 400px; + height: 250px; } .nitro-mod-tools-user-visits { width: 250px; + height: 250px; } .nitro-mod-tools-tickets { @@ -59,26 +61,10 @@ .nitro-mod-tools-chatlog, .nitro-mod-tools-user-visits { - .log-container { - min-height: 200px; - height: 100%; + .log-entry { - .log-entry-container { - - .log-entry { - - &.highlighted { - border: 1px solid $red; - } - } - - &.highlighted { - border: 1px solid $red; - } - } - - &:first-child { - padding-top: 0; + &.highlighted { + border: 1px solid $red; } } } diff --git a/src/components/mod-tools/views/chatlog/ChatlogRecord.ts b/src/components/mod-tools/views/chatlog/ChatlogRecord.ts new file mode 100644 index 00000000..089fd567 --- /dev/null +++ b/src/components/mod-tools/views/chatlog/ChatlogRecord.ts @@ -0,0 +1,11 @@ +export interface ChatlogRecord +{ + timestamp?: string; + habboId?: number; + username?: string; + message?: string; + hasHighlighting?: boolean; + isRoomInfo?: boolean; + roomId?: number; + roomName?: string; +} diff --git a/src/components/mod-tools/views/chatlog/ChatlogView.tsx b/src/components/mod-tools/views/chatlog/ChatlogView.tsx index 58a57c6d..616dfb36 100644 --- a/src/components/mod-tools/views/chatlog/ChatlogView.tsx +++ b/src/components/mod-tools/views/chatlog/ChatlogView.tsx @@ -1,9 +1,9 @@ import { ChatRecordData } from '@nitrots/nitro-renderer'; -import { CSSProperties, FC, Key, useCallback } from 'react'; -import { AutoSizer, CellMeasurer, CellMeasurerCache, List, ListRowProps } from 'react-virtualized'; +import { FC, useMemo } from 'react'; import { CreateLinkEvent, TryVisitRoom } from '../../../../api'; -import { Base, Button, Column, Flex, Grid, Text } from '../../../../common'; +import { Base, Button, Column, Flex, Grid, InfiniteScroll, Text } from '../../../../common'; import { useModTools } from '../../../../hooks'; +import { ChatlogRecord } from './ChatlogRecord'; interface ChatlogViewProps { @@ -15,94 +15,38 @@ export const ChatlogView: FC = props => const { records = null } = props; const { openRoomInfo = null } = useModTools(); - const rowRenderer = (props: ListRowProps) => + const allRecords = useMemo(() => { - let chatlogEntry = records[0].chatlog[props.index]; + const results: ChatlogRecord[] = []; - return ( - - - { chatlogEntry.timestamp } - CreateLinkEvent(`mod-tools/open-user-info/${ chatlogEntry.userId }`) }>{ chatlogEntry.userName } - { chatlogEntry.message } - - - ); - }; - - const advancedRowRenderer = (props: ListRowProps) => - { - let chatlogEntry = null; - let currentRecord: ChatRecordData = null; - let isRoomInfo = false; - let totalIndex = 0; - - for(let i = 0; i < records.length; i++) + records.forEach(record => { - currentRecord = records[i]; + results.push({ + isRoomInfo: true, + roomId: record.roomId, + roomName: record.roomName + }); - totalIndex++; // row for room info - totalIndex = (totalIndex + currentRecord.chatlog.length); - - if(props.index > (totalIndex - 1)) continue; - - if((props.index + 1) === (totalIndex - currentRecord.chatlog.length)) + record.chatlog.forEach(chatlog => { - isRoomInfo = true; - - break; - } - - const index = (props.index - (totalIndex - currentRecord.chatlog.length)); - - chatlogEntry = currentRecord.chatlog[index]; - - break; - } - - return ( - - { (isRoomInfo && currentRecord) && - } - { !isRoomInfo && - - { chatlogEntry.timestamp } - CreateLinkEvent(`mod-tools/open-user-info/${ chatlogEntry.userId }`) }>{ chatlogEntry.userName } - { chatlogEntry.message } - } - - ); - } - - const getNumRowsForAdvanced = useCallback(() => - { - let count = 0; - - for(let i = 0; i < records.length; i++) - { - count++; // add room info row - count = count + records[i].chatlog.length; - } - - return count; + results.push({ + timestamp: chatlog.timestamp, + habboId: chatlog.userId, + username: chatlog.userName, + hasHighlighting: chatlog.hasHighlighting, + message: chatlog.message, + isRoomInfo: false + }); + }); + }); + + return results; }, [ records ]); - const RoomInfo = (props: { roomId: number, roomName: string, uniqueKey: Key, style: CSSProperties }) => + const RoomInfo = (props: { roomId: number, roomName: string }) => { return ( - + Room name: { props.roomName } @@ -115,15 +59,8 @@ export const ChatlogView: FC = props => ); } - const cache = new CellMeasurerCache({ - defaultHeight: 25, - fixedWidth: true - }); - return ( <> - { (records && (records.length === 1)) && - } @@ -133,25 +70,21 @@ export const ChatlogView: FC = props => { (records && (records.length > 0)) && - - - { ({ height, width }) => - { - cache.clearAll(); - - return ( - 1) ? getNumRowsForAdvanced() : records[0].chatlog.length } - rowHeight={ cache.rowHeight } - className={ 'log-entry-container' } - rowRenderer={ (records.length > 1) ? advancedRowRenderer : rowRenderer } - deferredMeasurementCache={ cache } /> - ); - } } - - } + + { + return ( + <> + { row.isRoomInfo && + } + { !row.isRoomInfo && + + { row.timestamp } + CreateLinkEvent(`mod-tools/open-user-info/${ row.habboId }`) }>{ row.username } + { row.message } + } + + ); + } } /> } ); diff --git a/src/components/mod-tools/views/room/ModToolsChatlogView.tsx b/src/components/mod-tools/views/room/ModToolsChatlogView.tsx index f9ea05e1..62a80f3a 100644 --- a/src/components/mod-tools/views/room/ModToolsChatlogView.tsx +++ b/src/components/mod-tools/views/room/ModToolsChatlogView.tsx @@ -35,7 +35,7 @@ export const ModToolsChatlogView: FC = props => return ( - + { roomChatlog && } diff --git a/src/components/mod-tools/views/user/ModToolsUserRoomVisitsView.tsx b/src/components/mod-tools/views/user/ModToolsUserRoomVisitsView.tsx index f3d9ac80..efaa7de5 100644 --- a/src/components/mod-tools/views/user/ModToolsUserRoomVisitsView.tsx +++ b/src/components/mod-tools/views/user/ModToolsUserRoomVisitsView.tsx @@ -1,8 +1,7 @@ import { GetRoomVisitsMessageComposer, RoomVisitsData, RoomVisitsEvent } from '@nitrots/nitro-renderer'; import { FC, useEffect, useState } from 'react'; -import { AutoSizer, List, ListRowProps } from 'react-virtualized'; import { SendMessageComposer, TryVisitRoom } from '../../../../api'; -import { Base, Column, DraggableWindowPosition, Grid, NitroCardContentView, NitroCardHeaderView, NitroCardView, Text } from '../../../../common'; +import { Base, Column, DraggableWindowPosition, Grid, InfiniteScroll, NitroCardContentView, NitroCardHeaderView, NitroCardView, Text } from '../../../../common'; import { useMessageEvent } from '../../../../hooks'; interface ModToolsUserRoomVisitsViewProps @@ -32,19 +31,6 @@ export const ModToolsUserRoomVisitsView: FC = p if(!userId) return null; - const RowRenderer = (props: ListRowProps) => - { - const item = roomVisitData.rooms[props.index]; - - return ( - - { item.enterHour.toString().padStart(2, '0') }: { item.enterMinute.toString().padStart(2, '0') } - { item.roomName } - TryVisitRoom(item.roomId) }>Visit Room - - ); - } - return ( @@ -57,24 +43,16 @@ export const ModToolsUserRoomVisitsView: FC = p Visit - - { roomVisitData && - - { ({ height, width }) => - { - return ( - - ); - } } - } - + + { + return ( + + { row.enterHour.toString().padStart(2, '0') }: { row.enterMinute.toString().padStart(2, '0') } + { row.roomName } + TryVisitRoom(row.roomId) }>Visit Room + + ); + } } /> diff --git a/src/components/room/widgets/choosers/ChooserWidgetView.tsx b/src/components/room/widgets/choosers/ChooserWidgetView.tsx index 12c5387f..8667a617 100644 --- a/src/components/room/widgets/choosers/ChooserWidgetView.tsx +++ b/src/components/room/widgets/choosers/ChooserWidgetView.tsx @@ -1,7 +1,7 @@ +import classNames from 'classnames'; import { FC, useEffect, useMemo, useState } from 'react'; -import { AutoSizer, List, ListRowProps, ListRowRenderer } from 'react-virtualized'; import { GetSessionDataManager, LocalizeText, RoomObjectItem } from '../../../../api'; -import { Column, Flex, NitroCardContentView, NitroCardHeaderView, NitroCardView, Text } from '../../../../common'; +import { Flex, InfiniteScroll, NitroCardContentView, NitroCardHeaderView, NitroCardView, Text } from '../../../../common'; interface ChooserWidgetViewProps { @@ -25,17 +25,6 @@ export const ChooserWidgetView: FC = props => return items.filter(item => item.name.toLocaleLowerCase().includes(value)); }, [ items, searchValue ]); - const rowRenderer: ListRowRenderer = (props: ListRowProps) => - { - const item = filteredItems[props.index]; - - return ( - setSelectedItem(item) }> - { item.name } { canSeeId && (' - ' + item.id) } - - ); - } - useEffect(() => { if(!selectedItem) return; @@ -46,21 +35,16 @@ export const ChooserWidgetView: FC = props => return ( - + setSearchValue(event.target.value) } /> - - - { ({ width, height }) => - { - return () - } } - - + + { + return ( + setSelectedItem(row) }> + { row.name } { canSeeId && (' - ' + row.id) } + + ); + } } /> ); diff --git a/yarn.lock b/yarn.lock index 6b568a4f..22a28cc4 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1043,7 +1043,7 @@ core-js-pure "^3.20.2" regenerator-runtime "^0.13.4" -"@babel/runtime@^7.10.2", "@babel/runtime@^7.12.5", "@babel/runtime@^7.16.3", "@babel/runtime@^7.17.2", "@babel/runtime@^7.18.3", "@babel/runtime@^7.18.9", "@babel/runtime@^7.5.5", "@babel/runtime@^7.6.2", "@babel/runtime@^7.6.3", "@babel/runtime@^7.7.2", "@babel/runtime@^7.8.4", "@babel/runtime@^7.8.7": +"@babel/runtime@^7.10.2", "@babel/runtime@^7.12.5", "@babel/runtime@^7.16.3", "@babel/runtime@^7.17.2", "@babel/runtime@^7.18.3", "@babel/runtime@^7.18.9", "@babel/runtime@^7.5.5", "@babel/runtime@^7.6.2", "@babel/runtime@^7.6.3", "@babel/runtime@^7.8.4", "@babel/runtime@^7.8.7": version "7.18.9" resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.18.9.tgz#b4fcfce55db3d2e5e080d2490f608a3b9f407f4a" integrity sha512-lkqXDcvlFT5rvEjiu6+QYO+1GXrEHRo2LOtS7E4GtX5ESIZOgepqsZBVIj6Pv+a6zqsya9VCgiK1KAK4BvJDAw== @@ -1614,9 +1614,9 @@ integrity sha512-4eMqkns+NL2/DmdezjbVG4TW+eII3hvgDM3koDQNoO4yjMgU+55TTptPU9jJL/JJwntRiUECLSIHg8eZxmA5mA== "@pixi/filter-adjustment@^4.1.3": - version "4.1.3" - resolved "https://registry.yarnpkg.com/@pixi/filter-adjustment/-/filter-adjustment-4.1.3.tgz#61e34b4dd9766ccf40463f0538201bf68f78df66" - integrity sha512-W+NhPiZRYKoRToa5+tkU95eOw8gnS5dfIp3ZP+pLv2mdER9RI+4xHxp1uLHMqUYZViTaMdZIIoVOuCgHFPYCbQ== + version "4.2.0" + resolved "https://registry.yarnpkg.com/@pixi/filter-adjustment/-/filter-adjustment-4.2.0.tgz#1648f705f856619835184dae42299138bf964c83" + integrity sha512-3Pvo5WyUb8X5GQ69X3/Tj6rHl0q7gArvcIYKeV2+/PzHaMypVF4Lsr3I3zYSyWWokxOQ0bFCAtNWm1WwDRA41g== "@pixi/filter-alpha@~6.4.2": version "6.4.2" @@ -1932,6 +1932,18 @@ "@svgr/plugin-svgo" "^5.5.0" loader-utils "^2.0.0" +"@tanstack/react-virtual@^3.0.0-beta.18": + version "3.0.0-beta.18" + resolved "https://registry.yarnpkg.com/@tanstack/react-virtual/-/react-virtual-3.0.0-beta.18.tgz#b97b2019f7d6a5770fb88ee1f7591da55b9059b4" + integrity sha512-mnyCZT6htcRNw1jVb+WyfMUMbd1UmXX/JWPuMf6Bmj92DB/V7Ogk5n5rby5Y5aste7c7mlsBeMF8HtpwERRvEQ== + dependencies: + "@tanstack/virtual-core" "3.0.0-beta.18" + +"@tanstack/virtual-core@3.0.0-beta.18": + version "3.0.0-beta.18" + resolved "https://registry.yarnpkg.com/@tanstack/virtual-core/-/virtual-core-3.0.0-beta.18.tgz#d4b0738c1d0aada922063c899675ff4df9f696b2" + integrity sha512-tcXutY05NpN9lp3+AXI9Sn85RxSPV0EJC0XMim9oeQj/E7bjXoL0qZ4Er4wwnvIbv/hZjC91EmbIQGjgdr6nZg== + "@tootallnate/once@1": version "1.1.2" resolved "https://registry.yarnpkg.com/@tootallnate/once/-/once-1.1.2.tgz#ccb91445360179a04e7fe6aff78c00ffc1eeaf82" @@ -2123,15 +2135,7 @@ dependencies: "@types/react" "*" -"@types/react-virtualized@^9.21.21": - version "9.21.21" - resolved "https://registry.yarnpkg.com/@types/react-virtualized/-/react-virtualized-9.21.21.tgz#65c96f25314f0fb3d40536929dc78112753b49e1" - integrity sha512-Exx6I7p4Qn+BBA1SRyj/UwQlZ0I0Pq7g7uhAp0QQ4JWzZunqEqNBGTmCmMmS/3N9wFgAGWuBD16ap7k8Y14VPA== - dependencies: - "@types/prop-types" "*" - "@types/react" "^17" - -"@types/react@*", "@types/react@>=16.9.11", "@types/react@^17", "@types/react@^18.0.15": +"@types/react@*", "@types/react@>=16.9.11", "@types/react@^18.0.15": version "18.0.15" resolved "https://registry.yarnpkg.com/@types/react/-/react-18.0.15.tgz#d355644c26832dc27f3e6cbf0c4f4603fc4ab7fe" integrity sha512-iz3BtLuIYH1uWdsv6wXYdhozhqj20oD4/Hk2DNXIn1kFsmp9x8d9QB6FnPhfkbhd2PgEONt9Q1x/ebkwjfFLow== @@ -3715,11 +3719,6 @@ cliui@^6.0.0: strip-ansi "^6.0.0" wrap-ansi "^6.2.0" -clsx@^1.0.4: - version "1.2.1" - resolved "https://registry.yarnpkg.com/clsx/-/clsx-1.2.1.tgz#0ddc4a20a549b59c93a4116bb26f5294ca17dc12" - integrity sha512-EcR6r5a8bj6pu3ycsa/E/cKVGuTgZJZdsyUYHOksG/UHIiKfjxzRxYJpyVBwYaQeOvghal9fcc4PidlgzugAQg== - co@^4.6.0: version "4.6.0" resolved "https://registry.yarnpkg.com/co/-/co-4.6.0.tgz#6ea6bdf3d853ae54ccb8e47bfa0bf3f9031fb184" @@ -4567,7 +4566,7 @@ dom-converter@^0.2.0: dependencies: utila "~0.4" -dom-helpers@^5.0.1, dom-helpers@^5.1.3, dom-helpers@^5.2.0, dom-helpers@^5.2.1: +dom-helpers@^5.0.1, dom-helpers@^5.2.0, dom-helpers@^5.2.1: version "5.2.1" resolved "https://registry.yarnpkg.com/dom-helpers/-/dom-helpers-5.2.1.tgz#d9400536b2bf8225ad98fe052e029451ac40e902" integrity sha512-nRCa7CK3VTrM2NmGkIy4cbK7IZlgBE/PYMn55rrXefr5xXDP0LdtfPnblFDoVdcAfslJ7or6iqAUnx0CCGIWQA== @@ -9420,7 +9419,7 @@ prop-types@15.7.2: object-assign "^4.1.1" react-is "^16.8.1" -prop-types@^15.6.2, prop-types@^15.7.2, prop-types@^15.8.1: +prop-types@^15.6.2, prop-types@^15.8.1: version "15.8.1" resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.8.1.tgz#67d87bf1a694f48435cf332c24af10214a3140b5" integrity sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg== @@ -9757,18 +9756,6 @@ react-transition-group@^4.4.2: loose-envify "^1.4.0" prop-types "^15.6.2" -react-virtualized@^9.22.3: - version "9.22.3" - resolved "https://registry.yarnpkg.com/react-virtualized/-/react-virtualized-9.22.3.tgz#f430f16beb0a42db420dbd4d340403c0de334421" - integrity sha512-MKovKMxWTcwPSxE1kK1HcheQTWfuCxAuBoSTf2gwyMM21NdX/PXUhnoP8Uc5dRKd+nKm8v41R36OellhdCpkrw== - dependencies: - "@babel/runtime" "^7.7.2" - clsx "^1.0.4" - dom-helpers "^5.1.3" - loose-envify "^1.4.0" - prop-types "^15.7.2" - react-lifecycles-compat "^3.0.4" - react-youtube@^7.13.1: version "7.14.0" resolved "https://registry.yarnpkg.com/react-youtube/-/react-youtube-7.14.0.tgz#0505d86491521ca94ef0afb74af3f7936dc7bc86"