diff --git a/client/packages/design/components/VirtualChatList/README.md b/client/packages/design/components/VirtualChatList/README.md new file mode 100644 index 00000000..b72d20eb --- /dev/null +++ b/client/packages/design/components/VirtualChatList/README.md @@ -0,0 +1,5 @@ +WIP: Warning + +可变高度的虚拟列表 + +专为聊天场景打造的 diff --git a/client/packages/design/components/VirtualChatList/ResizeWatcher.tsx b/client/packages/design/components/VirtualChatList/ResizeWatcher.tsx new file mode 100644 index 00000000..61273f0c --- /dev/null +++ b/client/packages/design/components/VirtualChatList/ResizeWatcher.tsx @@ -0,0 +1,60 @@ +import React, { useEffect, useRef } from 'react'; +import { useMemoizedFn } from 'ahooks'; + +type Size = { height: number; width: number }; + +interface ResizeWatcherProps { + wrapperStyle?: React.CSSProperties; + onResize?: (size: Size) => void; +} + +/** + * 当容器大小发生变化时 + * 触发回调 + */ +export const ResizeWatcher: React.FC = React.memo( + (props) => { + const rootRef = useRef(null); + + const handleResize = useMemoizedFn((size: Size) => { + if (props.onResize) { + props.onResize(size); + } + }); + + useEffect(() => { + if (!rootRef.current) { + return; + } + + const resizeObserver = new ResizeObserver((entries) => { + entries.forEach((entry) => { + const { target, contentRect } = entry; + if (!target.parentElement) { + return; + } + + handleResize({ + width: Math.round(contentRect.width), + height: Math.round(contentRect.height), + }); + }); + }); + resizeObserver.observe(rootRef.current); + + return () => { + if (resizeObserver && rootRef.current) { + resizeObserver.unobserve(rootRef.current); + resizeObserver.disconnect(); + } + }; + }, []); + + return ( +
+ {props.children} +
+ ); + } +); +ResizeWatcher.displayName = 'ResizeWatcher'; diff --git a/client/packages/design/components/VirtualChatList/Scroller.tsx b/client/packages/design/components/VirtualChatList/Scroller.tsx new file mode 100644 index 00000000..4c9fe62f --- /dev/null +++ b/client/packages/design/components/VirtualChatList/Scroller.tsx @@ -0,0 +1,164 @@ +import React, { PropsWithChildren, useMemo, useRef, useState } from 'react'; +import { ResizeWatcher } from './ResizeWatcher'; +import { useMemoizedFn, useDebounceFn, usePrevious } from 'ahooks'; +import { IsForward, Vector } from './types'; +import clsx from 'clsx'; + +export interface ScrollerRef { + scrollTo: (position: Vector) => void; + getMaxPosition: () => Vector; +} + +type ScrollerProps = PropsWithChildren<{ + className?: string; + style?: React.CSSProperties; + innerStyle?: React.CSSProperties; + isLock?: boolean; + scrollingClassName?: string; + onScroll?: ( + position: Vector, + detail: { + forward: IsForward; + isUserScrolling: boolean; + isMouseDown: boolean; + } + ) => void; + onScrollEnd?: (position: Vector) => void; + onContainerResize?: (info: { + containerSize: Vector; + position: Vector; + }) => void; +}>; + +const DEFAULT_POS = { x: 0, y: 0 }; + +/** + * 滚动状态管理组件 + */ +export const Scroller = React.forwardRef( + (props, ref) => { + const wrapperRef = useRef(null); + const innerRef = useRef(null); + const style = useMemo(() => { + if (props.isLock ?? false) { + return { ...props.style, overflow: 'hidden' }; + } + return props.style; + }, []); + + const [isScroll, setIsScroll] = useState(false); + const [isMouseDown, setIsMouseDown] = useState(false); + const { run: setIsScrollLazy } = useDebounceFn( + (val) => { + setIsScroll(val); + }, + { + leading: false, + trailing: true, + wait: 300, + } + ); + + const getPosition = useMemoizedFn(() => { + if (!wrapperRef.current) { + return DEFAULT_POS; + } + return { + x: wrapperRef.current.scrollLeft, + y: wrapperRef.current.scrollTop, + }; + }); + + const getContainerSize = useMemoizedFn(() => { + if (!wrapperRef.current) { + return DEFAULT_POS; + } + return { + x: wrapperRef.current.clientWidth, + y: wrapperRef.current.clientHeight, + }; + }); + + const { run: handleEndScrollLazy } = useDebounceFn( + () => { + setIsScroll(false); + if (props.onScrollEnd) { + props.onScrollEnd(getPosition()); + } + }, + { + leading: false, + trailing: true, + wait: 300, + } + ); + + const handleWheel = useMemoizedFn(() => { + setIsScroll(true); + setIsScrollLazy(false); + }); + + const handleMouseDown = useMemoizedFn(() => { + setIsMouseDown(true); + }); + + const handleMouseUp = useMemoizedFn(() => { + setIsMouseDown(false); + }); + + const prevPosition = usePrevious(getPosition()) ?? DEFAULT_POS; + const handleMouseScroll = useMemoizedFn(() => { + const isUserScrolling = isScroll || isMouseDown; + const currentPosition = getPosition(); + const forward = { + x: currentPosition.x > prevPosition.x, + y: currentPosition.y > prevPosition.y, + }; + setIsScroll(true); + handleEndScrollLazy(); + if (props.onScroll) { + props.onScroll(currentPosition, { + forward, + isUserScrolling, + isMouseDown: isMouseDown, + }); + } + }); + + const handleResize = useMemoizedFn(() => { + if (props.onContainerResize) { + props.onContainerResize({ + containerSize: getContainerSize(), + position: getPosition(), + }); + } + }); + + return ( + +
+
+ {props.children} +
+
+
+ ); + } +); +Scroller.displayName = 'Scroller'; diff --git a/client/packages/design/components/VirtualChatList/index.stories.tsx b/client/packages/design/components/VirtualChatList/index.stories.tsx new file mode 100644 index 00000000..b9dfdef0 --- /dev/null +++ b/client/packages/design/components/VirtualChatList/index.stories.tsx @@ -0,0 +1,22 @@ +import React from 'react'; +import { ComponentStory, ComponentMeta } from '@storybook/react'; +import { VirtualChatList } from '.'; + +// More on default export: https://storybook.js.org/docs/react/writing-stories/introduction#default-export +export default { + title: 'Tailchat/VirtualChatList', + component: VirtualChatList, + // More on argTypes: https://storybook.js.org/docs/react/api/argtypes + argTypes: {}, +} as ComponentMeta; + +// More on component templates: https://storybook.js.org/docs/react/writing-stories/introduction#using-args +const Template: ComponentStory = (args) => ( + +); + +export const Default = Template.bind({}); +// More on args: https://storybook.js.org/docs/react/writing-stories/args +Default.args = { + text: 'fooooo', +}; diff --git a/client/packages/design/components/VirtualChatList/index.tsx b/client/packages/design/components/VirtualChatList/index.tsx new file mode 100644 index 00000000..19a7e9cb --- /dev/null +++ b/client/packages/design/components/VirtualChatList/index.tsx @@ -0,0 +1,14 @@ +import React, { useRef } from 'react'; +import { Scroller, ScrollerRef } from './Scroller'; + +export const VirtualChatList: React.FC = React.memo(() => { + const scrollerRef = useRef(null); + + return ( + + {/* TODO */} +
Foo
+
+ ); +}); +VirtualChatList.displayName = 'VirtualChatList'; diff --git a/client/packages/design/components/VirtualChatList/types.ts b/client/packages/design/components/VirtualChatList/types.ts new file mode 100644 index 00000000..36a6884c --- /dev/null +++ b/client/packages/design/components/VirtualChatList/types.ts @@ -0,0 +1,9 @@ +export interface Vector { + x: number; + y: number; +} + +export interface IsForward { + x: boolean; + y: boolean; +} diff --git a/client/packages/design/package.json b/client/packages/design/package.json index 80a4f82e..0ea31e06 100644 --- a/client/packages/design/package.json +++ b/client/packages/design/package.json @@ -23,7 +23,9 @@ "homepage": "https://github.com/msgbyte/tailchat#readme", "dependencies": { "@iconify/react": "^3.2.1", + "ahooks": "^3.7.1", "antd": "^4.19.5", + "clsx": "^1.1.1", "lodash": "^4.17.21", "react-fastify-form": "1.0.10", "str2int": "^1.1.0" @@ -37,6 +39,8 @@ "@storybook/react": "^6.4.22", "@storybook/testing-library": "^0.0.11", "@types/lodash": "^4.14.170", + "@types/react": "^17.0.39", + "@types/react-dom": "^17.0.8", "babel-loader": "^8.2.5", "react": "17.0.2", "react-dom": "17.0.2", diff --git a/client/web/package.json b/client/web/package.json index 6cc468e3..deee03ae 100644 --- a/client/web/package.json +++ b/client/web/package.json @@ -54,7 +54,7 @@ "react-transition-group": "^4.4.2", "react-use-gesture": "^9.1.3", "react-virtualized-auto-sizer": "^1.0.6", - "react-virtuoso": "^2.8.3", + "react-virtuoso": "^2.18.0", "socket.io-client": "^4.1.2", "source-ref-runtime": "^1.0.7", "tailchat-design": "workspace:^1.0.0", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 24fa6935..cd08c54b 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -67,8 +67,12 @@ importers: '@storybook/react': ^6.4.22 '@storybook/testing-library': ^0.0.11 '@types/lodash': ^4.14.170 + '@types/react': ^17.0.39 + '@types/react-dom': ^17.0.8 + ahooks: ^3.7.1 antd: ^4.19.5 babel-loader: ^8.2.5 + clsx: ^1.1.1 lodash: ^4.17.21 react: 17.0.2 react-dom: 17.0.2 @@ -78,7 +82,9 @@ importers: webpack: ^5.72.0 dependencies: '@iconify/react': 3.2.2_react@17.0.2 + ahooks: 3.7.1_react@17.0.2 antd: 4.22.8_sfoxds7t5ydpegc3knd667wn6m + clsx: 1.2.1 lodash: 4.17.21 react-fastify-form: 1.0.10_react@17.0.2 str2int: 1.1.0 @@ -86,11 +92,13 @@ importers: '@babel/core': 7.18.13 '@storybook/addon-actions': 6.5.10_sfoxds7t5ydpegc3knd667wn6m '@storybook/addon-essentials': 6.5.10_syz2u4gb4ghy424l3cvhntynam - '@storybook/addon-interactions': 6.5.10_3tgeifm2vmwrlpqlopppsnjtcu + '@storybook/addon-interactions': 6.5.10_dscil3oxjefkmogs52lepurcyi '@storybook/addon-links': 6.5.10_sfoxds7t5ydpegc3knd667wn6m '@storybook/react': 6.5.10_d6mkdkfnct6ha2zsg6gmc4s2je '@storybook/testing-library': 0.0.11_sfoxds7t5ydpegc3knd667wn6m '@types/lodash': 4.14.184 + '@types/react': 17.0.48 + '@types/react-dom': 17.0.17 babel-loader: 8.2.5_tb6moc662p5idmcg3l5ipbhpta react: 17.0.2 react-dom: 17.0.2_react@17.0.2 @@ -269,7 +277,7 @@ importers: react-transition-group: ^4.4.2 react-use-gesture: ^9.1.3 react-virtualized-auto-sizer: ^1.0.6 - react-virtuoso: ^2.8.3 + react-virtuoso: ^2.18.0 rimraf: ^3.0.2 rollup-plugin-copy: ^3.4.0 rollup-plugin-replace: ^2.2.0 @@ -327,7 +335,7 @@ importers: react-transition-group: 4.4.5_sfoxds7t5ydpegc3knd667wn6m react-use-gesture: 9.1.3_react@17.0.2 react-virtualized-auto-sizer: 1.0.6_sfoxds7t5ydpegc3knd667wn6m - react-virtuoso: 2.17.2_sfoxds7t5ydpegc3knd667wn6m + react-virtuoso: 2.18.0_sfoxds7t5ydpegc3knd667wn6m socket.io-client: 4.5.1 source-ref-runtime: 1.0.7 tailchat-design: link:../packages/design @@ -2634,7 +2642,7 @@ packages: engines: {node: '>=10'} dev: false - /@design-systems/utils/2.12.0_sfoxds7t5ydpegc3knd667wn6m: + /@design-systems/utils/2.12.0_sk3eihvpffgp52mstba5zhq3vu: resolution: {integrity: sha512-Y/d2Zzr+JJfN6u1gbuBUb1ufBuLMJJRZQk+dRmw8GaTpqKx5uf7cGUYGTwN02dIb3I+Tf+cW8jcGBTRiFxdYFg==} peerDependencies: '@types/react': '*' @@ -2642,22 +2650,23 @@ packages: react-dom: '>= 16.8.6' dependencies: '@babel/runtime': 7.18.9 - clsx: 1.1.0 + '@types/react': 17.0.48 + clsx: 1.2.1 focus-lock: 0.8.1 react: 17.0.2 react-dom: 17.0.2_react@17.0.2 react-merge-refs: 1.1.0 dev: true - /@devtools-ds/object-inspector/1.2.0_sfoxds7t5ydpegc3knd667wn6m: + /@devtools-ds/object-inspector/1.2.0_sk3eihvpffgp52mstba5zhq3vu: resolution: {integrity: sha512-VztcwqVwScSvYdvJVZBJYsVO/2Pew3JPpFV3T9fuCHQLlHcLYOV3aU/kBS2ScuE2O1JN0ZbobLqFLa3vQF54Fw==} peerDependencies: react: '>= 16.8.6' dependencies: '@babel/runtime': 7.7.2 '@devtools-ds/object-parser': 1.2.0 - '@devtools-ds/themes': 1.2.0_sfoxds7t5ydpegc3knd667wn6m - '@devtools-ds/tree': 1.2.0_sfoxds7t5ydpegc3knd667wn6m + '@devtools-ds/themes': 1.2.0_sk3eihvpffgp52mstba5zhq3vu + '@devtools-ds/tree': 1.2.0_sk3eihvpffgp52mstba5zhq3vu clsx: 1.1.0 react: 17.0.2 transitivePeerDependencies: @@ -2671,13 +2680,13 @@ packages: '@babel/runtime': 7.5.5 dev: true - /@devtools-ds/themes/1.2.0_sfoxds7t5ydpegc3knd667wn6m: + /@devtools-ds/themes/1.2.0_sk3eihvpffgp52mstba5zhq3vu: resolution: {integrity: sha512-LimEITorE6yWZWWuMc6OiBfLQgPrQqWbyMEmfRUDPa3PHXoAY4SpDxczfg31fgyRDUNWnZhjaJH5bBbu8VEbIw==} peerDependencies: react: '>= 16.8.6' dependencies: '@babel/runtime': 7.5.5 - '@design-systems/utils': 2.12.0_sfoxds7t5ydpegc3knd667wn6m + '@design-systems/utils': 2.12.0_sk3eihvpffgp52mstba5zhq3vu clsx: 1.1.0 react: 17.0.2 transitivePeerDependencies: @@ -2685,13 +2694,13 @@ packages: - react-dom dev: true - /@devtools-ds/tree/1.2.0_sfoxds7t5ydpegc3knd667wn6m: + /@devtools-ds/tree/1.2.0_sk3eihvpffgp52mstba5zhq3vu: resolution: {integrity: sha512-hC4g4ocuo2eg7jsnzKdauxH0sDQiPW3KSM2+uK3kRgcmr9PzpBD5Kob+Y/WFSVKswFleftOGKL4BQLuRv0sPxA==} peerDependencies: react: '>= 16.8.6' dependencies: '@babel/runtime': 7.7.2 - '@devtools-ds/themes': 1.2.0_sfoxds7t5ydpegc3knd667wn6m + '@devtools-ds/themes': 1.2.0_sk3eihvpffgp52mstba5zhq3vu clsx: 1.1.0 react: 17.0.2 transitivePeerDependencies: @@ -2910,7 +2919,7 @@ packages: '@docusaurus/react-loadable': 5.5.2_react@17.0.2 '@docusaurus/types': 2.0.1_sfoxds7t5ydpegc3knd667wn6m '@types/history': 4.7.11 - '@types/react': 17.0.48 + '@types/react': 18.0.17 '@types/react-router-config': 5.0.6 '@types/react-router-dom': 5.3.3 react: 17.0.2 @@ -3355,7 +3364,7 @@ packages: react-dom: ^16.8.4 || ^17.0.0 dependencies: '@types/history': 4.7.11 - '@types/react': 17.0.48 + '@types/react': 18.0.17 commander: 5.1.0 joi: 17.6.0 react: 17.0.2 @@ -4418,7 +4427,7 @@ packages: - webpack-command dev: true - /@storybook/addon-interactions/6.5.10_3tgeifm2vmwrlpqlopppsnjtcu: + /@storybook/addon-interactions/6.5.10_dscil3oxjefkmogs52lepurcyi: resolution: {integrity: sha512-+O/ZuQjonpFmTdFRqjCimQTx4S4c1+S3dYCn6gD/E4xzqlQn1BQaER3paX/aBUKb3oRaSO9RUQ+uxePM4zBEwA==} peerDependencies: react: ^16.8.0 || ^17.0.0 || ^18.0.0 @@ -4429,7 +4438,7 @@ packages: react-dom: optional: true dependencies: - '@devtools-ds/object-inspector': 1.2.0_sfoxds7t5ydpegc3knd667wn6m + '@devtools-ds/object-inspector': 1.2.0_sk3eihvpffgp52mstba5zhq3vu '@storybook/addons': 6.5.10_sfoxds7t5ydpegc3knd667wn6m '@storybook/api': 6.5.10_sfoxds7t5ydpegc3knd667wn6m '@storybook/client-logger': 6.5.10 @@ -5805,7 +5814,7 @@ packages: optional: true dependencies: '@babel/runtime': 7.18.9 - '@types/react': 17.0.48 + '@types/react': 18.0.17 '@types/react-dom': 17.0.17 '@types/react-test-renderer': 18.0.0 react: 17.0.2 @@ -6037,7 +6046,7 @@ packages: /@types/emoji-mart/3.0.9: resolution: {integrity: sha512-qdBo/2Y8MXaJ/2spKjDZocuq79GpnOhkwMHnK2GnVFa8WYFgfA+ei6sil3aeWQPCreOKIx9ogPpR5+7MaOqYAA==} dependencies: - '@types/react': 17.0.48 + '@types/react': 18.0.17 dev: true /@types/eslint-scope/3.7.4: @@ -6199,6 +6208,10 @@ packages: pretty-format: 27.5.1 dev: true + /@types/js-cookie/2.2.7: + resolution: {integrity: sha512-aLkWa0C0vO5b4Sr798E26QgOkss68Un0bLjs7u9qxzPT5CG+8DuNTffWES58YzJs3hrVAOs1wonycqEBqNJubA==} + dev: false + /@types/json-buffer/3.0.0: resolution: {integrity: sha512-3YP80IxxFJB4b5tYC2SUPwkg0XQLiu0nWvhRgEatgjf+29IcWO9X1k8xRv5DGssJ/lCrjYTjQPcobJr2yWIVuQ==} dev: false @@ -6247,7 +6260,7 @@ packages: /@types/loadable__component/5.13.4: resolution: {integrity: sha512-YhoCCxyuvP2XeZNbHbi8Wb9EMaUJuA2VGHxJffcQYrJKIKSkymJrhbzsf9y4zpTmr5pExAAEh5hbF628PAZ8Dg==} dependencies: - '@types/react': 17.0.48 + '@types/react': 18.0.17 dev: true /@types/lodash/4.14.184: @@ -6396,7 +6409,7 @@ packages: /@types/react-helmet/6.1.5: resolution: {integrity: sha512-/ICuy7OHZxR0YCAZLNg9r7I9aijWUWvxaPR6uTuyxe8tAj5RL4Sw1+R6NhXUtOsarkGYPmaHdBDvuXh2DIN/uA==} dependencies: - '@types/react': 17.0.48 + '@types/react': 18.0.17 dev: true /@types/react-highlight/0.12.5: @@ -6408,7 +6421,7 @@ packages: /@types/react-mentions/4.1.6: resolution: {integrity: sha512-f4/BdnjlMxT47q+WqlcYYwFABbBMVQrDoFFeMeljtFC5nnR9/x8TOFmN18BJKgNuWMgivy9uE5EKtsjlay751w==} dependencies: - '@types/react': 17.0.48 + '@types/react': 18.0.17 dev: true /@types/react-redux/7.1.24: @@ -6423,38 +6436,38 @@ packages: resolution: {integrity: sha512-db1mx37a1EJDf1XeX8jJN7R3PZABmJQXR8r28yUjVMFSjkmnQo6X6pOEEmNl+Tp2gYQOGPdYbFIipBtdElZ3Yg==} dependencies: '@types/history': 4.7.11 - '@types/react': 17.0.48 + '@types/react': 18.0.17 '@types/react-router': 5.1.18 /@types/react-router-dom/5.3.3: resolution: {integrity: sha512-kpqnYK4wcdm5UaWI3fLcELopqLrHgLqNsdpHauzlQktfkHL3npOSwtj1Uz9oKBAzs7lFtVkV8j83voAz2D8fhw==} dependencies: '@types/history': 4.7.11 - '@types/react': 17.0.48 + '@types/react': 18.0.17 '@types/react-router': 5.1.18 /@types/react-router/5.1.18: resolution: {integrity: sha512-YYknwy0D0iOwKQgz9v8nOzt2J6l4gouBmDnWqUUznltOTaon+r8US8ky8HvN0tXvc38U9m6z/t2RsVsnd1zM0g==} dependencies: '@types/history': 4.7.11 - '@types/react': 17.0.48 + '@types/react': 18.0.17 /@types/react-test-renderer/18.0.0: resolution: {integrity: sha512-C7/5FBJ3g3sqUahguGi03O79b8afNeSD6T8/GU50oQrJCU0bVCCGQHaGKUbg2Ce8VQEEqTw8/HiS6lXHHdgkdQ==} dependencies: - '@types/react': 17.0.48 + '@types/react': 18.0.17 dev: true /@types/react-transition-group/4.4.5: resolution: {integrity: sha512-juKD/eiSM3/xZYzjuzH6ZwpP+/lejltmiS3QEzV/vmb/Q8+HfDmxu+Baga8UEMGBqV88Nbg4l2hY/K2DkyaLLA==} dependencies: - '@types/react': 17.0.48 + '@types/react': 18.0.17 dev: true /@types/react-virtualized-auto-sizer/1.0.1: resolution: {integrity: sha512-GH8sAnBEM5GV9LTeiz56r4ZhMOUSrP43tAQNSRVxNexDjcNKLCEtnxusAItg1owFUFE6k0NslV26gqVClVvong==} dependencies: - '@types/react': 17.0.48 + '@types/react': 18.0.17 dev: true /@types/react-virtualized/9.21.21: @@ -7229,6 +7242,27 @@ packages: clean-stack: 2.2.0 indent-string: 4.0.0 + /ahooks-v3-count/1.0.0: + resolution: {integrity: sha512-V7uUvAwnimu6eh/PED4mCDjE7tokeZQLKlxg9lCTMPhN+NjsSbtdacByVlR1oluXQzD3MOw55wylDmQo4+S9ZQ==} + dev: false + + /ahooks/3.7.1_react@17.0.2: + resolution: {integrity: sha512-9fooKjhScNyJaIPnlWd13LkY1gQYqv3BqwSA9ynHg1ZUtDqAICuCRoedV97ylrEL6QqI4zeq3bO3lQxkfWVNcg==} + engines: {node: '>=8.0.0'} + peerDependencies: + react: ^16.8.0 || ^17.0.0 || ^18.0.0 + dependencies: + '@types/js-cookie': 2.2.7 + ahooks-v3-count: 1.0.0 + dayjs: 1.11.5 + intersection-observer: 0.12.2 + js-cookie: 2.2.1 + lodash: 4.17.21 + react: 17.0.2 + resize-observer-polyfill: 1.5.1 + screenfull: 5.2.0 + dev: false + /airbnb-js-shims/2.2.1: resolution: {integrity: sha512-wJNXPH66U2xjgo1Zwyjf9EydvJ2Si94+vSdk6EERcBfB2VZkeltpqIats0cqIZMLCXP3zcyaUKGYQeIBT6XjsQ==} dependencies: @@ -9016,7 +9050,6 @@ packages: /clsx/1.2.1: resolution: {integrity: sha512-EcR6r5a8bj6pu3ycsa/E/cKVGuTgZJZdsyUYHOksG/UHIiKfjxzRxYJpyVBwYaQeOvghal9fcc4PidlgzugAQg==} engines: {node: '>=6'} - dev: false /clui/0.3.6: resolution: {integrity: sha512-Z4UbgZILlIAjkEkZiDOa2aoYjohKx7fa6DxIh6cE9A6WNWZ61iXfQc6CmdC9SKdS5nO0P0UyQ+WfoXfB65e3HQ==} @@ -13938,6 +13971,10 @@ packages: engines: {node: '>= 0.10'} dev: true + /intersection-observer/0.12.2: + resolution: {integrity: sha512-7m1vEcPCxXYI8HqnL8CKI6siDyD+eIWSwgB3DZA+ZTogxk9I4CDnj4wilt9x/+/QbHI4YG5YZNmC6458/e9Ktg==} + dev: false + /into-stream/3.1.0: resolution: {integrity: sha512-TcdjPibTksa1NQximqep2r17ISRiNE9fwlfbg3F8ANdvP5/yrFTew86VcO//jk4QTaMlbjypPBq76HN2zaKfZQ==} engines: {node: '>=4'} @@ -15186,6 +15223,10 @@ packages: resolution: {integrity: sha512-NnRs6dsyqUXejqk/yv2aiXlAvOs56sLkX6nUdeaNezI5LFFLlsZjOThmwnrcwh5ZZRwZlCMnVAY3CvhIhoVEKQ==} dev: false + /js-cookie/2.2.1: + resolution: {integrity: sha512-HvdH2LzI/EAZcUwA8+0nKNtWHqS+ZmijLA30RwZA0bo7ToCckjK5MkGhjED9KoRcXO6BaGI3I9UIzSA1FKFPOQ==} + dev: false + /js-sha3/0.8.0: resolution: {integrity: sha512-gF1cRrHhIzNfToc802P800N8PpXS+evLLXfsVpowqmAFR9uwbi89WvXg2QspOmXL8QL86J4T1EpFu+yUkwJY3Q==} dev: false @@ -20276,8 +20317,8 @@ packages: react-dom: 17.0.2_react@17.0.2 dev: false - /react-virtuoso/2.17.2_sfoxds7t5ydpegc3knd667wn6m: - resolution: {integrity: sha512-5xl0mCCVEANzY0SbVbUjQgRrc2it3vdGCn72kUQo0wy4s3QGVR8S3QcLZj3lBrHocGIf/ONEJ3g/uqs0KEl9eA==} + /react-virtuoso/2.18.0_sfoxds7t5ydpegc3knd667wn6m: + resolution: {integrity: sha512-BxMW9as2dPOP4YFkry/oNjQMEn3cOgEjHLb7Fg8oubOgRAfiukp1Co41QFD9ZMXZBNBZNTI2E5BwC5pol31mTg==} engines: {node: '>=10'} peerDependencies: react: '>=16 || >=17 || >= 18' @@ -21183,6 +21224,11 @@ packages: ajv-formats: 2.1.1 ajv-keywords: 5.1.0_ajv@8.11.0 + /screenfull/5.2.0: + resolution: {integrity: sha512-9BakfsO2aUQN2K9Fdbj87RJIEZ82Q9IGim7FqM5OsebfoFC6ZHXgDq/KvniuLTPdeM8wY2o6Dj3WQ7KeQCj3cA==} + engines: {node: '>=0.10.0'} + dev: false + /script_sanitize/1.2.6: resolution: {integrity: sha512-CA53o9tyResT5Sq8HT4w6jcmHoYtfbBxRKvaBQc0Iw0kS4+c9MDNwl1ReUcFjbb/GFm8YjB7diTJE10MWOnHNQ==} dev: false