From 4662d2924b19381f180fff42c3de76305bb969cd Mon Sep 17 00:00:00 2001 From: Abdelrahman Ashraf Date: Sat, 14 Dec 2024 12:31:34 +0700 Subject: [PATCH] fix(react): cannot transfer control from a canvas more than once #326 --- .../src/pages/index.tsx | 66 +- packages/react/package.json | 16 +- packages/react/setup-file.ts | 8 + packages/react/src/base-dotlottie-react.tsx | 248 ++ packages/react/src/dotlottie-worker.tsx | 69 +- packages/react/src/dotlottie.tsx | 67 +- packages/react/src/index.ts | 4 +- packages/react/src/use-dotlottie-worker.tsx | 264 -- packages/react/src/use-dotlottie.tsx | 263 -- packages/react/src/use-stable-callback.tsx | 20 - packages/react/tests/__fixtures__/test.json | 3263 +++++++++++++++++ packages/react/tests/__fixtures__/test.lottie | Bin 0 -> 1446 bytes .../dotlottie-react.spec.tsx.snap | 25 + packages/react/tests/dotlottie-react.spec.tsx | 688 ++++ packages/react/tsup.config.cjs | 11 +- packages/react/vitest.config.ts | 29 + pnpm-lock.yaml | 321 +- 17 files changed, 4484 insertions(+), 878 deletions(-) create mode 100644 packages/react/setup-file.ts create mode 100644 packages/react/src/base-dotlottie-react.tsx delete mode 100644 packages/react/src/use-dotlottie-worker.tsx delete mode 100644 packages/react/src/use-dotlottie.tsx delete mode 100644 packages/react/src/use-stable-callback.tsx create mode 100644 packages/react/tests/__fixtures__/test.json create mode 100644 packages/react/tests/__fixtures__/test.lottie create mode 100644 packages/react/tests/__snapshots__/dotlottie-react.spec.tsx.snap create mode 100644 packages/react/tests/dotlottie-react.spec.tsx create mode 100644 packages/react/vitest.config.ts diff --git a/apps/dotlottie-next-example/src/pages/index.tsx b/apps/dotlottie-next-example/src/pages/index.tsx index c787479d..2570781b 100644 --- a/apps/dotlottie-next-example/src/pages/index.tsx +++ b/apps/dotlottie-next-example/src/pages/index.tsx @@ -1,6 +1,8 @@ +import type { DotLottie, DotLottieWorker } from '@lottiefiles/dotlottie-react'; import { DotLottieReact } from '@lottiefiles/dotlottie-react'; import { Inter } from 'next/font/google'; import Head from 'next/head'; +import { useState } from 'react'; import styles from '@/styles/Home.module.css'; @@ -9,6 +11,9 @@ const inter = Inter({ subsets: ['latin'] }); const src = 'https://lottie.host/e641272e-039b-4612-96de-138acfbede6e/bc0sW78EeR.lottie'; export default function Home(): JSX.Element { + const [dotLottie, setDotLottie] = useState(null); + const [showDotLottie, setShowDotLottie] = useState(false); + return ( <> @@ -18,17 +23,56 @@ export default function Home(): JSX.Element {
- + {showDotLottie && ( + + )} +
+ + + + +
); diff --git a/packages/react/package.json b/packages/react/package.json index 393ff22f..19d2d474 100644 --- a/packages/react/package.json +++ b/packages/react/package.json @@ -38,6 +38,9 @@ "lint": "eslint --fix .", "stats:eslint": "cross-env TIMING=1 eslint .", "stats:ts": "tsc -p tsconfig.build.json --extendedDiagnostics", + "test": "vitest run --browser.headless", + "test:coverage": "vitest run --browser.headless --coverage", + "test:watch": "vitest", "type-check": "tsc --noEmit" }, "peerDependencies": { @@ -47,11 +50,18 @@ "@lottiefiles/dotlottie-web": "workspace:*" }, "devDependencies": { - "@types/react": "^19.0.1", + "@testing-library/user-event": "^14.5.2", + "@types/react": "^18", + "@vitejs/plugin-react": "^4.2.1", + "@vitest/browser": "2.1.0-beta.5", + "@vitest/coverage-istanbul": "2.1.0-beta.5", "cross-env": "7.0.3", - "react": "^19.0.0", + "playwright": "1.45.2", + "react": "^18", "tsup": "8.3.5", - "typescript": "5.0.4" + "typescript": "5.0.4", + "vitest": "2.1.0-beta.5", + "vitest-browser-react": "^0.0.4" }, "publishConfig": { "access": "public", diff --git a/packages/react/setup-file.ts b/packages/react/setup-file.ts new file mode 100644 index 00000000..edc53adf --- /dev/null +++ b/packages/react/setup-file.ts @@ -0,0 +1,8 @@ +// eslint-disable-next-line import/no-unassigned-import +import 'vitest-browser-react'; +import { setWasmUrl } from './src'; + +// eslint-disable-next-line node/no-unsupported-features/node-builtins +const wasmUrl = new URL('../web/src/core/dotlottie-player.wasm?url', import.meta.url).href; + +setWasmUrl(wasmUrl); diff --git a/packages/react/src/base-dotlottie-react.tsx b/packages/react/src/base-dotlottie-react.tsx new file mode 100644 index 00000000..e07a878f --- /dev/null +++ b/packages/react/src/base-dotlottie-react.tsx @@ -0,0 +1,248 @@ +/* eslint-disable no-warning-comments */ +'use client'; + +import type { Config, DotLottie, DotLottieWorker } from '@lottiefiles/dotlottie-web'; +import { useState, useEffect, useCallback, useRef, type ComponentProps, type RefCallback } from 'react'; +import type { JSX } from 'react'; + +export type BaseDotLottieProps = Omit & + ComponentProps<'canvas'> & { + animationId?: string; + /** + * A function that creates a `DotLottie` or `DotLottieWorker` instance. + */ + createDotLottie: (config: T extends DotLottieWorker ? Config & { workerId?: string } : Config) => T; + /** + * A callback function that receives the `DotLottie` or `DotLottieWorker` instance. + * + * @example + * ```tsx + * const [dotLottie, setDotLottie] = useState(null); + * + * + * ``` + */ + dotLottieRefCallback?: RefCallback; + /** + * @deprecated The `playOnHover` property is deprecated. + * Instead, use the `onMouseEnter` and `onMouseLeave` events to control animation playback. + * Utilize the `dotLottieRefCallback` to access the `DotLottie` instance and invoke the `play` and `pause` methods. + * + * Example usage: + * ```tsx + * const [dotLottie, setDotLottie] = useState(null); + * + * dotLottie?.play()} + * onMouseLeave={() => dotLottie?.pause()} + * /> + * ``` + */ + playOnHover?: boolean; + themeData?: string; + workerId?: T extends DotLottieWorker ? string : undefined; + }; + +export const BaseDotLottieReact = ({ + animationId, + autoplay, + backgroundColor, + className, + createDotLottie, + data, + dotLottieRefCallback, + loop, + mode, + playOnHover, + renderConfig, + segment, + speed, + src, + style, + themeData, + themeId, + useFrameInterpolation, + workerId, + ...props +}: BaseDotLottieProps & { + createDotLottie: (config: T extends DotLottieWorker ? Config & { workerId?: string } : Config) => T; +}): JSX.Element => { + const [dotLottie, setDotLottie] = useState(null); + const canvasRef = useRef(null); + const dotLottieRef = useRef(null); + const dotLottieRefCallbackRef = useRef | undefined>(dotLottieRefCallback); + + const config: Omit & { + workerId?: T extends DotLottieWorker ? string : undefined; + } = { + speed, + mode, + loop, + useFrameInterpolation, + segment, + backgroundColor, + autoplay, + themeId, + workerId, + src, + data, + renderConfig, + }; + + const configRef = useRef, 'createDotLottie' | 'dotLottieRefCallback'> | undefined>(config); + + dotLottieRefCallbackRef.current = dotLottieRefCallback; + dotLottieRef.current = dotLottie; + configRef.current = config; + + useEffect(() => { + if (typeof dotLottieRefCallbackRef.current === 'function' && dotLottie) { + dotLottieRefCallbackRef.current(dotLottie); + } + }, [dotLottie]); + + const setCanvasRef = useCallback((canvas: HTMLCanvasElement | null) => { + canvasRef.current = canvas; + + if (canvas) { + const dotLottieInstance = createDotLottie({ + ...configRef.current, + canvas, + }); + + setDotLottie(dotLottieInstance as T); + } else { + dotLottie?.destroy(); + setDotLottie(null); + } + }, []); + + useEffect(() => { + const handlePlayOnHover = (event: MouseEvent): void => { + if (!playOnHover) return; + + if (event.type === 'mouseenter') { + dotLottieRef.current?.play(); + } + + if (event.type === 'mouseleave') { + dotLottieRef.current?.pause(); + } + }; + + canvasRef.current?.addEventListener('mouseenter', handlePlayOnHover); + canvasRef.current?.addEventListener('mouseleave', handlePlayOnHover); + + return () => { + canvasRef.current?.removeEventListener('mouseenter', handlePlayOnHover); + canvasRef.current?.removeEventListener('mouseleave', handlePlayOnHover); + }; + }, [playOnHover]); + + useEffect(() => { + return () => { + if (dotLottie) { + dotLottie.destroy(); + setDotLottie(null); + } + }; + }, [dotLottie]); + + useEffect(() => { + dotLottieRef.current?.setSpeed(speed ?? 1); + }, [speed]); + + useEffect(() => { + dotLottieRef.current?.setMode(mode ?? 'forward'); + }, [mode]); + + useEffect(() => { + dotLottieRef.current?.setLoop(loop ?? false); + }, [loop]); + + useEffect(() => { + dotLottieRef.current?.setUseFrameInterpolation(useFrameInterpolation ?? true); + }, [useFrameInterpolation]); + + useEffect(() => { + if (typeof segment?.[0] === 'number' && typeof segment[1] === 'number') { + dotLottieRef.current?.setSegment(segment[0], segment[1]); + } else { + // TODO: implement it for worker + // dotLottieRef.current?.resetSegment(); + } + }, [segment]); + + useEffect(() => { + dotLottieRef.current?.setBackgroundColor(backgroundColor ?? ''); + }, [backgroundColor]); + + useEffect(() => { + dotLottieRef.current?.setRenderConfig(renderConfig ?? {}); + }, [JSON.stringify(renderConfig)]); + + useEffect(() => { + if (typeof data !== 'string' && typeof data !== 'object') return; + + dotLottieRef.current?.load({ + data, + ...configRef.current, + }); + }, [data]); + + useEffect(() => { + if (typeof src !== 'string') return; + + dotLottieRef.current?.load({ + src, + ...configRef.current, + }); + }, [src]); + + useEffect(() => { + dotLottieRef.current?.setMarker(props.marker ?? ''); + }, [props.marker]); + + useEffect(() => { + dotLottieRef.current?.loadAnimation(animationId ?? ''); + }, [animationId]); + + useEffect(() => { + if (typeof themeId === 'string') { + dotLottieRef.current?.setTheme(themeId); + } else { + // TODO: implement it for worker + // dotLottieRef.current?.resetTheme(); + } + }, [themeId]); + + useEffect(() => { + dotLottieRef.current?.setThemeData(themeData ?? ''); + }, [themeData]); + + return ( +
+ +
+ ); +}; diff --git a/packages/react/src/dotlottie-worker.tsx b/packages/react/src/dotlottie-worker.tsx index 6da83fbf..6a548547 100644 --- a/packages/react/src/dotlottie-worker.tsx +++ b/packages/react/src/dotlottie-worker.tsx @@ -1,68 +1,15 @@ 'use client'; -import type { DotLottieWorker, Config } from '@lottiefiles/dotlottie-web'; -import { useEffect, type ComponentProps, type RefCallback, type JSX } from 'react'; +import type { Config } from '@lottiefiles/dotlottie-web'; +import { DotLottieWorker } from '@lottiefiles/dotlottie-web'; -import { useDotLottieWorker } from './use-dotlottie-worker'; -import useStableCallback from './use-stable-callback'; +import { BaseDotLottieReact } from './base-dotlottie-react'; +import type { BaseDotLottieProps } from './base-dotlottie-react'; -export type DotLottieWorkerReactProps = Omit & - ComponentProps<'canvas'> & { - animationId?: string; - dotLottieRefCallback?: RefCallback; - playOnHover?: boolean; - themeData?: string; - themeId?: string; - workerId?: string; - }; +export type DotLottieWorkerReactProps = Omit, 'createDotLottie'>; -export const DotLottieWorkerReact = ({ - animationId, - autoplay, - backgroundColor, - data, - dotLottieRefCallback, - loop, - marker, - mode, - playOnHover, - renderConfig, - segment, - speed, - src, - themeData, - themeId, - useFrameInterpolation, - workerId, - ...props -}: DotLottieWorkerReactProps): JSX.Element => { - const { DotLottieComponent, dotLottie } = useDotLottieWorker({ - workerId, - data, - mode, - speed, - src, - autoplay, - loop, - segment, - renderConfig, - backgroundColor, - useFrameInterpolation, - playOnHover, - marker, - themeId, - animationId, - themeData, - }); +const createDotLottieWorker = (config: Config & { workerId?: string }): DotLottieWorker => new DotLottieWorker(config); - const stableDotLottieRefCallback = - typeof dotLottieRefCallback === 'function' ? useStableCallback(dotLottieRefCallback) : undefined; - - useEffect(() => { - if (typeof stableDotLottieRefCallback === 'function') { - stableDotLottieRefCallback(dotLottie); - } - }, [stableDotLottieRefCallback, dotLottie]); - - return ; +export const DotLottieWorkerReact = (props: DotLottieWorkerReactProps): JSX.Element => { + return ; }; diff --git a/packages/react/src/dotlottie.tsx b/packages/react/src/dotlottie.tsx index 0461e156..0fe0fe15 100644 --- a/packages/react/src/dotlottie.tsx +++ b/packages/react/src/dotlottie.tsx @@ -1,65 +1,16 @@ 'use client'; -import type { DotLottie, Config } from '@lottiefiles/dotlottie-web'; -import { useEffect, type ComponentProps, type RefCallback, type JSX } from 'react'; +import type { Config } from '@lottiefiles/dotlottie-web'; +import { DotLottie } from '@lottiefiles/dotlottie-web'; +import type { JSX } from 'react'; -import { useDotLottie } from './use-dotlottie'; -import useStableCallback from './use-stable-callback'; +import type { BaseDotLottieProps } from './base-dotlottie-react'; +import { BaseDotLottieReact } from './base-dotlottie-react'; -export type DotLottieReactProps = Omit & - ComponentProps<'canvas'> & { - animationId?: string; - dotLottieRefCallback?: RefCallback; - playOnHover?: boolean; - themeData?: string; - themeId?: string; - }; +export type DotLottieReactProps = Omit, 'createDotLottie'>; -export const DotLottieReact = ({ - animationId, - autoplay, - backgroundColor, - data, - dotLottieRefCallback, - loop, - marker, - mode, - playOnHover, - renderConfig, - segment, - speed, - src, - themeData, - themeId, - useFrameInterpolation, - ...props -}: DotLottieReactProps): JSX.Element => { - const { DotLottieComponent, dotLottie } = useDotLottie({ - data, - mode, - speed, - src, - autoplay, - loop, - segment, - renderConfig, - backgroundColor, - useFrameInterpolation, - playOnHover, - marker, - themeId, - animationId, - themeData, - }); +const createDotLottie = (config: Config): DotLottie => new DotLottie(config); - const stableDotLottieRefCallback = - typeof dotLottieRefCallback === 'function' ? useStableCallback(dotLottieRefCallback) : undefined; - - useEffect(() => { - if (typeof stableDotLottieRefCallback === 'function') { - stableDotLottieRefCallback(dotLottie); - } - }, [stableDotLottieRefCallback, dotLottie]); - - return ; +export const DotLottieReact = (props: DotLottieReactProps): JSX.Element => { + return ; }; diff --git a/packages/react/src/index.ts b/packages/react/src/index.ts index 33c50fb4..34e355d0 100644 --- a/packages/react/src/index.ts +++ b/packages/react/src/index.ts @@ -1,9 +1,9 @@ +'use client'; + import { DotLottie, DotLottieWorker } from '@lottiefiles/dotlottie-web'; export * from './dotlottie'; export type * from '@lottiefiles/dotlottie-web'; -export * from './use-dotlottie'; -export * from './use-dotlottie-worker'; export * from './dotlottie-worker'; export const setWasmUrl = (url: string): void => { diff --git a/packages/react/src/use-dotlottie-worker.tsx b/packages/react/src/use-dotlottie-worker.tsx deleted file mode 100644 index 4fa200cb..00000000 --- a/packages/react/src/use-dotlottie-worker.tsx +++ /dev/null @@ -1,264 +0,0 @@ -import type { Config } from '@lottiefiles/dotlottie-web'; -import { DotLottieWorker } from '@lottiefiles/dotlottie-web'; -import { useCallback, useState, useEffect, useRef, type JSX } from 'react'; -import type { ComponentProps, RefCallback } from 'react'; - -interface DotLottieWorkerComponentProps { - setCanvasRef: RefCallback; - setContainerRef: RefCallback; -} - -function DotLottieWorkerComponent({ - children, - className = '', - setCanvasRef, - setContainerRef, - style, - ...rest -}: DotLottieWorkerComponentProps & ComponentProps<'canvas'>): JSX.Element { - const containerStyle = { - width: '100%', - height: '100%', - lineHeight: 0, - ...style, - }; - - return ( -
- - {children} - -
- ); -} - -export type DotLottieWorkerConfig = Omit & { - animationId?: string; - playOnHover?: boolean; - themeData?: string; - themeId?: string; - workerId?: string; -}; - -export interface UseDotLottieWorkerResult { - DotLottieComponent: (props: ComponentProps<'canvas'>) => JSX.Element; - canvas: HTMLCanvasElement | null; - container: HTMLDivElement | null; - dotLottie: DotLottieWorker | null; - setCanvasRef: RefCallback; - setContainerRef: RefCallback; -} - -export const useDotLottieWorker = (config?: DotLottieWorkerConfig): UseDotLottieWorkerResult => { - const [dotLottie, setDotLottie] = useState(null); - - const dotLottieRef = useRef(null); - const configRef = useRef(config); - - const canvasRef = useRef(null); - const containerRef = useRef(null); - - dotLottieRef.current = dotLottie; - configRef.current = config; - - const hoverHandler = useCallback((event: MouseEvent) => { - if (!configRef.current?.playOnHover || !dotLottieRef.current?.isLoaded) return; - - if (event.type === 'mouseenter') { - dotLottieRef.current.play(); - } else if (event.type === 'mouseleave') { - dotLottieRef.current.pause(); - } - }, []); - - const setCanvasRef = useCallback((canvas: HTMLCanvasElement | null) => { - canvasRef.current = canvas; - }, []); - - const setContainerRef = useCallback((container: HTMLDivElement | null) => { - containerRef.current = container; - }, []); - - const Component = useCallback( - (props: ComponentProps<'canvas'>): JSX.Element => { - return ; - }, - [setCanvasRef, setContainerRef], - ); - - useEffect(() => { - const canvas = canvasRef.current; - - let dotLottieInstance: DotLottieWorker | null = null; - - if (canvas) { - dotLottieInstance = new DotLottieWorker({ - ...configRef.current, - canvas, - }); - - canvas.addEventListener('mouseenter', hoverHandler); - canvas.addEventListener('mouseleave', hoverHandler); - - setDotLottie(dotLottieInstance); - } - - return () => { - dotLottieInstance?.destroy(); - setDotLottie(null); - canvas?.removeEventListener('mouseenter', hoverHandler); - canvas?.removeEventListener('mouseleave', hoverHandler); - }; - }, [hoverHandler]); - - // speed reactivity - useEffect(() => { - if (!dotLottieRef.current) return; - - if (typeof config?.speed === 'number' && config.speed !== dotLottieRef.current.speed) { - dotLottieRef.current.setSpeed(config.speed); - } - }, [config?.speed]); - - // mode reactivity - useEffect(() => { - if (!dotLottieRef.current) return; - - if (typeof config?.mode === 'string' && config.mode !== dotLottieRef.current.mode) { - dotLottieRef.current.setMode(config.mode); - } - }, [config?.mode]); - - // loop reactivity - useEffect(() => { - if (!dotLottieRef.current) return; - - if (typeof config?.loop === 'boolean' && config.loop !== dotLottieRef.current.loop) { - dotLottieRef.current.setLoop(config.loop); - } - }, [config?.loop]); - - // useFrameInterpolation reactivity - useEffect(() => { - if (!dotLottieRef.current) return; - - if ( - typeof config?.useFrameInterpolation === 'boolean' && - config.useFrameInterpolation !== dotLottieRef.current.useFrameInterpolation - ) { - dotLottieRef.current.setUseFrameInterpolation(config.useFrameInterpolation); - } - }, [config?.useFrameInterpolation]); - - // segment reactivity - useEffect(() => { - if (!dotLottieRef.current) return; - - const startFrame = config?.segment?.[0]; - const endFrame = config?.segment?.[1]; - - if (typeof startFrame === 'number' && typeof endFrame === 'number') { - dotLottieRef.current.setSegment(startFrame, endFrame); - } - }, [config?.segment]); - - // background color reactivity - useEffect(() => { - if (!dotLottieRef.current) return; - - if ( - typeof config?.backgroundColor === 'string' && - config.backgroundColor !== dotLottieRef.current.backgroundColor - ) { - dotLottieRef.current.setBackgroundColor(config.backgroundColor); - } - }, [config?.backgroundColor]); - - // render config reactivity - useEffect(() => { - if (!dotLottieRef.current) return; - - if (typeof config?.renderConfig === 'object') { - dotLottieRef.current.setRenderConfig(config.renderConfig); - } - }, [JSON.stringify(config?.renderConfig)]); - - // data reactivity - useEffect(() => { - if (!dotLottieRef.current) return; - - if (typeof config?.data === 'string' || config?.data instanceof ArrayBuffer) { - dotLottieRef.current.load({ - data: config.data, - ...(configRef.current || {}), - }); - } - }, [config?.data]); - - // src reactivity - useEffect(() => { - if (!dotLottieRef.current) return; - - if (typeof config?.src === 'string') { - dotLottieRef.current.load({ - src: config.src, - ...(configRef.current || {}), - }); - } - }, [config?.src]); - - useEffect(() => { - if (!dotLottieRef.current) return; - - if (typeof config?.marker === 'string') { - dotLottieRef.current.setMarker(config.marker); - } - }, [config?.marker]); - - // animationId reactivity - useEffect(() => { - if (!dotLottieRef.current) return; - - if ( - dotLottieRef.current.isLoaded && - config?.animationId && - dotLottieRef.current.activeAnimationId !== config.animationId - ) { - dotLottieRef.current.loadAnimation(config.animationId); - } - }, [config?.animationId]); - - // themeId reactivity - useEffect(() => { - if (!dotLottieRef.current) return; - - if (dotLottieRef.current.isLoaded && dotLottieRef.current.activeThemeId !== config?.themeId) { - dotLottieRef.current.setTheme(config?.themeId || ''); - } - }, [config?.themeId]); - - // themeData reactivity - useEffect(() => { - if (!dotLottieRef.current) return; - - if (dotLottieRef.current.isLoaded) { - dotLottieRef.current.setThemeData(config?.themeData || ''); - } - }, [config?.themeData]); - - return { - dotLottie, - setCanvasRef, - setContainerRef, - canvas: canvasRef.current, - container: containerRef.current, - DotLottieComponent: Component, - }; -}; diff --git a/packages/react/src/use-dotlottie.tsx b/packages/react/src/use-dotlottie.tsx deleted file mode 100644 index 9c3e5f67..00000000 --- a/packages/react/src/use-dotlottie.tsx +++ /dev/null @@ -1,263 +0,0 @@ -import type { Config } from '@lottiefiles/dotlottie-web'; -import { DotLottie } from '@lottiefiles/dotlottie-web'; -import { useCallback, useState, useEffect, useRef, type JSX } from 'react'; -import type { ComponentProps, RefCallback } from 'react'; - -interface DotLottieComponentProps { - setCanvasRef: RefCallback; - setContainerRef: RefCallback; -} - -function DotLottieComponent({ - children, - className = '', - setCanvasRef, - setContainerRef, - style, - ...rest -}: DotLottieComponentProps & ComponentProps<'canvas'>): JSX.Element { - const containerStyle = { - width: '100%', - height: '100%', - lineHeight: 0, - ...style, - }; - - return ( -
- - {children} - -
- ); -} - -export type DotLottieConfig = Omit & { - animationId?: string; - playOnHover?: boolean; - themeData?: string; - themeId?: string; -}; - -export interface UseDotLottieResult { - DotLottieComponent: (props: ComponentProps<'canvas'>) => JSX.Element; - canvas: HTMLCanvasElement | null; - container: HTMLDivElement | null; - dotLottie: DotLottie | null; - setCanvasRef: RefCallback; - setContainerRef: RefCallback; -} - -export const useDotLottie = (config?: DotLottieConfig): UseDotLottieResult => { - const [dotLottie, setDotLottie] = useState(null); - - const dotLottieRef = useRef(null); - const configRef = useRef(config); - - const canvasRef = useRef(null); - const containerRef = useRef(null); - - dotLottieRef.current = dotLottie; - configRef.current = config; - - const hoverHandler = useCallback((event: MouseEvent) => { - if (!configRef.current?.playOnHover || !dotLottieRef.current?.isLoaded) return; - - if (event.type === 'mouseenter') { - dotLottieRef.current.play(); - } else if (event.type === 'mouseleave') { - dotLottieRef.current.pause(); - } - }, []); - - const setCanvasRef = useCallback((canvas: HTMLCanvasElement | null) => { - canvasRef.current = canvas; - }, []); - - const setContainerRef = useCallback((container: HTMLDivElement | null) => { - containerRef.current = container; - }, []); - - const Component = useCallback( - (props: ComponentProps<'canvas'>): JSX.Element => { - return ; - }, - [setCanvasRef, setContainerRef], - ); - - useEffect(() => { - const canvas = canvasRef.current; - - let dotLottieInstance: DotLottie | null = null; - - if (canvas) { - dotLottieInstance = new DotLottie({ - ...configRef.current, - canvas, - }); - - canvas.addEventListener('mouseenter', hoverHandler); - canvas.addEventListener('mouseleave', hoverHandler); - - setDotLottie(dotLottieInstance); - } - - return () => { - dotLottieInstance?.destroy(); - setDotLottie(null); - canvas?.removeEventListener('mouseenter', hoverHandler); - canvas?.removeEventListener('mouseleave', hoverHandler); - }; - }, [hoverHandler]); - - // speed reactivity - useEffect(() => { - if (!dotLottieRef.current) return; - - if (typeof config?.speed === 'number' && config.speed !== dotLottieRef.current.speed) { - dotLottieRef.current.setSpeed(config.speed); - } - }, [config?.speed]); - - // mode reactivity - useEffect(() => { - if (!dotLottieRef.current) return; - - if (typeof config?.mode === 'string' && config.mode !== dotLottieRef.current.mode) { - dotLottieRef.current.setMode(config.mode); - } - }, [config?.mode]); - - // loop reactivity - useEffect(() => { - if (!dotLottieRef.current) return; - - if (typeof config?.loop === 'boolean' && config.loop !== dotLottieRef.current.loop) { - dotLottieRef.current.setLoop(config.loop); - } - }, [config?.loop]); - - // useFrameInterpolation reactivity - useEffect(() => { - if (!dotLottieRef.current) return; - - if ( - typeof config?.useFrameInterpolation === 'boolean' && - config.useFrameInterpolation !== dotLottieRef.current.useFrameInterpolation - ) { - dotLottieRef.current.setUseFrameInterpolation(config.useFrameInterpolation); - } - }, [config?.useFrameInterpolation]); - - // segment reactivity - useEffect(() => { - if (!dotLottieRef.current) return; - - const startFrame = config?.segment?.[0]; - const endFrame = config?.segment?.[1]; - - if (typeof startFrame === 'number' && typeof endFrame === 'number') { - dotLottieRef.current.setSegment(startFrame, endFrame); - } - }, [config?.segment]); - - // background color reactivity - useEffect(() => { - if (!dotLottieRef.current) return; - - if ( - typeof config?.backgroundColor === 'string' && - config.backgroundColor !== dotLottieRef.current.backgroundColor - ) { - dotLottieRef.current.setBackgroundColor(config.backgroundColor); - } - }, [config?.backgroundColor]); - - // render config reactivity - useEffect(() => { - if (!dotLottieRef.current) return; - - if (typeof config?.renderConfig === 'object') { - dotLottieRef.current.setRenderConfig(config.renderConfig); - } - }, [JSON.stringify(config?.renderConfig)]); - - // data reactivity - useEffect(() => { - if (!dotLottieRef.current) return; - - if (typeof config?.data === 'string' || config?.data instanceof ArrayBuffer) { - dotLottieRef.current.load({ - data: config.data, - ...(configRef.current || {}), - }); - } - }, [config?.data]); - - // src reactivity - useEffect(() => { - if (!dotLottieRef.current) return; - - if (typeof config?.src === 'string') { - dotLottieRef.current.load({ - src: config.src, - ...(configRef.current || {}), - }); - } - }, [config?.src]); - - useEffect(() => { - if (!dotLottieRef.current) return; - - if (typeof config?.marker === 'string') { - dotLottieRef.current.setMarker(config.marker); - } - }, [config?.marker]); - - // animationId reactivity - useEffect(() => { - if (!dotLottieRef.current) return; - - if ( - dotLottieRef.current.isLoaded && - config?.animationId && - dotLottieRef.current.activeAnimationId !== config.animationId - ) { - dotLottieRef.current.loadAnimation(config.animationId); - } - }, [config?.animationId]); - - // themeId reactivity - useEffect(() => { - if (!dotLottieRef.current) return; - - if (dotLottieRef.current.isLoaded && dotLottieRef.current.activeThemeId !== config?.themeId) { - dotLottieRef.current.setTheme(config?.themeId || ''); - } - }, [config?.themeId]); - - // themeData reactivity - useEffect(() => { - if (!dotLottieRef.current) return; - - if (dotLottieRef.current.isLoaded) { - dotLottieRef.current.setThemeData(config?.themeData || ''); - } - }, [config?.themeData]); - - return { - dotLottie, - setCanvasRef, - setContainerRef, - canvas: canvasRef.current, - container: containerRef.current, - DotLottieComponent: Component, - }; -}; diff --git a/packages/react/src/use-stable-callback.tsx b/packages/react/src/use-stable-callback.tsx deleted file mode 100644 index b10ba5b4..00000000 --- a/packages/react/src/use-stable-callback.tsx +++ /dev/null @@ -1,20 +0,0 @@ -import { useCallback, useLayoutEffect, useRef, useEffect } from 'react'; - -// eslint-disable-next-line no-negated-condition -const useIsomorphicLayoutEffect = typeof window !== 'undefined' ? useLayoutEffect : useEffect; - -/** - * Returns a memoized version of your function that maintains a stable reference, but - * also can read the latest scope (props and state) of the component in which it is used. - */ -export default function useStableCallback( - callback: (...args: Args) => T, -): (...args: Args) => T { - const callbackContainer = useRef(callback); - - useIsomorphicLayoutEffect(() => { - callbackContainer.current = callback; - }); - - return useCallback((...args: Args) => callbackContainer.current(...args), [callbackContainer]); -} diff --git a/packages/react/tests/__fixtures__/test.json b/packages/react/tests/__fixtures__/test.json new file mode 100644 index 00000000..0a689cad --- /dev/null +++ b/packages/react/tests/__fixtures__/test.json @@ -0,0 +1,3263 @@ +{ + "v": "5.7.0", + "ip": 0, + "op": 42, + "fr": 30, + "w": 1500, + "h": 1500, + "nm": "B", + "assets": [], + "markers": [ + { + "cm": "Marker_1", + "tm": 0, + "dr": 10 + }, + { + "cm": "Marker_2", + "tm": 10, + "dr": 10 + }, + { + "cm": "Marker_3", + "tm": 20, + "dr": 10 + }, + { + "cm": "Marker_4", + "tm": 30, + "dr": 12 + } + ], + "layers": [ + { + "ind": 1, + "ty": 4, + "nm": "R", + "sr": 1, + "ks": { + "o": { + "a": 1, + "k": [ + { + "i": { + "x": 0.515, + "y": 0.955 + }, + "o": { + "x": 0.455, + "y": 0.03 + }, + "t": 0, + "s": [ + 100 + ] + }, + { + "i": { + "x": 0.515, + "y": 0.955 + }, + "o": { + "x": 0.455, + "y": 0.03 + }, + "t": 6, + "s": [ + 100 + ] + }, + { + "i": { + "x": 0.515, + "y": 0.955 + }, + "o": { + "x": 0.455, + "y": 0.03 + }, + "t": 12, + "s": [ + 100 + ] + }, + { + "i": { + "x": 0.515, + "y": 0.955 + }, + "o": { + "x": 0.455, + "y": 0.03 + }, + "t": 18, + "s": [ + 100 + ] + }, + { + "i": { + "x": 0.515, + "y": 0.955 + }, + "o": { + "x": 0.455, + "y": 0.03 + }, + "t": 24, + "s": [ + 100 + ] + }, + { + "i": { + "x": 0.515, + "y": 0.955 + }, + "o": { + "x": 0.455, + "y": 0.03 + }, + "t": 30, + "s": [ + 100 + ] + }, + { + "i": { + "x": 0.515, + "y": 0.955 + }, + "o": { + "x": 0.455, + "y": 0.03 + }, + "t": 36, + "s": [ + 100 + ] + }, + { + "t": 42, + "s": [ + 100 + ] + } + ] + }, + "r": { + "a": 1, + "k": [ + { + "i": { + "x": 0.515, + "y": 0.955 + }, + "o": { + "x": 0.455, + "y": 0.03 + }, + "t": 0, + "s": [ + 0 + ] + }, + { + "i": { + "x": 0.515, + "y": 0.955 + }, + "o": { + "x": 0.455, + "y": 0.03 + }, + "t": 6, + "s": [ + 0 + ] + }, + { + "i": { + "x": 0.515, + "y": 0.955 + }, + "o": { + "x": 0.455, + "y": 0.03 + }, + "t": 12, + "s": [ + 0 + ] + }, + { + "i": { + "x": 0.515, + "y": 0.955 + }, + "o": { + "x": 0.455, + "y": 0.03 + }, + "t": 18, + "s": [ + 0 + ] + }, + { + "i": { + "x": 0.515, + "y": 0.955 + }, + "o": { + "x": 0.455, + "y": 0.03 + }, + "t": 24, + "s": [ + 0 + ] + }, + { + "i": { + "x": 0.515, + "y": 0.955 + }, + "o": { + "x": 0.455, + "y": 0.03 + }, + "t": 30, + "s": [ + 0 + ] + }, + { + "i": { + "x": 0.515, + "y": 0.955 + }, + "o": { + "x": 0.455, + "y": 0.03 + }, + "t": 36, + "s": [ + 0 + ] + }, + { + "t": 42, + "s": [ + 0 + ] + } + ] + }, + "p": { + "k": [ + { + "i": { + "x": 0.515, + "y": 0.955 + }, + "o": { + "x": 0.455, + "y": 0.03 + }, + "t": 0, + "s": [ + 750, + 953 + ] + }, + { + "i": { + "x": 0.515, + "y": 0.955 + }, + "o": { + "x": 0.455, + "y": 0.03 + }, + "t": 6, + "s": [ + 753, + 1057 + ] + }, + { + "i": { + "x": 0.515, + "y": 0.955 + }, + "o": { + "x": 0.455, + "y": 0.03 + }, + "t": 12, + "s": [ + 757, + 877 + ] + }, + { + "i": { + "x": 0.515, + "y": 0.955 + }, + "o": { + "x": 0.455, + "y": 0.03 + }, + "t": 18, + "s": [ + 757, + 1013 + ] + }, + { + "i": { + "x": 0.515, + "y": 0.955 + }, + "o": { + "x": 0.455, + "y": 0.03 + }, + "t": 24, + "s": [ + 743, + 913 + ] + }, + { + "i": { + "x": 0.515, + "y": 0.955 + }, + "o": { + "x": 0.455, + "y": 0.03 + }, + "t": 30, + "s": [ + 750, + 985 + ] + }, + { + "i": { + "x": 0.515, + "y": 0.955 + }, + "o": { + "x": 0.455, + "y": 0.03 + }, + "t": 36, + "s": [ + 750, + 945 + ] + }, + { + "t": 42, + "s": [ + 750, + 953 + ] + } + ], + "a": 1 + }, + "a": { + "k": [ + { + "i": { + "x": 0.515, + "y": 0.955 + }, + "o": { + "x": 0.455, + "y": 0.03 + }, + "t": 0, + "s": [ + 190, + 169 + ] + }, + { + "i": { + "x": 0.515, + "y": 0.955 + }, + "o": { + "x": 0.455, + "y": 0.03 + }, + "t": 6, + "s": [ + 333, + 65 + ] + }, + { + "i": { + "x": 0.515, + "y": 0.955 + }, + "o": { + "x": 0.455, + "y": 0.03 + }, + "t": 12, + "s": [ + 117, + 245 + ] + }, + { + "i": { + "x": 0.515, + "y": 0.955 + }, + "o": { + "x": 0.455, + "y": 0.03 + }, + "t": 18, + "s": [ + 243, + 109 + ] + }, + { + "i": { + "x": 0.515, + "y": 0.955 + }, + "o": { + "x": 0.455, + "y": 0.03 + }, + "t": 24, + "s": [ + 155, + 209 + ] + }, + { + "i": { + "x": 0.515, + "y": 0.955 + }, + "o": { + "x": 0.455, + "y": 0.03 + }, + "t": 30, + "s": [ + 190, + 137 + ] + }, + { + "i": { + "x": 0.515, + "y": 0.955 + }, + "o": { + "x": 0.455, + "y": 0.03 + }, + "t": 36, + "s": [ + 190, + 177 + ] + }, + { + "t": 42, + "s": [ + 190, + 169 + ] + } + ], + "a": 1 + }, + "s": { + "k": [ + { + "i": { + "x": 0.515, + "y": 0.955 + }, + "o": { + "x": 0.455, + "y": 0.03 + }, + "t": 0, + "s": [ + 100, + 100 + ] + }, + { + "i": { + "x": 0.515, + "y": 0.955 + }, + "o": { + "x": 0.455, + "y": 0.03 + }, + "t": 6, + "s": [ + 100, + 100 + ] + }, + { + "i": { + "x": 0.515, + "y": 0.955 + }, + "o": { + "x": 0.455, + "y": 0.03 + }, + "t": 12, + "s": [ + 100, + 100 + ] + }, + { + "i": { + "x": 0.515, + "y": 0.955 + }, + "o": { + "x": 0.455, + "y": 0.03 + }, + "t": 18, + "s": [ + 100, + 100 + ] + }, + { + "i": { + "x": 0.515, + "y": 0.955 + }, + "o": { + "x": 0.455, + "y": 0.03 + }, + "t": 24, + "s": [ + 100, + 100 + ] + }, + { + "i": { + "x": 0.515, + "y": 0.955 + }, + "o": { + "x": 0.455, + "y": 0.03 + }, + "t": 30, + "s": [ + 100, + 100 + ] + }, + { + "i": { + "x": 0.515, + "y": 0.955 + }, + "o": { + "x": 0.455, + "y": 0.03 + }, + "t": 36, + "s": [ + 100, + 100 + ] + }, + { + "t": 42, + "s": [ + 100, + 100 + ] + } + ], + "a": 1 + }, + "sk": { + "a": 0, + "k": 0 + }, + "sa": { + "a": 0, + "k": 0 + } + }, + "shapes": [ + { + "ty": "sh", + "nm": "", + "bm": 0, + "d": 1, + "ks": { + "k": [ + { + "i": { + "x": 0.515, + "y": 0.955 + }, + "o": { + "x": 0.455, + "y": 0.03 + }, + "t": 0, + "s": [ + { + "i": [ + [ + 0, + 0 + ], + [ + -44.15, + 0 + ], + [ + 0, + 0 + ], + [ + 0, + -44.15 + ], + [ + 0, + 0 + ], + [ + 44.15, + 0 + ], + [ + 0, + 0 + ], + [ + 0, + 44.15 + ] + ], + "o": [ + [ + 0, + -44.15 + ], + [ + 0, + 0 + ], + [ + 44.15, + 0 + ], + [ + 0, + 0 + ], + [ + 0, + 44.15 + ], + [ + 0, + 0 + ], + [ + -44.15, + 0 + ], + [ + 0, + 0 + ] + ], + "v": [ + [ + 0, + 80 + ], + [ + 80, + 0 + ], + [ + 300, + 0 + ], + [ + 380, + 80 + ], + [ + 380, + 258 + ], + [ + 300, + 338 + ], + [ + 80, + 338 + ], + [ + 0, + 258 + ] + ], + "c": true + } + ] + }, + { + "i": { + "x": 0.515, + "y": 0.955 + }, + "o": { + "x": 0.455, + "y": 0.03 + }, + "t": 6, + "s": [ + { + "i": [ + [ + 0, + 0 + ], + [ + -35.87, + 0 + ], + [ + 0, + 0 + ], + [ + 0, + -35.87 + ], + [ + 0, + 0 + ], + [ + 35.87, + 0 + ], + [ + 0, + 0 + ], + [ + 0, + 35.87 + ] + ], + "o": [ + [ + 0, + -35.87 + ], + [ + 0, + 0 + ], + [ + 35.87, + 0 + ], + [ + 0, + 0 + ], + [ + 0, + 35.87 + ], + [ + 0, + 0 + ], + [ + -35.87, + 0 + ], + [ + 0, + 0 + ] + ], + "v": [ + [ + 0, + 65 + ], + [ + 65, + 0 + ], + [ + 601, + 0 + ], + [ + 666, + 65 + ], + [ + 666, + 65 + ], + [ + 601, + 130 + ], + [ + 65, + 130 + ], + [ + 0, + 65 + ] + ], + "c": true + } + ] + }, + { + "i": { + "x": 0.515, + "y": 0.955 + }, + "o": { + "x": 0.455, + "y": 0.03 + }, + "t": 12, + "s": [ + { + "i": [ + [ + 0, + 0 + ], + [ + -44.15, + 0 + ], + [ + 0, + 0 + ], + [ + 0, + -44.15 + ], + [ + 0, + 0 + ], + [ + 44.15, + 0 + ], + [ + 0, + 0 + ], + [ + 0, + 44.15 + ] + ], + "o": [ + [ + 0, + -44.15 + ], + [ + 0, + 0 + ], + [ + 44.15, + 0 + ], + [ + 0, + 0 + ], + [ + 0, + 44.15 + ], + [ + 0, + 0 + ], + [ + -44.15, + 0 + ], + [ + 0, + 0 + ] + ], + "v": [ + [ + 0, + 80 + ], + [ + 80, + 0 + ], + [ + 154, + 0 + ], + [ + 234, + 80 + ], + [ + 234, + 410 + ], + [ + 154, + 490 + ], + [ + 80, + 490 + ], + [ + 0, + 410 + ] + ], + "c": true + } + ] + }, + { + "i": { + "x": 0.515, + "y": 0.955 + }, + "o": { + "x": 0.455, + "y": 0.03 + }, + "t": 18, + "s": [ + { + "i": [ + [ + 0, + 0 + ], + [ + -44.15, + 0 + ], + [ + 0, + 0 + ], + [ + 0, + -44.15 + ], + [ + 0, + 0 + ], + [ + 44.15, + 0 + ], + [ + 0, + 0 + ], + [ + 0, + 44.15 + ] + ], + "o": [ + [ + 0, + -44.15 + ], + [ + 0, + 0 + ], + [ + 44.15, + 0 + ], + [ + 0, + 0 + ], + [ + 0, + 44.15 + ], + [ + 0, + 0 + ], + [ + -44.15, + 0 + ], + [ + 0, + 0 + ] + ], + "v": [ + [ + 0, + 80 + ], + [ + 80, + 0 + ], + [ + 406, + 0 + ], + [ + 486, + 80 + ], + [ + 486, + 138 + ], + [ + 406, + 218 + ], + [ + 80, + 218 + ], + [ + 0, + 138 + ] + ], + "c": true + } + ] + }, + { + "i": { + "x": 0.515, + "y": 0.955 + }, + "o": { + "x": 0.455, + "y": 0.03 + }, + "t": 24, + "s": [ + { + "i": [ + [ + 0, + 0 + ], + [ + -44.15, + 0 + ], + [ + 0, + 0 + ], + [ + 0, + -44.15 + ], + [ + 0, + 0 + ], + [ + 44.15, + 0 + ], + [ + 0, + 0 + ], + [ + 0, + 44.15 + ] + ], + "o": [ + [ + 0, + -44.15 + ], + [ + 0, + 0 + ], + [ + 44.15, + 0 + ], + [ + 0, + 0 + ], + [ + 0, + 44.15 + ], + [ + 0, + 0 + ], + [ + -44.15, + 0 + ], + [ + 0, + 0 + ] + ], + "v": [ + [ + 0, + 80 + ], + [ + 80, + 0 + ], + [ + 230, + 0 + ], + [ + 310, + 80 + ], + [ + 310, + 338 + ], + [ + 230, + 418 + ], + [ + 80, + 418 + ], + [ + 0, + 338 + ] + ], + "c": true + } + ] + }, + { + "i": { + "x": 0.515, + "y": 0.955 + }, + "o": { + "x": 0.455, + "y": 0.03 + }, + "t": 30, + "s": [ + { + "i": [ + [ + 0, + 0 + ], + [ + -44.15, + 0 + ], + [ + 0, + 0 + ], + [ + 0, + -44.15 + ], + [ + 0, + 0 + ], + [ + 44.15, + 0 + ], + [ + 0, + 0 + ], + [ + 0, + 44.15 + ] + ], + "o": [ + [ + 0, + -44.15 + ], + [ + 0, + 0 + ], + [ + 44.15, + 0 + ], + [ + 0, + 0 + ], + [ + 0, + 44.15 + ], + [ + 0, + 0 + ], + [ + -44.15, + 0 + ], + [ + 0, + 0 + ] + ], + "v": [ + [ + 0, + 80 + ], + [ + 80, + 0 + ], + [ + 300, + 0 + ], + [ + 380, + 80 + ], + [ + 380, + 194 + ], + [ + 300, + 274 + ], + [ + 80, + 274 + ], + [ + 0, + 194 + ] + ], + "c": true + } + ] + }, + { + "i": { + "x": 0.515, + "y": 0.955 + }, + "o": { + "x": 0.455, + "y": 0.03 + }, + "t": 36, + "s": [ + { + "i": [ + [ + 0, + 0 + ], + [ + -44.15, + 0 + ], + [ + 0, + 0 + ], + [ + 0, + -44.15 + ], + [ + 0, + 0 + ], + [ + 44.15, + 0 + ], + [ + 0, + 0 + ], + [ + 0, + 44.15 + ] + ], + "o": [ + [ + 0, + -44.15 + ], + [ + 0, + 0 + ], + [ + 44.15, + 0 + ], + [ + 0, + 0 + ], + [ + 0, + 44.15 + ], + [ + 0, + 0 + ], + [ + -44.15, + 0 + ], + [ + 0, + 0 + ] + ], + "v": [ + [ + 0, + 80 + ], + [ + 80, + 0 + ], + [ + 300, + 0 + ], + [ + 380, + 80 + ], + [ + 380, + 274 + ], + [ + 300, + 354 + ], + [ + 80, + 354 + ], + [ + 0, + 274 + ] + ], + "c": true + } + ] + }, + { + "t": 42, + "s": [ + { + "i": [ + [ + 0, + 0 + ], + [ + -44.15, + 0 + ], + [ + 0, + 0 + ], + [ + 0, + -44.15 + ], + [ + 0, + 0 + ], + [ + 44.15, + 0 + ], + [ + 0, + 0 + ], + [ + 0, + 44.15 + ] + ], + "o": [ + [ + 0, + -44.15 + ], + [ + 0, + 0 + ], + [ + 44.15, + 0 + ], + [ + 0, + 0 + ], + [ + 0, + 44.15 + ], + [ + 0, + 0 + ], + [ + -44.15, + 0 + ], + [ + 0, + 0 + ] + ], + "v": [ + [ + 0, + 80 + ], + [ + 80, + 0 + ], + [ + 300, + 0 + ], + [ + 380, + 80 + ], + [ + 380, + 258 + ], + [ + 300, + 338 + ], + [ + 80, + 338 + ], + [ + 0, + 258 + ] + ], + "c": true + } + ] + } + ], + "a": 1 + } + }, + { + "ty": "fl", + "nm": "", + "bm": 0, + "c": { + "sid": "c1", + "a": 1, + "k": [ + { + "i": { + "x": 0.515, + "y": 0.955 + }, + "o": { + "x": 0.455, + "y": 0.03 + }, + "t": 0, + "s": [ + 0.271, + 0.271, + 0.271 + ] + }, + { + "i": { + "x": 0.515, + "y": 0.955 + }, + "o": { + "x": 0.455, + "y": 0.03 + }, + "t": 6, + "s": [ + 0.271, + 0.271, + 0.271 + ] + }, + { + "i": { + "x": 0.515, + "y": 0.955 + }, + "o": { + "x": 0.455, + "y": 0.03 + }, + "t": 12, + "s": [ + 0.271, + 0.271, + 0.271 + ] + }, + { + "i": { + "x": 0.515, + "y": 0.955 + }, + "o": { + "x": 0.455, + "y": 0.03 + }, + "t": 18, + "s": [ + 0.271, + 0.271, + 0.271 + ] + }, + { + "i": { + "x": 0.515, + "y": 0.955 + }, + "o": { + "x": 0.455, + "y": 0.03 + }, + "t": 24, + "s": [ + 0.271, + 0.271, + 0.271 + ] + }, + { + "i": { + "x": 0.515, + "y": 0.955 + }, + "o": { + "x": 0.455, + "y": 0.03 + }, + "t": 30, + "s": [ + 0.271, + 0.271, + 0.271 + ] + }, + { + "i": { + "x": 0.515, + "y": 0.955 + }, + "o": { + "x": 0.455, + "y": 0.03 + }, + "t": 36, + "s": [ + 0.271, + 0.271, + 0.271 + ] + }, + { + "t": 42, + "s": [ + 0.271, + 0.271, + 0.271 + ] + } + ] + }, + "o": { + "a": 1, + "k": [ + { + "i": { + "x": 0.515, + "y": 0.955 + }, + "o": { + "x": 0.455, + "y": 0.03 + }, + "t": 0, + "s": [ + 100 + ] + }, + { + "i": { + "x": 0.515, + "y": 0.955 + }, + "o": { + "x": 0.455, + "y": 0.03 + }, + "t": 6, + "s": [ + 100 + ] + }, + { + "i": { + "x": 0.515, + "y": 0.955 + }, + "o": { + "x": 0.455, + "y": 0.03 + }, + "t": 12, + "s": [ + 100 + ] + }, + { + "i": { + "x": 0.515, + "y": 0.955 + }, + "o": { + "x": 0.455, + "y": 0.03 + }, + "t": 18, + "s": [ + 100 + ] + }, + { + "i": { + "x": 0.515, + "y": 0.955 + }, + "o": { + "x": 0.455, + "y": 0.03 + }, + "t": 24, + "s": [ + 100 + ] + }, + { + "i": { + "x": 0.515, + "y": 0.955 + }, + "o": { + "x": 0.455, + "y": 0.03 + }, + "t": 30, + "s": [ + 100 + ] + }, + { + "i": { + "x": 0.515, + "y": 0.955 + }, + "o": { + "x": 0.455, + "y": 0.03 + }, + "t": 36, + "s": [ + 100 + ] + }, + { + "t": 42, + "s": [ + 100 + ] + } + ] + }, + "r": 1 + } + ], + "hasMask": false, + "ip": 0, + "op": 43, + "st": 0, + "hd": false + }, + { + "ind": 2, + "ty": 4, + "nm": "E", + "sr": 1, + "ks": { + "o": { + "a": 1, + "k": [ + { + "i": { + "x": 0.515, + "y": 0.955 + }, + "o": { + "x": 0.455, + "y": 0.03 + }, + "t": 0, + "s": [ + 100 + ] + }, + { + "i": { + "x": 0.515, + "y": 0.955 + }, + "o": { + "x": 0.455, + "y": 0.03 + }, + "t": 6, + "s": [ + 100 + ] + }, + { + "i": { + "x": 0.515, + "y": 0.955 + }, + "o": { + "x": 0.455, + "y": 0.03 + }, + "t": 12, + "s": [ + 100 + ] + }, + { + "i": { + "x": 0.515, + "y": 0.955 + }, + "o": { + "x": 0.455, + "y": 0.03 + }, + "t": 18, + "s": [ + 100 + ] + }, + { + "i": { + "x": 0.515, + "y": 0.955 + }, + "o": { + "x": 0.455, + "y": 0.03 + }, + "t": 24, + "s": [ + 100 + ] + }, + { + "i": { + "x": 0.515, + "y": 0.955 + }, + "o": { + "x": 0.455, + "y": 0.03 + }, + "t": 30, + "s": [ + 100 + ] + }, + { + "i": { + "x": 0.515, + "y": 0.955 + }, + "o": { + "x": 0.455, + "y": 0.03 + }, + "t": 36, + "s": [ + 100 + ] + }, + { + "t": 42, + "s": [ + 100 + ] + } + ] + }, + "r": { + "a": 1, + "k": [ + { + "i": { + "x": 0.515, + "y": 0.955 + }, + "o": { + "x": 0.455, + "y": 0.03 + }, + "t": 0, + "s": [ + 0 + ] + }, + { + "i": { + "x": 0.515, + "y": 0.955 + }, + "o": { + "x": 0.455, + "y": 0.03 + }, + "t": 6, + "s": [ + 0 + ] + }, + { + "i": { + "x": 0.515, + "y": 0.955 + }, + "o": { + "x": 0.455, + "y": 0.03 + }, + "t": 12, + "s": [ + 0 + ] + }, + { + "i": { + "x": 0.515, + "y": 0.955 + }, + "o": { + "x": 0.455, + "y": 0.03 + }, + "t": 18, + "s": [ + 0 + ] + }, + { + "i": { + "x": 0.515, + "y": 0.955 + }, + "o": { + "x": 0.455, + "y": 0.03 + }, + "t": 24, + "s": [ + 0 + ] + }, + { + "i": { + "x": 0.515, + "y": 0.955 + }, + "o": { + "x": 0.455, + "y": 0.03 + }, + "t": 30, + "s": [ + 0 + ] + }, + { + "i": { + "x": 0.515, + "y": 0.955 + }, + "o": { + "x": 0.455, + "y": 0.03 + }, + "t": 36, + "s": [ + 0 + ] + }, + { + "t": 42, + "s": [ + 0 + ] + } + ] + }, + "p": { + "k": [ + { + "i": { + "x": 0.515, + "y": 0.955 + }, + "o": { + "x": 0.455, + "y": 0.03 + }, + "t": 0, + "s": [ + 750, + 594 + ] + }, + { + "i": { + "x": 0.515, + "y": 0.955 + }, + "o": { + "x": 0.455, + "y": 0.03 + }, + "t": 6, + "s": [ + 750, + 802 + ] + }, + { + "i": { + "x": 0.515, + "y": 0.955 + }, + "o": { + "x": 0.455, + "y": 0.03 + }, + "t": 12, + "s": [ + 750, + 226 + ] + }, + { + "i": { + "x": 0.515, + "y": 0.955 + }, + "o": { + "x": 0.455, + "y": 0.03 + }, + "t": 18, + "s": [ + 750, + 664 + ] + }, + { + "i": { + "x": 0.515, + "y": 0.955 + }, + "o": { + "x": 0.455, + "y": 0.03 + }, + "t": 24, + "s": [ + 750, + 318 + ] + }, + { + "i": { + "x": 0.515, + "y": 0.955 + }, + "o": { + "x": 0.455, + "y": 0.03 + }, + "t": 30, + "s": [ + 750, + 612 + ] + }, + { + "i": { + "x": 0.515, + "y": 0.955 + }, + "o": { + "x": 0.455, + "y": 0.03 + }, + "t": 36, + "s": [ + 750, + 514 + ] + }, + { + "t": 42, + "s": [ + 750, + 594 + ] + } + ], + "a": 1 + }, + "a": { + "k": [ + { + "i": { + "x": 0.515, + "y": 0.955 + }, + "o": { + "x": 0.455, + "y": 0.03 + }, + "t": 0, + "s": [ + 190, + 190 + ] + }, + { + "i": { + "x": 0.515, + "y": 0.955 + }, + "o": { + "x": 0.455, + "y": 0.03 + }, + "t": 6, + "s": [ + 190, + 190 + ] + }, + { + "i": { + "x": 0.515, + "y": 0.955 + }, + "o": { + "x": 0.455, + "y": 0.03 + }, + "t": 12, + "s": [ + 190, + 190 + ] + }, + { + "i": { + "x": 0.515, + "y": 0.955 + }, + "o": { + "x": 0.455, + "y": 0.03 + }, + "t": 18, + "s": [ + 190, + 190 + ] + }, + { + "i": { + "x": 0.515, + "y": 0.955 + }, + "o": { + "x": 0.455, + "y": 0.03 + }, + "t": 24, + "s": [ + 190, + 190 + ] + }, + { + "i": { + "x": 0.515, + "y": 0.955 + }, + "o": { + "x": 0.455, + "y": 0.03 + }, + "t": 30, + "s": [ + 190, + 190 + ] + }, + { + "i": { + "x": 0.515, + "y": 0.955 + }, + "o": { + "x": 0.455, + "y": 0.03 + }, + "t": 36, + "s": [ + 190, + 190 + ] + }, + { + "t": 42, + "s": [ + 190, + 190 + ] + } + ], + "a": 1 + }, + "s": { + "k": [ + { + "i": { + "x": 0.515, + "y": 0.955 + }, + "o": { + "x": 0.455, + "y": 0.03 + }, + "t": 0, + "s": [ + 100, + 100 + ] + }, + { + "i": { + "x": 0.515, + "y": 0.955 + }, + "o": { + "x": 0.455, + "y": 0.03 + }, + "t": 6, + "s": [ + 100, + 100 + ] + }, + { + "i": { + "x": 0.515, + "y": 0.955 + }, + "o": { + "x": 0.455, + "y": 0.03 + }, + "t": 12, + "s": [ + 100, + 100 + ] + }, + { + "i": { + "x": 0.515, + "y": 0.955 + }, + "o": { + "x": 0.455, + "y": 0.03 + }, + "t": 18, + "s": [ + 100, + 100 + ] + }, + { + "i": { + "x": 0.515, + "y": 0.955 + }, + "o": { + "x": 0.455, + "y": 0.03 + }, + "t": 24, + "s": [ + 100, + 100 + ] + }, + { + "i": { + "x": 0.515, + "y": 0.955 + }, + "o": { + "x": 0.455, + "y": 0.03 + }, + "t": 30, + "s": [ + 100, + 100 + ] + }, + { + "i": { + "x": 0.515, + "y": 0.955 + }, + "o": { + "x": 0.455, + "y": 0.03 + }, + "t": 36, + "s": [ + 100, + 100 + ] + }, + { + "t": 42, + "s": [ + 100, + 100 + ] + } + ], + "a": 1 + }, + "sk": { + "a": 0, + "k": 0 + }, + "sa": { + "a": 0, + "k": 0 + } + }, + "shapes": [ + { + "ty": "sh", + "nm": "", + "bm": 0, + "d": 1, + "ks": { + "k": [ + { + "i": { + "x": 0.515, + "y": 0.955 + }, + "o": { + "x": 0.455, + "y": 0.03 + }, + "t": 0, + "s": [ + { + "i": [ + [ + -104.86, + 0 + ], + [ + 0, + -104.86 + ], + [ + 104.86, + 0 + ], + [ + 0, + 104.86 + ] + ], + "o": [ + [ + 104.86, + 0 + ], + [ + 0, + 104.86 + ], + [ + -104.86, + 0 + ], + [ + 0, + -104.86 + ] + ], + "v": [ + [ + 190, + 0 + ], + [ + 380, + 190 + ], + [ + 190, + 380 + ], + [ + 0, + 190 + ] + ], + "c": true + } + ] + }, + { + "i": { + "x": 0.515, + "y": 0.955 + }, + "o": { + "x": 0.455, + "y": 0.03 + }, + "t": 6, + "s": [ + { + "i": [ + [ + -104.86, + 0 + ], + [ + 0, + -104.86 + ], + [ + 104.86, + 0 + ], + [ + 0, + 104.86 + ] + ], + "o": [ + [ + 104.86, + 0 + ], + [ + 0, + 104.86 + ], + [ + -104.86, + 0 + ], + [ + 0, + -104.86 + ] + ], + "v": [ + [ + 190, + 0 + ], + [ + 380, + 190 + ], + [ + 190, + 380 + ], + [ + 0, + 190 + ] + ], + "c": true + } + ] + }, + { + "i": { + "x": 0.515, + "y": 0.955 + }, + "o": { + "x": 0.455, + "y": 0.03 + }, + "t": 12, + "s": [ + { + "i": [ + [ + -104.86, + 0 + ], + [ + 0, + -104.86 + ], + [ + 104.86, + 0 + ], + [ + 0, + 104.86 + ] + ], + "o": [ + [ + 104.86, + 0 + ], + [ + 0, + 104.86 + ], + [ + -104.86, + 0 + ], + [ + 0, + -104.86 + ] + ], + "v": [ + [ + 190, + 0 + ], + [ + 380, + 190 + ], + [ + 190, + 380 + ], + [ + 0, + 190 + ] + ], + "c": true + } + ] + }, + { + "i": { + "x": 0.515, + "y": 0.955 + }, + "o": { + "x": 0.455, + "y": 0.03 + }, + "t": 18, + "s": [ + { + "i": [ + [ + -104.86, + 0 + ], + [ + 0, + -104.86 + ], + [ + 104.86, + 0 + ], + [ + 0, + 104.86 + ] + ], + "o": [ + [ + 104.86, + 0 + ], + [ + 0, + 104.86 + ], + [ + -104.86, + 0 + ], + [ + 0, + -104.86 + ] + ], + "v": [ + [ + 190, + 0 + ], + [ + 380, + 190 + ], + [ + 190, + 380 + ], + [ + 0, + 190 + ] + ], + "c": true + } + ] + }, + { + "i": { + "x": 0.515, + "y": 0.955 + }, + "o": { + "x": 0.455, + "y": 0.03 + }, + "t": 24, + "s": [ + { + "i": [ + [ + -104.86, + 0 + ], + [ + 0, + -104.86 + ], + [ + 104.86, + 0 + ], + [ + 0, + 104.86 + ] + ], + "o": [ + [ + 104.86, + 0 + ], + [ + 0, + 104.86 + ], + [ + -104.86, + 0 + ], + [ + 0, + -104.86 + ] + ], + "v": [ + [ + 190, + 0 + ], + [ + 380, + 190 + ], + [ + 190, + 380 + ], + [ + 0, + 190 + ] + ], + "c": true + } + ] + }, + { + "i": { + "x": 0.515, + "y": 0.955 + }, + "o": { + "x": 0.455, + "y": 0.03 + }, + "t": 30, + "s": [ + { + "i": [ + [ + -104.86, + 0 + ], + [ + 0, + -104.86 + ], + [ + 104.86, + 0 + ], + [ + 0, + 104.86 + ] + ], + "o": [ + [ + 104.86, + 0 + ], + [ + 0, + 104.86 + ], + [ + -104.86, + 0 + ], + [ + 0, + -104.86 + ] + ], + "v": [ + [ + 190, + 0 + ], + [ + 380, + 190 + ], + [ + 190, + 380 + ], + [ + 0, + 190 + ] + ], + "c": true + } + ] + }, + { + "i": { + "x": 0.515, + "y": 0.955 + }, + "o": { + "x": 0.455, + "y": 0.03 + }, + "t": 36, + "s": [ + { + "i": [ + [ + -104.86, + 0 + ], + [ + 0, + -104.86 + ], + [ + 104.86, + 0 + ], + [ + 0, + 104.86 + ] + ], + "o": [ + [ + 104.86, + 0 + ], + [ + 0, + 104.86 + ], + [ + -104.86, + 0 + ], + [ + 0, + -104.86 + ] + ], + "v": [ + [ + 190, + 0 + ], + [ + 380, + 190 + ], + [ + 190, + 380 + ], + [ + 0, + 190 + ] + ], + "c": true + } + ] + }, + { + "t": 42, + "s": [ + { + "i": [ + [ + -104.86, + 0 + ], + [ + 0, + -104.86 + ], + [ + 104.86, + 0 + ], + [ + 0, + 104.86 + ] + ], + "o": [ + [ + 104.86, + 0 + ], + [ + 0, + 104.86 + ], + [ + -104.86, + 0 + ], + [ + 0, + -104.86 + ] + ], + "v": [ + [ + 190, + 0 + ], + [ + 380, + 190 + ], + [ + 190, + 380 + ], + [ + 0, + 190 + ] + ], + "c": true + } + ] + } + ], + "a": 1 + } + }, + { + "ty": "fl", + "nm": "", + "bm": 0, + "c": { + "sid": "c0", + "a": 1, + "k": [ + { + "i": { + "x": 0.515, + "y": 0.955 + }, + "o": { + "x": 0.455, + "y": 0.03 + }, + "t": 0, + "s": [ + 1, + 0.377, + 0 + ] + }, + { + "i": { + "x": 0.515, + "y": 0.955 + }, + "o": { + "x": 0.455, + "y": 0.03 + }, + "t": 6, + "s": [ + 1, + 0.377, + 0 + ] + }, + { + "i": { + "x": 0.515, + "y": 0.955 + }, + "o": { + "x": 0.455, + "y": 0.03 + }, + "t": 12, + "s": [ + 1, + 0.377, + 0 + ] + }, + { + "i": { + "x": 0.515, + "y": 0.955 + }, + "o": { + "x": 0.455, + "y": 0.03 + }, + "t": 18, + "s": [ + 1, + 0.377, + 0 + ] + }, + { + "i": { + "x": 0.515, + "y": 0.955 + }, + "o": { + "x": 0.455, + "y": 0.03 + }, + "t": 24, + "s": [ + 1, + 0.377, + 0 + ] + }, + { + "i": { + "x": 0.515, + "y": 0.955 + }, + "o": { + "x": 0.455, + "y": 0.03 + }, + "t": 30, + "s": [ + 1, + 0.377, + 0 + ] + }, + { + "i": { + "x": 0.515, + "y": 0.955 + }, + "o": { + "x": 0.455, + "y": 0.03 + }, + "t": 36, + "s": [ + 1, + 0.377, + 0 + ] + }, + { + "t": 42, + "s": [ + 1, + 0.377, + 0 + ] + } + ] + }, + "o": { + "a": 1, + "k": [ + { + "i": { + "x": 0.515, + "y": 0.955 + }, + "o": { + "x": 0.455, + "y": 0.03 + }, + "t": 0, + "s": [ + 100 + ] + }, + { + "i": { + "x": 0.515, + "y": 0.955 + }, + "o": { + "x": 0.455, + "y": 0.03 + }, + "t": 6, + "s": [ + 100 + ] + }, + { + "i": { + "x": 0.515, + "y": 0.955 + }, + "o": { + "x": 0.455, + "y": 0.03 + }, + "t": 12, + "s": [ + 100 + ] + }, + { + "i": { + "x": 0.515, + "y": 0.955 + }, + "o": { + "x": 0.455, + "y": 0.03 + }, + "t": 18, + "s": [ + 100 + ] + }, + { + "i": { + "x": 0.515, + "y": 0.955 + }, + "o": { + "x": 0.455, + "y": 0.03 + }, + "t": 24, + "s": [ + 100 + ] + }, + { + "i": { + "x": 0.515, + "y": 0.955 + }, + "o": { + "x": 0.455, + "y": 0.03 + }, + "t": 30, + "s": [ + 100 + ] + }, + { + "i": { + "x": 0.515, + "y": 0.955 + }, + "o": { + "x": 0.455, + "y": 0.03 + }, + "t": 36, + "s": [ + 100 + ] + }, + { + "t": 42, + "s": [ + 100 + ] + } + ] + }, + "r": 1 + } + ], + "hasMask": false, + "ip": 0, + "op": 43, + "st": 0, + "hd": false + }, + { + "ind": 3, + "ty": 1, + "nm": "B", + "sr": 1, + "ks": { + "o": { + "a": 0, + "k": 100 + }, + "r": { + "a": 0, + "k": 0 + }, + "p": { + "a": 0, + "k": [ + 0, + 0 + ] + }, + "a": { + "a": 0, + "k": [ + 0, + 0 + ] + }, + "s": { + "a": 0, + "k": [ + 100, + 100 + ] + }, + "sk": { + "a": 0, + "k": 0 + }, + "sa": { + "a": 0, + "k": 0 + } + }, + "hasMask": false, + "ip": 0, + "op": 43, + "st": 0, + "hd": false, + "sc": "#ffffff", + "sh": 1500, + "sw": 1500 + } + ] +} \ No newline at end of file diff --git a/packages/react/tests/__fixtures__/test.lottie b/packages/react/tests/__fixtures__/test.lottie new file mode 100644 index 0000000000000000000000000000000000000000..8ea125cad7f4242638048c69c023c76d808915db GIT binary patch literal 1446 zcmWIWW@Zs#U|`^2SRNG@`S7RJolqbz9*B8?I5#mbGcC2aL@%p2KhL(ukgLIfhvEOE z$m~LaH&^OAoR>N(-Et6)@%o>qwte@*bqBjcJGfb9BsK_hUt1D$HaTr?d|%3guNfy=k%x`tPEEMWw%&zxXO?J1us5 zRC&@qi^-4jewJ*mS~R=YLcKXy{l~Jz?Z<3?#WDo07PmB6(bQOX^$<(*|m1RiiS%zeo}xnH;7u;JUap+#xFKc8&B=CL;Cv;gzk+^1V~ zowz1CctpLN^zdjyMz(UgtB0Y^oYTvvDO$(`y`8v8z_YkZxa}Kz$)Q%&m@ht_ch8(U zd{jbtwvhai$Ob(GC$d;T!`s+v;;)d!0-E0DToX412Y!NKvyLV!v`(4rRetx~D{F+ZmWH~;Oj$>U?Y#49< zHzH6iV8^z$IHNM7-1fMlMJhK;Km0o5o&S2m9ut!nds_}W>Pfxd@0MAgJ4?ZzH)Bho zm9*44?f(8p+X@91F3EknZtBXtbELNRt*R2ssbvmdG2@QNwhET3KIpseVd(9=Q=cX<%YC-)`!*wG=fU7hC6&8p zn;fiB-j)5t@6ntNA3M8@psg0Azx~!l(aC$vL0wTl>~cyZds|Jpujc+wW#Y>^FSzSp5&z?CHh@{I01251yt@&`*|3 z;n}v4$7q_P-8P=2iL;HTIBMKp9kEK`1n26urCdyYOEe{8w3--BKIrXV&T;95ko{9v zfz^LsZ0l0UbF*K;!6dfy&jk%OFLrm!ARC*miI*6IdVtwtisIXkKgvW~jwFkwtZ9-- z7JcHfx{7I$@dxF9eKQ`$$Sj#Cc5^xN_l@G3K?++YR7ssFJU`)q-iG*?DW50&vD$Vq z_o{4PUd7?6gByACyPw-{dzkz2v%C2o=bKSwKR^8c5_$h@^5y-%K5ev4(Dd~defEi` zhf(Wkf=q-Vck%(RN(tt$Q%5W|eEVg0{#ez~6VClt6twwyWpg7smVRk&+H14L|KrE4 zlCn4Vb6WIidBz+ym?UT&#D3fRxA}za`;zt)ub7bVTy(zPUHM-9zio@S?N>Lb|7QsB uW@Hj!z+E~53n(OjQdXjCMK9P8`Wk>tq+%|>o0SbD$pnNYKw5?s!~+1HB6Z&Y literal 0 HcmV?d00001 diff --git a/packages/react/tests/__snapshots__/dotlottie-react.spec.tsx.snap b/packages/react/tests/__snapshots__/dotlottie-react.spec.tsx.snap new file mode 100644 index 00000000..314b8f0f --- /dev/null +++ b/packages/react/tests/__snapshots__/dotlottie-react.spec.tsx.snap @@ -0,0 +1,25 @@ +// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html + +exports[`'DotLottieReact' > basic 1`] = ` +
+
+ +
+
+`; + +exports[`'DotLottieWorkerReact' > basic 1`] = ` +
+
+ +
+
+`; diff --git a/packages/react/tests/dotlottie-react.spec.tsx b/packages/react/tests/dotlottie-react.spec.tsx new file mode 100644 index 00000000..65b44c77 --- /dev/null +++ b/packages/react/tests/dotlottie-react.spec.tsx @@ -0,0 +1,688 @@ +import { DotLottie, DotLottieWorker } from '@lottiefiles/dotlottie-web'; +import { userEvent } from '@testing-library/user-event'; +import React from 'react'; +import { afterEach, describe, expect, test, vi } from 'vitest'; +import type { ComponentRenderOptions, RenderResult } from 'vitest-browser-react'; +import { cleanup, render as vitestRender } from 'vitest-browser-react'; + +import { DotLottieReact, DotLottieWorkerReact } from '../src'; + +import lottieBaseSrc from './__fixtures__/test.json?url'; +import baseSrc from './__fixtures__/test.lottie?url'; + +const dotLottieSrc = `http://localhost:5173/${baseSrc}`; +const lottieSrc = `http://localhost:5173/${lottieBaseSrc}`; + +const Wrapper: React.FC<{ children: React.ReactNode }> = ({ children }) => { + return <>{children}; +}; + +const render = (ui: React.ReactNode, options?: ComponentRenderOptions): RenderResult => + vitestRender(ui, { wrapper: Wrapper, ...options }); + +describe.each([ + { component: DotLottieReact, instanceType: DotLottie }, + { component: DotLottieWorkerReact, instanceType: DotLottieWorker }, +])('$component.name', ({ component: Component, instanceType }) => { + afterEach(() => { + cleanup(); + }); + + test('basic', async () => { + const onLoad = vi.fn(); + const onDestroy = vi.fn(); + const onComplete = vi.fn(); + const dotLottieRefCallback = vi.fn(); + + const { container, unmount } = render( + , + ); + + expect(container).toMatchSnapshot(); + + await vi.waitFor(() => { + expect(dotLottieRefCallback).toHaveBeenCalledTimes(1); + }); + + const dotLottie = dotLottieRefCallback.mock.calls[0]?.[0]; + + expect(dotLottie).toBeInstanceOf(instanceType); + + dotLottie?.addEventListener('load', onLoad); + dotLottie?.addEventListener('destroy', onDestroy); + dotLottie?.addEventListener('complete', onComplete); + + await vi.waitFor(() => { + expect(onLoad).toHaveBeenCalledTimes(1); + }); + + await vi.waitFor( + () => { + expect(onComplete).toHaveBeenCalledTimes(1); + }, + { timeout: dotLottie?.duration * 1000 + 100 }, + ); + + unmount(); + + await vi.waitFor(() => { + expect(onDestroy).toHaveBeenCalledTimes(1); + }); + }); + + test('calls dotLottie.setLoop when loop prop changes', async () => { + const onLoad = vi.fn(); + const dotLottieRefCallback = vi.fn(); + + const { rerender } = render(); + + await vi.waitFor(() => { + expect(dotLottieRefCallback).toHaveBeenCalledTimes(1); + }); + + const dotLottie = dotLottieRefCallback.mock.calls[0]?.[0]; + + const setLoop = vi.spyOn(dotLottie, 'setLoop'); + + dotLottie?.addEventListener('load', onLoad); + + await vi.waitFor(() => { + expect(onLoad).toHaveBeenCalledTimes(1); + }); + + expect(dotLottie?.loop).toBe(false); + + rerender(); + + await vi.waitFor(() => { + expect(setLoop).toHaveBeenCalledTimes(1); + }); + + expect(setLoop).toHaveBeenCalledWith(true); + + await vi.waitFor(() => { + expect(dotLottie?.loop).toBe(true); + }); + + rerender(); + + await vi.waitFor(() => { + expect(setLoop).toHaveBeenCalledTimes(2); + }); + + expect(setLoop).toHaveBeenCalledWith(false); + + await vi.waitFor(() => { + expect(dotLottie?.loop).toBe(false); + }); + }); + + test('calls dotLottie.setSpeed when speed prop changes', async () => { + const onLoad = vi.fn(); + const dotLottieRefCallback = vi.fn(); + + const { rerender } = render(); + + await vi.waitFor(() => { + expect(dotLottieRefCallback).toHaveBeenCalledTimes(1); + }); + + const dotLottie = dotLottieRefCallback.mock.calls[0]?.[0]; + + dotLottie?.addEventListener('load', onLoad); + + await vi.waitFor(() => { + expect(onLoad).toHaveBeenCalledTimes(1); + }); + + const setSpeed = vi.spyOn(dotLottie, 'setSpeed'); + + expect(dotLottie?.speed).toBe(1); + + rerender(); + + await vi.waitFor(() => { + expect(setSpeed).toHaveBeenCalledTimes(1); + }); + + expect(setSpeed).toHaveBeenCalledWith(2); + + await vi.waitFor(() => { + expect(dotLottie?.speed).toBe(2); + }); + + rerender(); + + await vi.waitFor(() => { + expect(setSpeed).toHaveBeenCalledTimes(2); + }); + + expect(setSpeed).toHaveBeenCalledWith(1); + + await vi.waitFor(() => { + expect(dotLottie?.speed).toBe(1); + }); + }); + + test('calls dotLottie.setMode when mode prop changes', async () => { + const onLoad = vi.fn(); + const dotLottieRefCallback = vi.fn(); + + const { rerender } = render(); + + await vi.waitFor(() => { + expect(dotLottieRefCallback).toHaveBeenCalledTimes(1); + }); + + const dotLottie = dotLottieRefCallback.mock.calls[0]?.[0]; + + dotLottie?.addEventListener('load', onLoad); + + await vi.waitFor(() => { + expect(onLoad).toHaveBeenCalledTimes(1); + }); + + const setMode = vi.spyOn(dotLottie, 'setMode'); + + expect(dotLottie?.mode).toBe('forward'); + + rerender(); + + await vi.waitFor(() => { + expect(setMode).toHaveBeenCalledTimes(1); + }); + + expect(setMode).toHaveBeenCalledWith('reverse'); + + await vi.waitFor(() => { + expect(dotLottie?.mode).toBe('reverse'); + }); + + rerender(); + + await vi.waitFor(() => { + expect(setMode).toHaveBeenCalledTimes(2); + }); + + expect(setMode).toHaveBeenCalledWith('forward'); + + await vi.waitFor(() => { + expect(dotLottie?.mode).toBe('forward'); + }); + }); + + test('calls dotLottie.setUseFrameInterpolation when useFrameInterpolation prop changes', async () => { + const onLoad = vi.fn(); + const dotLottieRefCallback = vi.fn(); + + const { rerender } = render(); + + await vi.waitFor(() => { + expect(dotLottieRefCallback).toHaveBeenCalledTimes(1); + }); + + const dotLottie = dotLottieRefCallback.mock.calls[0]?.[0]; + + const setUseFrameInterpolation = vi.spyOn(dotLottie, 'setUseFrameInterpolation'); + + dotLottie?.addEventListener('load', onLoad); + + await vi.waitFor(() => { + expect(onLoad).toHaveBeenCalledTimes(1); + }); + + expect(dotLottie?.useFrameInterpolation).toBe(true); + + rerender( + , + ); + + await vi.waitFor(() => { + expect(setUseFrameInterpolation).toHaveBeenCalledTimes(1); + }); + + expect(setUseFrameInterpolation).toHaveBeenCalledWith(false); + + await vi.waitFor(() => { + expect(dotLottie?.useFrameInterpolation).toBe(false); + }); + + rerender(); + + await vi.waitFor(() => { + expect(setUseFrameInterpolation).toHaveBeenCalledTimes(2); + }); + + expect(setUseFrameInterpolation).toHaveBeenCalledWith(true); + + await vi.waitFor(() => { + expect(dotLottie?.useFrameInterpolation).toBe(true); + }); + }); + + test('calls dotLottie.setBackgroundColor when backgroundColor prop changes', async () => { + const onLoad = vi.fn(); + const dotLottieRefCallback = vi.fn(); + + const { rerender } = render(); + + await vi.waitFor(() => { + expect(dotLottieRefCallback).toHaveBeenCalledTimes(1); + }); + + const dotLottie = dotLottieRefCallback.mock.calls[0]?.[0]; + + const setBackgroundColor = vi.spyOn(dotLottie, 'setBackgroundColor'); + + dotLottie?.addEventListener('load', onLoad); + + await vi.waitFor(() => { + expect(onLoad).toHaveBeenCalledTimes(1); + }); + + expect(dotLottie?.backgroundColor).toBe(''); + + rerender( + , + ); + + await vi.waitFor(() => { + expect(setBackgroundColor).toHaveBeenCalledTimes(1); + }); + + expect(setBackgroundColor).toHaveBeenCalledWith('#00ff00ff'); + + rerender(); + + await vi.waitFor(() => { + expect(setBackgroundColor).toHaveBeenCalledTimes(2); + }); + + expect(dotLottie?.backgroundColor).toBe(''); + }); + + test('calls dotLottie.setMarker when marker prop changes', async () => { + const onLoad = vi.fn(); + const dotLottieRefCallback = vi.fn(); + + const { rerender } = render(); + + await vi.waitFor(() => { + expect(dotLottieRefCallback).toHaveBeenCalledTimes(1); + }); + + const dotLottie = dotLottieRefCallback.mock.calls[0]?.[0]; + + const setMarker = vi.spyOn(dotLottie, 'setMarker'); + + dotLottie?.addEventListener('load', onLoad); + + await vi.waitFor(() => { + expect(onLoad).toHaveBeenCalledTimes(1); + }); + + expect(dotLottie?.marker).toBe(''); + + rerender(); + + await vi.waitFor(() => { + expect(setMarker).toHaveBeenCalledTimes(1); + }); + + expect(setMarker).toHaveBeenCalledWith('Marker_1'); + + rerender(); + + await vi.waitFor(() => { + expect(setMarker).toHaveBeenCalledTimes(2); + }); + + expect(dotLottie?.marker).toBe(''); + }); + + test('calls dotLottie.setSegment & dotLottie.resetSegment when segment prop changes', async () => { + const onLoad = vi.fn(); + const dotLottieRefCallback = vi.fn(); + + const { rerender } = render(); + + await vi.waitFor(() => { + expect(dotLottieRefCallback).toHaveBeenCalledTimes(1); + }); + + const dotLottie = dotLottieRefCallback.mock.calls[0]?.[0]; + + const setSegment = vi.spyOn(dotLottie, 'setSegment'); + const resetSegment = vi.spyOn(dotLottie, 'resetSegment'); + + dotLottie?.addEventListener('load', onLoad); + + await vi.waitFor(() => { + expect(onLoad).toHaveBeenCalledTimes(1); + }); + + expect(dotLottie?.segment).toBeUndefined(); + + rerender(); + + await vi.waitFor(() => { + expect(setSegment).toHaveBeenCalledTimes(1); + }); + + expect(setSegment).toHaveBeenCalledWith(0, 10); + + rerender(); + + await vi.waitFor(() => { + expect(resetSegment).toHaveBeenCalledTimes(1); + }); + + expect(dotLottie?.segment).toBeUndefined(); + }); + + test('calls dotLottie.setTheme & dotLottie.resetTheme when themeId prop changes', async () => { + const onLoad = vi.fn(); + const dotLottieRefCallback = vi.fn(); + + const { rerender } = render(); + + await vi.waitFor(() => { + expect(dotLottieRefCallback).toHaveBeenCalledTimes(1); + }); + + const dotLottie = dotLottieRefCallback.mock.calls[0]?.[0]; + + const setTheme = vi.spyOn(dotLottie, 'setTheme'); + const resetTheme = vi.spyOn(dotLottie, 'resetTheme'); + + dotLottie?.addEventListener('load', onLoad); + + await vi.waitFor(() => { + expect(onLoad).toHaveBeenCalledTimes(1); + }); + + expect(dotLottie?.themeId).toBeUndefined(); + + rerender(); + + await vi.waitFor(() => { + expect(setTheme).toHaveBeenCalledTimes(1); + }); + + expect(setTheme).toHaveBeenCalledWith('Theme_1'); + + rerender(); + + await vi.waitFor(() => { + expect(resetTheme).toHaveBeenCalledTimes(1); + }); + + expect(dotLottie?.themeId).toBeUndefined(); + }); + + test('playOnHover', async () => { + const user = userEvent.setup(); + + const onLoad = vi.fn(); + const dotLottieRefCallback = vi.fn(); + + const screen = render( + , + ); + + const dotLottie = dotLottieRefCallback.mock.calls[0]?.[0]; + + dotLottie?.addEventListener('load', onLoad); + + await vi.waitFor(() => { + expect(onLoad).toHaveBeenCalledTimes(1); + }); + + const play = vi.spyOn(dotLottie, 'play'); + const pause = vi.spyOn(dotLottie, 'pause'); + + let canvasElement = screen.getByTestId('dotLottie-canvas').element(); + + await user.hover(canvasElement); + + await vi.waitFor(() => { + expect(play).toHaveBeenCalledTimes(1); + }); + + await user.unhover(canvasElement); + + await vi.waitFor(() => { + expect(pause).toHaveBeenCalledTimes(1); + }); + + play.mockClear(); + pause.mockClear(); + + // shouldn't call play/pause again as the playOnHover prop is undefined + screen.rerender( + , + ); + + canvasElement = screen.getByTestId('dotLottie-canvas').element(); + + let mouseEnterCount = 0; + let mouseLeaveCount = 0; + + canvasElement.addEventListener('mouseenter', () => { + mouseEnterCount += 1; + }); + canvasElement.addEventListener('mouseleave', () => { + mouseLeaveCount += 1; + }); + + await user.hover(canvasElement); + + await vi.waitFor(() => { + expect(mouseEnterCount).toBe(1); + expect(mouseLeaveCount).toBe(0); + }); + + expect(play).not.toHaveBeenCalled(); + + await user.unhover(canvasElement); + + await vi.waitFor(() => { + expect(mouseEnterCount).toBe(1); + expect(mouseLeaveCount).toBe(1); + }); + + expect(pause).not.toHaveBeenCalled(); + }); + + test('calls dotLottie.loadAnimation when animationId prop changes', async () => { + const onLoad = vi.fn(); + const dotLottieRefCallback = vi.fn(); + + const { rerender } = render(); + + await vi.waitFor(() => { + expect(dotLottieRefCallback).toHaveBeenCalledTimes(1); + }); + + const dotLottie = dotLottieRefCallback.mock.calls[0]?.[0]; + + dotLottie?.addEventListener('load', onLoad); + + await vi.waitFor(() => { + expect(onLoad).toHaveBeenCalledTimes(1); + }); + + const loadAnimation = vi.spyOn(dotLottie, 'loadAnimation'); + + rerender( + , + ); + + await vi.waitFor(() => { + expect(loadAnimation).toHaveBeenCalledTimes(1); + }); + + expect(loadAnimation).toHaveBeenCalledWith('Animation_1'); + + rerender(); + + await vi.waitFor(() => { + expect(loadAnimation).toHaveBeenCalledTimes(2); + }); + + expect(loadAnimation).toHaveBeenCalledWith(''); + + await vi.waitFor(() => { + expect(dotLottie?.activeAnimationId).toBe(''); + }); + }); + + test('calls dotLottie.setRenderConfig when renderConfig prop changes', async () => { + const onLoad = vi.fn(); + const dotLottieRefCallback = vi.fn(); + + const { rerender } = render(); + + await vi.waitFor(() => { + expect(dotLottieRefCallback).toHaveBeenCalledTimes(1); + }); + + const dotLottie = dotLottieRefCallback.mock.calls[0]?.[0]; + + dotLottie?.addEventListener('load', onLoad); + + await vi.waitFor(() => { + expect(onLoad).toHaveBeenCalledTimes(1); + }); + + const defaultRenderConfig = dotLottie?.renderConfig; + + const setRenderConfig = vi.spyOn(dotLottie, 'setRenderConfig'); + + rerender( + , + ); + + await vi.waitFor(() => { + expect(setRenderConfig).toHaveBeenCalledTimes(1); + }); + + expect(setRenderConfig).toHaveBeenCalledWith({ + devicePixelRatio: 0.5, + freezeOnOffscreen: false, + }); + + rerender(); + + await vi.waitFor(() => { + expect(setRenderConfig).toHaveBeenCalledTimes(2); + }); + + expect(setRenderConfig).toHaveBeenCalledWith({}); + + // Falls back to the default values + expect(dotLottie?.renderConfig).toEqual(defaultRenderConfig); + }); + + test('calls dotLottie.load when data prop changes', async () => { + const onLoad = vi.fn(); + const dotLottieRefCallback = vi.fn(); + + let response = await fetch(lottieSrc); + const animationData = await response.json(); + + const { rerender } = render( + , + ); + + await vi.waitFor(() => { + expect(dotLottieRefCallback).toHaveBeenCalledTimes(1); + }); + + const dotLottie = dotLottieRefCallback.mock.calls[0]?.[0]; + + dotLottie?.addEventListener('load', onLoad); + + await vi.waitFor(() => { + expect(onLoad).toHaveBeenCalledTimes(1); + }); + + const load = vi.spyOn(dotLottie, 'load'); + + response = await fetch(dotLottieSrc); + const dotLottieAnimationData = await response.arrayBuffer(); + + rerender( + , + ); + + await vi.waitFor(() => { + expect(load).toHaveBeenCalledTimes(1); + }); + + expect(load).toHaveBeenCalledWith({ + data: dotLottieAnimationData, + loop: true, + autoplay: true, + speed: 2, + }); + }); + + test('calls dotLottie.load when src prop changes', async () => { + const onLoad = vi.fn(); + const dotLottieRefCallback = vi.fn(); + + const { rerender } = render(); + + await vi.waitFor(() => { + expect(dotLottieRefCallback).toHaveBeenCalledTimes(1); + }); + + const dotLottie = dotLottieRefCallback.mock.calls[0]?.[0]; + + dotLottie?.addEventListener('load', onLoad); + + await vi.waitFor(() => { + expect(onLoad).toHaveBeenCalledTimes(1); + }); + + const load = vi.spyOn(dotLottie, 'load'); + + rerender(); + + await vi.waitFor(() => { + expect(load).toHaveBeenCalledTimes(1); + }); + + expect(load).toHaveBeenCalledWith({ + src: lottieSrc, + loop: true, + autoplay: true, + speed: 2, + }); + }); +}); diff --git a/packages/react/tsup.config.cjs b/packages/react/tsup.config.cjs index 22f8c4dc..b72f7873 100644 --- a/packages/react/tsup.config.cjs +++ b/packages/react/tsup.config.cjs @@ -1,20 +1,17 @@ const { defineConfig } = require('tsup'); module.exports = defineConfig({ - bundle: true, + bundle: false, metafile: false, splitting: false, treeshake: true, clean: true, dts: true, - minify: false, - sourcemap: false, - entry: ['./src/index.ts'], + sourcemap: true, + entry: ['./src/**/*.{ts,tsx}'], format: ['esm'], platform: 'browser', - target: ['es2015', 'node18'], + target: ['es2020'], tsconfig: 'tsconfig.build.json', - // To provide an esm build without any external dependencies - noExternal: Object.keys(require('./package.json').dependencies), external: ['react'], }); diff --git a/packages/react/vitest.config.ts b/packages/react/vitest.config.ts new file mode 100644 index 00000000..4268bfa8 --- /dev/null +++ b/packages/react/vitest.config.ts @@ -0,0 +1,29 @@ +import react from '@vitejs/plugin-react'; +import { defineConfig } from 'vitest/config'; + +export default defineConfig({ + plugins: [react()], + test: { + browser: { + enabled: true, + name: 'chromium', + provider: 'playwright', + screenshotFailures: false, + }, + retry: 1, + coverage: { + provider: 'istanbul', + include: ['src/**/*.{ts,tsx}'], + reporter: ['json', 'json-summary', 'text-summary', 'lcov'], + thresholds: { + statements: 95, + branches: 95, + functions: 95, + lines: 95, + }, + }, + testTimeout: 10000, + cache: false, + setupFiles: ['./setup-file.ts'], + }, +}); diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index a5188a19..aade3601 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -393,21 +393,42 @@ importers: specifier: workspace:* version: link:../web devDependencies: + '@testing-library/user-event': + specifier: ^14.5.2 + version: 14.5.2(@testing-library/dom@10.4.0) '@types/react': - specifier: ^19.0.1 - version: 19.0.1 + specifier: ^18 + version: 18.2.74 + '@vitejs/plugin-react': + specifier: ^4.2.1 + version: 4.2.1(vite@5.3.4(@types/node@22.7.6)(lightningcss@1.26.0)(terser@5.31.1)) + '@vitest/browser': + specifier: 2.1.0-beta.5 + version: 2.1.0-beta.5(@types/node@22.7.6)(playwright@1.45.2)(typescript@5.0.4)(vitest@2.1.0-beta.5)(webdriverio@8.39.1(encoding@0.1.13)(typescript@5.0.4)) + '@vitest/coverage-istanbul': + specifier: 2.1.0-beta.5 + version: 2.1.0-beta.5(vitest@2.1.0-beta.5(@types/node@22.7.6)(@vitest/browser@2.1.0-beta.5)(lightningcss@1.26.0)(terser@5.31.1)) cross-env: specifier: 7.0.3 version: 7.0.3 + playwright: + specifier: 1.45.2 + version: 1.45.2 react: - specifier: ^19.0.0 - version: 19.0.0 + specifier: ^18 + version: 18.2.0 tsup: specifier: 8.3.5 version: 8.3.5(@swc/core@1.3.107(@swc/helpers@0.5.5))(jiti@1.21.0)(postcss@8.4.39)(typescript@5.0.4)(yaml@2.4.5) typescript: specifier: 5.0.4 version: 5.0.4 + vitest: + specifier: 2.1.0-beta.5 + version: 2.1.0-beta.5(@types/node@22.7.6)(@vitest/browser@2.1.0-beta.5)(lightningcss@1.26.0)(terser@5.31.1) + vitest-browser-react: + specifier: ^0.0.4 + version: 0.0.4(@types/react-dom@18.2.24)(@types/react@18.2.74)(@vitest/browser@2.1.0-beta.5(@types/node@22.7.6)(playwright@1.45.2)(typescript@5.0.4)(vitest@2.1.0-beta.5)(webdriverio@8.39.1(encoding@0.1.13)(typescript@5.0.4)))(react-dom@18.2.0(react@18.2.0))(react@18.2.0)(vitest@2.1.0-beta.5(@types/node@22.7.6)(@vitest/browser@2.1.0-beta.5)(lightningcss@1.26.0)(terser@5.31.1)) packages/solid: dependencies: @@ -644,10 +665,6 @@ packages: resolution: {integrity: sha512-5e3FI4Q3M3Pbr21+5xJwCv6ZT6KmGkI0vw3Tozy5ODAQFTIWe37iT8Cr7Ice2Ntb+M3iSKCEWMB1MBgKrW3whg==} engines: {node: '>=6.9.0'} - '@babel/generator@7.24.10': - resolution: {integrity: sha512-o9HBZL1G2129luEUlG1hB4N/nlYNWHnpwlND9eOMclRqqu1YDy2sSYVCFUZwl8I1Gxh+QSRrP2vD7EpUmFVXxg==} - engines: {node: '>=6.9.0'} - '@babel/generator@7.24.7': resolution: {integrity: sha512-oipXieGC3i45Y1A41t4tAqpnEZWgB/lC6Ehh6+rOviR5XWpTtMmLN+fGjz9vOiNRt0p6RtO6DtD0pdU3vpqdSA==} engines: {node: '>=6.9.0'} @@ -708,12 +725,6 @@ packages: peerDependencies: '@babel/core': ^7.0.0 - '@babel/helper-module-transforms@7.24.9': - resolution: {integrity: sha512-oYbh+rtFKj/HwBQkFlUzvcybzklmVdVV3UU+mN7n2t/q3yGHbuVdNxyFvSBO1tfvjyArpHNcWMAzsSPdyI46hw==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0 - '@babel/helper-module-transforms@7.25.7': resolution: {integrity: sha512-k/6f8dKG3yDz/qCwSM+RKovjMix563SLxQFo0UhRNo239SP6n9u5/eLtKD6EAjwta2JHJ49CsD8pms2HdNiMMQ==} engines: {node: '>=6.9.0'} @@ -724,10 +735,6 @@ packages: resolution: {integrity: sha512-VAwcwuYhv/AT+Vfr28c9y6SHzTan1ryqrydSTFGjU0uDJHw3uZ+PduI8plCLkRsDnqK2DMEDmwrOQRsK/Ykjng==} engines: {node: '>=6.9.0'} - '@babel/helper-plugin-utils@7.24.0': - resolution: {integrity: sha512-9cUznXMG0+FxRuJfvL82QlTqIzhVW9sL0KjMPHhAOOvpQGL8QtdxnBKILjBqxlHyliz0yCa1G903ZXI/FuHy2w==} - engines: {node: '>=6.9.0'} - '@babel/helper-plugin-utils@7.24.7': resolution: {integrity: sha512-Rq76wjt7yz9AAc1KnlRKNAi/dMSVWgDRx43FHoJEbcYU6xOWaE2dVPwcdTukJrjxS65GITyfbvEYHvkirZ6uEg==} engines: {node: '>=6.9.0'} @@ -778,10 +785,6 @@ packages: resolution: {integrity: sha512-yy1/KvjhV/ZCL+SM7hBrvnZJ3ZuT9OuZgIJAGpPEToANvc3iM6iDvBnRjtElWibHU6n8/LPR/EjX9EtIEYO3pw==} engines: {node: '>=6.9.0'} - '@babel/helper-validator-option@7.24.8': - resolution: {integrity: sha512-xb8t9tD1MHLungh/AIoWYN+gVHaB9kwlu8gffXGSt3FFEIT7RjS+xWbc2vUD1UTZdIpKj/ab3rdqJ7ufngyi2Q==} - engines: {node: '>=6.9.0'} - '@babel/helper-validator-option@7.25.7': resolution: {integrity: sha512-ytbPLsm+GjArDYXJ8Ydr1c/KJuutjF2besPNbIZnZ6MKUxi/uTA22t2ymmA4WFjZFpjiAMO0xuuJPqK2nvDVfQ==} engines: {node: '>=6.9.0'} @@ -820,11 +823,6 @@ packages: engines: {node: '>=6.0.0'} hasBin: true - '@babel/parser@7.24.8': - resolution: {integrity: sha512-WzfbgXOkGzZiXXCqk43kKwZjzwx4oulxZi3nq2TYL9mOjQv6kYwul9mz6ID36njuL7Xkp6nJEfok848Zj10j/w==} - engines: {node: '>=6.0.0'} - hasBin: true - '@babel/parser@7.25.8': resolution: {integrity: sha512-HcttkxzdPucv3nNFmfOOMfFf64KgdJVqm1KaCm25dPGMLElo9nsLvXeJECQg8UzPuBGLyTSA0ZzqCtDSzKTEoQ==} engines: {node: '>=6.0.0'} @@ -904,10 +902,6 @@ packages: resolution: {integrity: sha512-yb65Ed5S/QAcewNPh0nZczy9JdYXkkAbIsEo+P7BE7yO3txAY30Y/oPa3QkQ5It3xVG2kpKMg9MsdxZaO31uKA==} engines: {node: '>=6.9.0'} - '@babel/traverse@7.24.8': - resolution: {integrity: sha512-t0P1xxAPzEDcEPmjprAQq19NWum4K0EQPjMwZQZbHt+GiZqvjCHjj755Weq1YRPVzBI+3zSfvScfpnuIecVFJQ==} - engines: {node: '>=6.9.0'} - '@babel/traverse@7.25.7': resolution: {integrity: sha512-jatJPT1Zjqvh/1FyJs6qAHL+Dzb7sTb+xr7Q+gM1b+1oBsMsQQ4FkVKb6dFlJvLlVssqkRzV05Jzervt9yhnzg==} engines: {node: '>=6.9.0'} @@ -916,10 +910,6 @@ packages: resolution: {integrity: sha512-XEFXSlxiG5td2EJRe8vOmRbaXVgfcBlszKujvVmWIK/UpywWljQCfzAv3RQCGujWQ1RD4YYWEAqDXfuJiy8f5Q==} engines: {node: '>=6.9.0'} - '@babel/types@7.24.9': - resolution: {integrity: sha512-xm8XrMKz0IlUdocVbYJe0Z9xEgidU7msskG8BbhnTPK/HZ2z/7FP7ykqPgrUH+C+r414mNfNWam1f2vqOjqjYQ==} - engines: {node: '>=6.9.0'} - '@babel/types@7.25.8': resolution: {integrity: sha512-JWtuCu8VQsMladxVz/P4HzHUGCAwpuqacmowgXFs5XjxIgKuNjnLokQzuVjlTvIzODaDmpjT3oxcC48vyk9EWg==} engines: {node: '>=6.9.0'} @@ -3613,9 +3603,6 @@ packages: '@types/react@18.2.74': resolution: {integrity: sha512-9AEqNZZyBx8OdZpxzQlaFEVCSFUM2YXJH46yPOiOpm078k6ZLOCcuAzGum/zK8YBwY+dbahVNbHrbgrAwIRlqw==} - '@types/react@19.0.1': - resolution: {integrity: sha512-YW6614BDhqbpR5KtUYzTA+zlA7nayzJRA9ljz9CQoxthR0sDisYZLuvSMsil36t4EH/uAt8T52Xb4sVw17G+SQ==} - '@types/scheduler@0.16.8': resolution: {integrity: sha512-WZLiwShhwLRmeV6zH+GkbOFT6Z6VklCItrDioxUnv+u4Ll+8vKeFySoFyK/0ctcRpOmwAicELfmys1sDc/Rw+A==} @@ -7362,9 +7349,6 @@ packages: magic-string@0.25.9: resolution: {integrity: sha512-RmF0AsMzgt25qzqqLc1+MbHmhdx0ojF2Fvs4XnOqz2ZOBXzzkEwc/dJQZCYHAn7v1jbVOjAZfK8msRn4BxO4VQ==} - magic-string@0.30.10: - resolution: {integrity: sha512-iIRwTIf0QKV3UAnYK4PU8uiEc4SRh5jX0mwpIwETPpHdhVM4f53RSwS/vXvN1JhGX+Cs7B8qIq3d6AH49O5fAQ==} - magic-string@0.30.14: resolution: {integrity: sha512-5c99P1WKTed11ZC0HMJOj6CDIue6F8ySu+bJL+85q1zBEIY8IklrJ1eiKC2NDRh3Ct3FcvmJPyQHb9erXMTJNw==} @@ -7806,10 +7790,6 @@ packages: resolution: {integrity: sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==} engines: {node: '>=8'} - minipass@7.0.4: - resolution: {integrity: sha512-jYofLM5Dam9279rdkWzqHozUo4ybjdZmCsDHePy5V/PbBcVMiSZR97gmAy45aqi8CK1lG2ECd356FU86avfwUQ==} - engines: {node: '>=16 || 14 >=14.17'} - minipass@7.1.2: resolution: {integrity: sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==} engines: {node: '>=16 || 14 >=14.17'} @@ -8302,10 +8282,6 @@ packages: path-parse@1.0.7: resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==} - path-scurry@1.10.1: - resolution: {integrity: sha512-MkhCqzzBEpPvxxQ71Md0b1Kk51W01lrYvlMzSUaIzNsODdd7mqhiimSZlr+VegAz5Z6Vzt9Xg2ttE//XBhH3EQ==} - engines: {node: '>=16 || 14 >=14.17'} - path-scurry@1.11.1: resolution: {integrity: sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==} engines: {node: '>=16 || 14 >=14.18'} @@ -8834,10 +8810,6 @@ packages: resolution: {integrity: sha512-/3IjMdb2L9QbBdWiW5e3P2/npwMBaU9mHCSCUzNln0ZCYbcfTsGbTJrU/kGemdH2IWmB2ioZ+zkxtmq6g09fGQ==} engines: {node: '>=0.10.0'} - react@19.0.0: - resolution: {integrity: sha512-V8AVnmPIICiWpGfm6GLzCR/W5FXLchHop40W4nXBmdlEceh16rCN8O8LNWm5bh5XUX91fh7KpA+W0TgMKmgTpQ==} - engines: {node: '>=0.10.0'} - read-cache@1.0.0: resolution: {integrity: sha512-Owdv/Ft7IjOgm/i0xvNDZ1LrRANRfew4b2prF3OWMQLxLfu3bS8FVhCsrSCMK4lR56Y9ya+AThoTpDCTxCmpRA==} @@ -10677,6 +10649,22 @@ packages: vite: optional: true + vitest-browser-react@0.0.4: + resolution: {integrity: sha512-4uK8zgo5eHlhrBVEPX8ejRt8Bn4gzV6OZFTPdb1en3FtgjEhhst400XkIQHUC875Q90rOO5Tc4zPpCl8YXvoxg==} + engines: {node: ^18.0.0 || >=20.0.0} + peerDependencies: + '@types/react': '>18.0.0' + '@types/react-dom': '>18.0.0' + '@vitest/browser': '>=2.1.0' + react: '>18.0.0' + react-dom: '>18.0.0' + vitest: '>=2.1.0' + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + vitest@1.2.2: resolution: {integrity: sha512-d5Ouvrnms3GD9USIK36KG8OZ5bEvKEkITFtnGv56HFaSlbItJuYr7hv2Lkn903+AvRAgSixiamozUVfORUekjw==} engines: {node: ^18.0.0 || >=20.0.0} @@ -11102,12 +11090,12 @@ snapshots: '@babel/helper-compilation-targets': 7.23.6 '@babel/helper-module-transforms': 7.24.7(@babel/core@7.23.2) '@babel/helpers': 7.24.4 - '@babel/parser': 7.24.7 + '@babel/parser': 7.25.8 '@babel/template': 7.24.7 '@babel/traverse': 7.24.7 - '@babel/types': 7.24.7 + '@babel/types': 7.25.8 convert-source-map: 2.0.0 - debug: 4.3.5 + debug: 4.3.7 gensync: 1.0.0-beta.2 json5: 2.2.3 semver: 6.3.1 @@ -11127,7 +11115,7 @@ snapshots: '@babel/traverse': 7.24.7 '@babel/types': 7.24.7 convert-source-map: 2.0.0 - debug: 4.3.5 + debug: 4.3.7 gensync: 1.0.0-beta.2 json5: 2.2.3 semver: 6.3.1 @@ -11137,30 +11125,23 @@ snapshots: '@babel/core@7.24.9': dependencies: '@ampproject/remapping': 2.3.0 - '@babel/code-frame': 7.24.7 - '@babel/generator': 7.24.10 + '@babel/code-frame': 7.25.7 + '@babel/generator': 7.25.7 '@babel/helper-compilation-targets': 7.24.8 - '@babel/helper-module-transforms': 7.24.9(@babel/core@7.24.9) + '@babel/helper-module-transforms': 7.25.7(@babel/core@7.24.9) '@babel/helpers': 7.24.8 - '@babel/parser': 7.24.8 - '@babel/template': 7.24.7 - '@babel/traverse': 7.24.8 - '@babel/types': 7.24.9 + '@babel/parser': 7.25.8 + '@babel/template': 7.25.7 + '@babel/traverse': 7.25.7 + '@babel/types': 7.25.8 convert-source-map: 2.0.0 - debug: 4.3.5 + debug: 4.3.7 gensync: 1.0.0-beta.2 json5: 2.2.3 semver: 6.3.1 transitivePeerDependencies: - supports-color - '@babel/generator@7.24.10': - dependencies: - '@babel/types': 7.25.8 - '@jridgewell/gen-mapping': 0.3.5 - '@jridgewell/trace-mapping': 0.3.25 - jsesc: 2.5.2 - '@babel/generator@7.24.7': dependencies: '@babel/types': 7.25.8 @@ -11190,7 +11171,7 @@ snapshots: '@babel/helper-compilation-targets@7.24.8': dependencies: '@babel/compat-data': 7.24.9 - '@babel/helper-validator-option': 7.24.8 + '@babel/helper-validator-option': 7.25.7 browserslist: 4.23.2 lru-cache: 5.1.1 semver: 6.3.1 @@ -11214,7 +11195,7 @@ snapshots: '@babel/helper-function-name@7.24.7': dependencies: - '@babel/template': 7.24.7 + '@babel/template': 7.25.7 '@babel/types': 7.25.8 '@babel/helper-hoist-variables@7.24.7': @@ -11253,7 +11234,7 @@ snapshots: '@babel/helper-module-imports': 7.24.7 '@babel/helper-simple-access': 7.24.7 '@babel/helper-split-export-declaration': 7.24.7 - '@babel/helper-validator-identifier': 7.24.7 + '@babel/helper-validator-identifier': 7.25.7 transitivePeerDependencies: - supports-color @@ -11264,17 +11245,6 @@ snapshots: '@babel/helper-module-imports': 7.24.7 '@babel/helper-simple-access': 7.24.7 '@babel/helper-split-export-declaration': 7.24.7 - '@babel/helper-validator-identifier': 7.24.7 - transitivePeerDependencies: - - supports-color - - '@babel/helper-module-transforms@7.24.9(@babel/core@7.24.9)': - dependencies: - '@babel/core': 7.24.9 - '@babel/helper-environment-visitor': 7.24.7 - '@babel/helper-module-imports': 7.24.7 - '@babel/helper-simple-access': 7.24.7 - '@babel/helper-split-export-declaration': 7.24.7 '@babel/helper-validator-identifier': 7.25.7 transitivePeerDependencies: - supports-color @@ -11293,8 +11263,6 @@ snapshots: dependencies: '@babel/types': 7.25.8 - '@babel/helper-plugin-utils@7.24.0': {} - '@babel/helper-plugin-utils@7.24.7': {} '@babel/helper-plugin-utils@7.25.7': {} @@ -11310,7 +11278,7 @@ snapshots: '@babel/helper-simple-access@7.24.7': dependencies: - '@babel/traverse': 7.24.8 + '@babel/traverse': 7.25.7 '@babel/types': 7.25.8 transitivePeerDependencies: - supports-color @@ -11343,8 +11311,6 @@ snapshots: '@babel/helper-validator-option@7.24.7': {} - '@babel/helper-validator-option@7.24.8': {} - '@babel/helper-validator-option@7.25.7': {} '@babel/helpers@7.24.4': @@ -11357,12 +11323,12 @@ snapshots: '@babel/helpers@7.24.8': dependencies: - '@babel/template': 7.24.7 + '@babel/template': 7.25.7 '@babel/types': 7.25.8 '@babel/highlight@7.22.20': dependencies: - '@babel/helper-validator-identifier': 7.24.7 + '@babel/helper-validator-identifier': 7.25.7 chalk: 2.4.2 js-tokens: 4.0.0 @@ -11395,10 +11361,6 @@ snapshots: dependencies: '@babel/types': 7.25.8 - '@babel/parser@7.24.8': - dependencies: - '@babel/types': 7.25.8 - '@babel/parser@7.25.8': dependencies: '@babel/types': 7.25.8 @@ -11406,12 +11368,12 @@ snapshots: '@babel/plugin-syntax-jsx@7.24.7(@babel/core@7.24.4)': dependencies: '@babel/core': 7.24.4 - '@babel/helper-plugin-utils': 7.24.7 + '@babel/helper-plugin-utils': 7.25.7 '@babel/plugin-syntax-jsx@7.24.7(@babel/core@7.24.9)': dependencies: '@babel/core': 7.24.9 - '@babel/helper-plugin-utils': 7.24.7 + '@babel/helper-plugin-utils': 7.25.7 '@babel/plugin-syntax-jsx@7.25.7(@babel/core@7.24.9)': dependencies: @@ -11437,15 +11399,15 @@ snapshots: transitivePeerDependencies: - supports-color - '@babel/plugin-transform-react-jsx-self@7.24.1(@babel/core@7.24.4)': + '@babel/plugin-transform-react-jsx-self@7.24.1(@babel/core@7.24.9)': dependencies: - '@babel/core': 7.24.4 - '@babel/helper-plugin-utils': 7.24.0 + '@babel/core': 7.24.9 + '@babel/helper-plugin-utils': 7.25.7 - '@babel/plugin-transform-react-jsx-source@7.24.1(@babel/core@7.24.4)': + '@babel/plugin-transform-react-jsx-source@7.24.1(@babel/core@7.24.9)': dependencies: - '@babel/core': 7.24.4 - '@babel/helper-plugin-utils': 7.24.0 + '@babel/core': 7.24.9 + '@babel/helper-plugin-utils': 7.25.7 '@babel/plugin-transform-typescript@7.25.7(@babel/core@7.24.9)': dependencies: @@ -11500,22 +11462,7 @@ snapshots: '@babel/helper-split-export-declaration': 7.24.7 '@babel/parser': 7.25.8 '@babel/types': 7.25.8 - debug: 4.3.5 - globals: 11.12.0 - transitivePeerDependencies: - - supports-color - - '@babel/traverse@7.24.8': - dependencies: - '@babel/code-frame': 7.25.7 - '@babel/generator': 7.24.10 - '@babel/helper-environment-visitor': 7.24.7 - '@babel/helper-function-name': 7.24.7 - '@babel/helper-hoist-variables': 7.24.7 - '@babel/helper-split-export-declaration': 7.24.7 - '@babel/parser': 7.25.8 - '@babel/types': 7.25.8 - debug: 4.3.5 + debug: 4.3.7 globals: 11.12.0 transitivePeerDependencies: - supports-color @@ -11538,12 +11485,6 @@ snapshots: '@babel/helper-validator-identifier': 7.24.7 to-fast-properties: 2.0.0 - '@babel/types@7.24.9': - dependencies: - '@babel/helper-string-parser': 7.25.7 - '@babel/helper-validator-identifier': 7.25.7 - to-fast-properties: 2.0.0 - '@babel/types@7.25.8': dependencies: '@babel/helper-string-parser': 7.25.7 @@ -12266,7 +12207,7 @@ snapshots: '@eslint/eslintrc@2.1.4': dependencies: ajv: 6.12.6 - debug: 4.3.5 + debug: 4.3.7 espree: 9.6.1 globals: 13.23.0 ignore: 5.2.4 @@ -12390,9 +12331,9 @@ snapshots: '@graphql-tools/graphql-tag-pluck@7.1.5(graphql@16.8.1)': dependencies: - '@babel/parser': 7.24.7 + '@babel/parser': 7.25.8 '@babel/traverse': 7.24.7 - '@babel/types': 7.24.7 + '@babel/types': 7.25.8 '@graphql-tools/utils': 8.6.1(graphql@16.8.1) graphql: 16.8.1 tslib: 2.3.1 @@ -12489,7 +12430,7 @@ snapshots: '@humanwhocodes/config-array@0.11.14': dependencies: '@humanwhocodes/object-schema': 2.0.2 - debug: 4.3.5 + debug: 4.3.7 minimatch: 3.1.2 transitivePeerDependencies: - supports-color @@ -12731,14 +12672,14 @@ snapshots: eslint: 7.32.0 eslint-config-prettier: 8.5.0(eslint@7.32.0) eslint-import-resolver-node: 0.3.6 - eslint-import-resolver-typescript: 2.5.0(eslint-plugin-import@2.25.4)(eslint@7.32.0) + eslint-import-resolver-typescript: 2.5.0(eslint-plugin-import@2.25.4(@typescript-eslint/parser@5.13.0(eslint@7.32.0)(typescript@5.0.4))(eslint@7.32.0))(eslint@7.32.0) eslint-plugin-compat: 4.0.2(eslint@7.32.0) eslint-plugin-deprecation: 1.3.2(eslint@7.32.0)(typescript@5.0.4) eslint-plugin-eslint-comments: 3.2.0(eslint@7.32.0) eslint-plugin-filenames: 1.3.2(eslint@7.32.0) eslint-plugin-header: 3.1.1(eslint@7.32.0) eslint-plugin-html: 6.2.0 - eslint-plugin-import: 2.25.4(@typescript-eslint/parser@5.13.0(eslint@7.32.0)(typescript@5.0.4))(eslint-import-resolver-typescript@2.5.0)(eslint@7.32.0) + eslint-plugin-import: 2.25.4(@typescript-eslint/parser@5.13.0(eslint@7.32.0)(typescript@5.0.4))(eslint-import-resolver-typescript@2.5.0(eslint-plugin-import@2.25.4(@typescript-eslint/parser@5.13.0(eslint@7.32.0)(typescript@5.0.4))(eslint@7.32.0))(eslint@7.32.0))(eslint@7.32.0) eslint-plugin-jest: 26.1.1(@typescript-eslint/eslint-plugin@5.13.0(@typescript-eslint/parser@5.13.0(eslint@7.32.0)(typescript@5.0.4))(eslint@7.32.0)(typescript@5.0.4))(eslint@7.32.0)(typescript@5.0.4) eslint-plugin-jest-dom: 4.0.1(eslint@7.32.0) eslint-plugin-jest-formatting: 3.1.0(eslint@7.32.0) @@ -13043,15 +12984,13 @@ snapshots: transitivePeerDependencies: - '@parcel/core' - '@parcel/cache@2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.5))(@swc/helpers@0.5.5)': + '@parcel/cache@2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.5))': dependencies: '@parcel/core': 2.12.0(@swc/helpers@0.5.5) '@parcel/fs': 2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.5))(@swc/helpers@0.5.5) '@parcel/logger': 2.12.0 '@parcel/utils': 2.12.0 lmdb: 2.8.5 - transitivePeerDependencies: - - '@swc/helpers' '@parcel/codeframe@2.12.0': dependencies: @@ -13111,7 +13050,7 @@ snapshots: '@parcel/core@2.12.0(@swc/helpers@0.5.5)': dependencies: '@mischnic/json-sourcemap': 0.1.1 - '@parcel/cache': 2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.5))(@swc/helpers@0.5.5) + '@parcel/cache': 2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.5)) '@parcel/diagnostic': 2.12.0 '@parcel/events': 2.12.0 '@parcel/fs': 2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.5))(@swc/helpers@0.5.5) @@ -13526,7 +13465,7 @@ snapshots: '@parcel/types@2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.5))(@swc/helpers@0.5.5)': dependencies: - '@parcel/cache': 2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.5))(@swc/helpers@0.5.5) + '@parcel/cache': 2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.5)) '@parcel/diagnostic': 2.12.0 '@parcel/fs': 2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.5))(@swc/helpers@0.5.5) '@parcel/package-manager': 2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.5))(@swc/helpers@0.5.5) @@ -14178,7 +14117,7 @@ snapshots: '@sveltejs/vite-plugin-svelte-inspector@2.0.0(@sveltejs/vite-plugin-svelte@3.0.2(svelte@5.0.0-next.55)(vite@5.0.13(@types/node@22.7.6)(lightningcss@1.26.0)(terser@5.31.1)))(svelte@5.0.0-next.55)(vite@5.0.13(@types/node@22.7.6)(lightningcss@1.26.0)(terser@5.31.1))': dependencies: '@sveltejs/vite-plugin-svelte': 3.0.2(svelte@5.0.0-next.55)(vite@5.0.13(@types/node@22.7.6)(lightningcss@1.26.0)(terser@5.31.1)) - debug: 4.3.5 + debug: 4.3.7 svelte: 5.0.0-next.55 vite: 5.0.13(@types/node@22.7.6)(lightningcss@1.26.0)(terser@5.31.1) transitivePeerDependencies: @@ -14313,8 +14252,8 @@ snapshots: '@types/babel__core@7.20.5': dependencies: - '@babel/parser': 7.24.7 - '@babel/types': 7.24.7 + '@babel/parser': 7.25.8 + '@babel/types': 7.25.8 '@types/babel__generator': 7.6.8 '@types/babel__template': 7.4.4 '@types/babel__traverse': 7.20.5 @@ -14463,10 +14402,6 @@ snapshots: '@types/prop-types': 15.7.11 csstype: 3.1.3 - '@types/react@19.0.1': - dependencies: - csstype: 3.1.3 - '@types/scheduler@0.16.8': {} '@types/semver@7.5.4': {} @@ -14638,7 +14573,7 @@ snapshots: '@typescript-eslint/type-utils@5.13.0(eslint@7.32.0)(typescript@5.0.4)': dependencies: '@typescript-eslint/utils': 5.13.0(eslint@7.32.0)(typescript@5.0.4) - debug: 4.3.5 + debug: 4.3.7 eslint: 7.32.0 tsutils: 3.21.0(typescript@5.0.4) optionalDependencies: @@ -14650,7 +14585,7 @@ snapshots: dependencies: '@typescript-eslint/typescript-estree': 6.20.0(typescript@5.2.2) '@typescript-eslint/utils': 6.20.0(eslint@8.56.0)(typescript@5.2.2) - debug: 4.3.5 + debug: 4.3.7 eslint: 8.56.0 ts-api-utils: 1.0.3(typescript@5.2.2) optionalDependencies: @@ -14662,7 +14597,7 @@ snapshots: dependencies: '@typescript-eslint/typescript-estree': 7.5.0(typescript@5.2.2) '@typescript-eslint/utils': 7.5.0(eslint@8.57.0)(typescript@5.2.2) - debug: 4.3.5 + debug: 4.3.7 eslint: 8.57.0 ts-api-utils: 1.0.3(typescript@5.2.2) optionalDependencies: @@ -14682,10 +14617,10 @@ snapshots: dependencies: '@typescript-eslint/types': 5.13.0 '@typescript-eslint/visitor-keys': 5.13.0 - debug: 4.3.5 + debug: 4.3.7 globby: 11.1.0 is-glob: 4.0.3 - semver: 7.6.0 + semver: 7.6.3 tsutils: 3.21.0(typescript@5.0.4) optionalDependencies: typescript: 5.0.4 @@ -14710,7 +14645,7 @@ snapshots: dependencies: '@typescript-eslint/types': 6.20.0 '@typescript-eslint/visitor-keys': 6.20.0 - debug: 4.3.5 + debug: 4.3.7 globby: 11.1.0 is-glob: 4.0.3 minimatch: 9.0.3 @@ -14725,7 +14660,7 @@ snapshots: dependencies: '@typescript-eslint/types': 7.5.0 '@typescript-eslint/visitor-keys': 7.5.0 - debug: 4.3.5 + debug: 4.3.7 globby: 11.1.0 is-glob: 4.0.3 minimatch: 9.0.3 @@ -14759,7 +14694,7 @@ snapshots: '@typescript-eslint/typescript-estree': 5.62.0(typescript@5.0.4) eslint: 7.32.0 eslint-scope: 5.1.1 - semver: 7.6.0 + semver: 7.6.3 transitivePeerDependencies: - supports-color - typescript @@ -14823,15 +14758,26 @@ snapshots: '@vitejs/plugin-react@4.2.1(vite@5.2.8(@types/node@22.7.6)(lightningcss@1.26.0)(terser@5.31.1))': dependencies: - '@babel/core': 7.24.4 - '@babel/plugin-transform-react-jsx-self': 7.24.1(@babel/core@7.24.4) - '@babel/plugin-transform-react-jsx-source': 7.24.1(@babel/core@7.24.4) + '@babel/core': 7.24.9 + '@babel/plugin-transform-react-jsx-self': 7.24.1(@babel/core@7.24.9) + '@babel/plugin-transform-react-jsx-source': 7.24.1(@babel/core@7.24.9) '@types/babel__core': 7.20.5 react-refresh: 0.14.0 vite: 5.2.8(@types/node@22.7.6)(lightningcss@1.26.0)(terser@5.31.1) transitivePeerDependencies: - supports-color + '@vitejs/plugin-react@4.2.1(vite@5.3.4(@types/node@22.7.6)(lightningcss@1.26.0)(terser@5.31.1))': + dependencies: + '@babel/core': 7.24.9 + '@babel/plugin-transform-react-jsx-self': 7.24.1(@babel/core@7.24.9) + '@babel/plugin-transform-react-jsx-source': 7.24.1(@babel/core@7.24.9) + '@types/babel__core': 7.20.5 + react-refresh: 0.14.0 + vite: 5.3.4(@types/node@22.7.6)(lightningcss@1.26.0)(terser@5.31.1) + transitivePeerDependencies: + - supports-color + '@vitejs/plugin-vue@4.6.2(vite@5.0.13(@types/node@22.7.6)(lightningcss@1.26.0)(terser@5.31.1))(vue@3.4.6(typescript@5.2.2))': dependencies: vite: 5.0.13(@types/node@22.7.6)(lightningcss@1.26.0)(terser@5.31.1) @@ -14952,7 +14898,7 @@ snapshots: '@vitest/snapshot@1.2.2': dependencies: - magic-string: 0.30.10 + magic-string: 0.30.14 pathe: 1.1.2 pretty-format: 29.7.0 @@ -15026,7 +14972,7 @@ snapshots: '@vue/compiler-ssr': 3.4.6 '@vue/shared': 3.4.6 estree-walker: 2.0.2 - magic-string: 0.30.10 + magic-string: 0.30.14 postcss: 8.4.32 source-map-js: 1.2.0 @@ -15054,7 +15000,7 @@ snapshots: '@vue/compiler-dom': 3.4.6 '@vue/shared': 3.4.6 computeds: 0.0.1 - minimatch: 9.0.3 + minimatch: 9.0.5 muggle-string: 0.3.1 path-browserify: 1.0.1 vue-template-compiler: 2.7.16 @@ -15738,7 +15684,7 @@ snapshots: fs-minipass: 3.0.3 glob: 10.4.5 lru-cache: 7.18.3 - minipass: 7.0.4 + minipass: 7.1.2 minipass-collect: 1.0.2 minipass-flush: 1.0.5 minipass-pipeline: 1.2.4 @@ -17053,7 +16999,7 @@ snapshots: eslint-compat-utils@0.4.1(eslint@8.56.0): dependencies: eslint: 8.56.0 - semver: 7.6.0 + semver: 7.6.3 eslint-config-prettier@8.5.0(eslint@7.32.0): dependencies: @@ -17070,11 +17016,11 @@ snapshots: transitivePeerDependencies: - supports-color - eslint-import-resolver-typescript@2.5.0(eslint-plugin-import@2.25.4)(eslint@7.32.0): + eslint-import-resolver-typescript@2.5.0(eslint-plugin-import@2.25.4(@typescript-eslint/parser@5.13.0(eslint@7.32.0)(typescript@5.0.4))(eslint@7.32.0))(eslint@7.32.0): dependencies: debug: 4.3.4 eslint: 7.32.0 - eslint-plugin-import: 2.25.4(@typescript-eslint/parser@5.13.0(eslint@7.32.0)(typescript@5.0.4))(eslint-import-resolver-typescript@2.5.0)(eslint@7.32.0) + eslint-plugin-import: 2.25.4(@typescript-eslint/parser@5.13.0(eslint@7.32.0)(typescript@5.0.4))(eslint-import-resolver-typescript@2.5.0(eslint-plugin-import@2.25.4(@typescript-eslint/parser@5.13.0(eslint@7.32.0)(typescript@5.0.4))(eslint@7.32.0))(eslint@7.32.0))(eslint@7.32.0) glob: 7.2.3 is-glob: 4.0.3 resolve: 1.22.8 @@ -17082,14 +17028,14 @@ snapshots: transitivePeerDependencies: - supports-color - eslint-module-utils@2.8.0(@typescript-eslint/parser@5.13.0(eslint@7.32.0)(typescript@5.0.4))(eslint-import-resolver-node@0.3.6)(eslint-import-resolver-typescript@2.5.0(eslint-plugin-import@2.25.4)(eslint@7.32.0))(eslint@7.32.0): + eslint-module-utils@2.8.0(@typescript-eslint/parser@5.13.0(eslint@7.32.0)(typescript@5.0.4))(eslint-import-resolver-node@0.3.6)(eslint-import-resolver-typescript@2.5.0(eslint-plugin-import@2.25.4(@typescript-eslint/parser@5.13.0(eslint@7.32.0)(typescript@5.0.4))(eslint@7.32.0))(eslint@7.32.0))(eslint@7.32.0): dependencies: debug: 3.2.7 optionalDependencies: '@typescript-eslint/parser': 5.13.0(eslint@7.32.0)(typescript@5.0.4) eslint: 7.32.0 eslint-import-resolver-node: 0.3.6 - eslint-import-resolver-typescript: 2.5.0(eslint-plugin-import@2.25.4)(eslint@7.32.0) + eslint-import-resolver-typescript: 2.5.0(eslint-plugin-import@2.25.4(@typescript-eslint/parser@5.13.0(eslint@7.32.0)(typescript@5.0.4))(eslint@7.32.0))(eslint@7.32.0) transitivePeerDependencies: - supports-color @@ -17143,7 +17089,7 @@ snapshots: dependencies: htmlparser2: 7.2.0 - eslint-plugin-import@2.25.4(@typescript-eslint/parser@5.13.0(eslint@7.32.0)(typescript@5.0.4))(eslint-import-resolver-typescript@2.5.0)(eslint@7.32.0): + eslint-plugin-import@2.25.4(@typescript-eslint/parser@5.13.0(eslint@7.32.0)(typescript@5.0.4))(eslint-import-resolver-typescript@2.5.0(eslint-plugin-import@2.25.4(@typescript-eslint/parser@5.13.0(eslint@7.32.0)(typescript@5.0.4))(eslint@7.32.0))(eslint@7.32.0))(eslint@7.32.0): dependencies: array-includes: 3.1.7 array.prototype.flat: 1.3.2 @@ -17151,7 +17097,7 @@ snapshots: doctrine: 2.1.0 eslint: 7.32.0 eslint-import-resolver-node: 0.3.6 - eslint-module-utils: 2.8.0(@typescript-eslint/parser@5.13.0(eslint@7.32.0)(typescript@5.0.4))(eslint-import-resolver-node@0.3.6)(eslint-import-resolver-typescript@2.5.0(eslint-plugin-import@2.25.4)(eslint@7.32.0))(eslint@7.32.0) + eslint-module-utils: 2.8.0(@typescript-eslint/parser@5.13.0(eslint@7.32.0)(typescript@5.0.4))(eslint-import-resolver-node@0.3.6)(eslint-import-resolver-typescript@2.5.0(eslint-plugin-import@2.25.4(@typescript-eslint/parser@5.13.0(eslint@7.32.0)(typescript@5.0.4))(eslint@7.32.0))(eslint@7.32.0))(eslint@7.32.0) has: 1.0.4 is-core-module: 2.13.1 is-glob: 4.0.3 @@ -17556,7 +17502,7 @@ snapshots: estree-walker@3.0.3: dependencies: - '@types/estree': 1.0.5 + '@types/estree': 1.0.6 esutils@2.0.3: {} @@ -17859,7 +17805,7 @@ snapshots: fs-minipass@3.0.3: dependencies: - minipass: 7.0.4 + minipass: 7.1.2 fs.realpath@1.0.0: {} @@ -18037,7 +17983,7 @@ snapshots: fs.realpath: 1.0.0 minimatch: 8.0.4 minipass: 4.2.8 - path-scurry: 1.10.1 + path-scurry: 1.11.1 global-dirs@0.1.1: dependencies: @@ -19009,10 +18955,6 @@ snapshots: dependencies: sourcemap-codec: 1.4.8 - magic-string@0.30.10: - dependencies: - '@jridgewell/sourcemap-codec': 1.5.0 - magic-string@0.30.14: dependencies: '@jridgewell/sourcemap-codec': 1.5.0 @@ -19849,8 +19791,6 @@ snapshots: minipass@5.0.0: {} - minipass@7.0.4: {} - minipass@7.1.2: {} minizlib@2.1.2: @@ -20488,11 +20428,6 @@ snapshots: path-parse@1.0.7: {} - path-scurry@1.10.1: - dependencies: - lru-cache: 10.4.3 - minipass: 7.1.2 - path-scurry@1.11.1: dependencies: lru-cache: 10.4.3 @@ -20956,7 +20891,7 @@ snapshots: rc-config-loader@4.1.3: dependencies: - debug: 4.3.5 + debug: 4.3.7 js-yaml: 4.1.0 json5: 2.2.3 require-from-string: 2.0.2 @@ -21041,8 +20976,6 @@ snapshots: dependencies: loose-envify: 1.4.0 - react@19.0.0: {} - read-cache@1.0.0: dependencies: pify: 2.3.0 @@ -22183,7 +22116,7 @@ snapshots: ssri@10.0.5: dependencies: - minipass: 7.0.4 + minipass: 7.1.2 stable@0.1.8: {} @@ -22430,7 +22363,7 @@ snapshots: dependencies: '@types/pug': 2.0.10 detect-indent: 6.1.0 - magic-string: 0.30.10 + magic-string: 0.30.14 sorcery: 0.11.0 strip-indent: 3.0.0 svelte: 5.0.0-next.55 @@ -23082,7 +23015,7 @@ snapshots: '@types/node': 18.19.41 '@types/unist': 2.0.9 concat-stream: 2.0.0 - debug: 4.3.5 + debug: 4.3.7 fault: 2.0.1 glob: 8.1.0 ignore: 5.2.4 @@ -23110,7 +23043,7 @@ snapshots: '@types/node': 17.0.45 '@types/unist': 2.0.6 concat-stream: 2.0.0 - debug: 4.3.5 + debug: 4.3.7 fault: 2.0.1 glob: 7.2.3 ignore: 5.2.4 @@ -23473,7 +23406,7 @@ snapshots: vite-node@1.2.2(@types/node@22.7.6)(lightningcss@1.26.0)(terser@5.31.1): dependencies: cac: 6.7.14 - debug: 4.3.5 + debug: 4.3.7 pathe: 1.1.2 picocolors: 1.0.1 vite: 5.3.4(@types/node@22.7.6)(lightningcss@1.26.0)(terser@5.31.1) @@ -23597,6 +23530,16 @@ snapshots: optionalDependencies: vite: 5.2.13(@types/node@22.7.6)(lightningcss@1.26.0)(terser@5.31.1) + vitest-browser-react@0.0.4(@types/react-dom@18.2.24)(@types/react@18.2.74)(@vitest/browser@2.1.0-beta.5(@types/node@22.7.6)(playwright@1.45.2)(typescript@5.0.4)(vitest@2.1.0-beta.5)(webdriverio@8.39.1(encoding@0.1.13)(typescript@5.0.4)))(react-dom@18.2.0(react@18.2.0))(react@18.2.0)(vitest@2.1.0-beta.5(@types/node@22.7.6)(@vitest/browser@2.1.0-beta.5)(lightningcss@1.26.0)(terser@5.31.1)): + dependencies: + '@vitest/browser': 2.1.0-beta.5(@types/node@22.7.6)(playwright@1.45.2)(typescript@5.0.4)(vitest@2.1.0-beta.5)(webdriverio@8.39.1(encoding@0.1.13)(typescript@5.0.4)) + react: 18.2.0 + react-dom: 18.2.0(react@18.2.0) + vitest: 2.1.0-beta.5(@types/node@22.7.6)(@vitest/browser@2.1.0-beta.5)(lightningcss@1.26.0)(terser@5.31.1) + optionalDependencies: + '@types/react': 18.2.74 + '@types/react-dom': 18.2.24 + vitest@1.2.2(@types/node@22.7.6)(@vitest/browser@1.6.0)(lightningcss@1.26.0)(terser@5.31.1): dependencies: '@vitest/expect': 1.2.2