From a22b0b244fbdc28f4bc0f1adfe5aed584aa4be60 Mon Sep 17 00:00:00 2001 From: Alexander Hj <10656981+alexqhj@users.noreply.github.com> Date: Thu, 15 May 2025 08:27:39 +0200 Subject: [PATCH 001/194] Use script.remove instead of removeChild for unity loader hook (#576) --- module/source/hooks/use-unity-loader.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/module/source/hooks/use-unity-loader.ts b/module/source/hooks/use-unity-loader.ts index 8fd574ff..eb2ad0fa 100644 --- a/module/source/hooks/use-unity-loader.ts +++ b/module/source/hooks/use-unity-loader.ts @@ -18,12 +18,12 @@ const useUnityLoader = (unityConfig: UnityConfig): UnityLoaderStatus => { // this scenario, the window is not available. We can't create a Unity // Loader in this case. if (isBrowserEnvironment === false) { - return; + return undefined; } // If the script's source is null, we'll reset the status to idle. if (unityConfig.loaderUrl === null) { setStatus(UnityLoaderStatus.Idle); - return; + return undefined; } /** * Find existing script element by source. It may have been added by @@ -78,7 +78,7 @@ const useUnityLoader = (unityConfig: UnityConfig): UnityLoaderStatus => { if (script !== null) { script.removeEventListener("load", setStateFromEvent); script.removeEventListener("error", setStateFromEvent); - window.document.body.removeChild(script); + script.remove(); } }; }, [unityConfig.loaderUrl]); From c0c58fe3f3a12a8cc1f08d7b2798dc6f63a295a1 Mon Sep 17 00:00:00 2001 From: Jeffrey Lanters Date: Mon, 19 May 2025 10:41:10 +0200 Subject: [PATCH 002/194] Removed deprecated actions --- .github/workflows/validate-module.yml | 6 ------ 1 file changed, 6 deletions(-) diff --git a/.github/workflows/validate-module.yml b/.github/workflows/validate-module.yml index cc8cdb1a..33e3dd30 100644 --- a/.github/workflows/validate-module.yml +++ b/.github/workflows/validate-module.yml @@ -21,12 +21,6 @@ jobs: with: node-version: 16 registry-url: https://registry.npmjs.org - # Cache Node Module Dependencies - - name: Cache Node Module Dependencies - uses: actions/cache@v2 - with: - path: "module/node_modules" - key: nodemodules-${{ runner.os }}-${{ hashFiles('module/package-lock.json') }} # Install Dependencies - name: Install Dependencies working-directory: module From ade588eb3b033f7203a3934ec7b9dccfb44aa685 Mon Sep 17 00:00:00 2001 From: Jeffrey Lanters Date: Mon, 16 Jun 2025 11:35:25 +0200 Subject: [PATCH 003/194] Add autoSyncPersistentDataPath to ConfigurableUnityArguments type --- module/source/types/unity-config.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/module/source/types/unity-config.ts b/module/source/types/unity-config.ts index a4ee8b35..34b01009 100644 --- a/module/source/types/unity-config.ts +++ b/module/source/types/unity-config.ts @@ -19,6 +19,7 @@ type ConfigurableUnityArguments = Pick< | "productVersion" | "webglContextAttributes" | "cacheControl" + | "autoSyncPersistentDataPath" >; /** From 583ef34cd47987099a553ad5e533a61c1008fd93 Mon Sep 17 00:00:00 2001 From: Jeffrey Lanters Date: Mon, 16 Jun 2025 11:35:52 +0200 Subject: [PATCH 004/194] Update RELEASE-NOTES.md to add support for autoSyncPersistentDataPath in Unity configuration --- RELEASE-NOTES.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/RELEASE-NOTES.md b/RELEASE-NOTES.md index c9bc418e..75d15b07 100644 --- a/RELEASE-NOTES.md +++ b/RELEASE-NOTES.md @@ -1 +1 @@ -- Add support for workerUrl (multithreading) [#575][#571] +- Added support for configurating autoSyncPersistentDataPath in the Unity configuration. From 31f37bd1d250c3a3a88ea3869d29a1532948eee4 Mon Sep 17 00:00:00 2001 From: Jeffrey Lanters Date: Mon, 16 Jun 2025 11:36:13 +0200 Subject: [PATCH 005/194] Bump version to 9.9.0 in package.json and package-lock.json --- module/package-lock.json | 2 +- module/package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/module/package-lock.json b/module/package-lock.json index 0f2a70d1..83e3e6d7 100644 --- a/module/package-lock.json +++ b/module/package-lock.json @@ -1,6 +1,6 @@ { "name": "react-unity-webgl", - "version": "9.8.0", + "version": "9.9.0", "lockfileVersion": 2, "requires": true, "packages": { diff --git a/module/package.json b/module/package.json index 95587b90..de46893d 100644 --- a/module/package.json +++ b/module/package.json @@ -1,6 +1,6 @@ { "name": "react-unity-webgl", - "version": "9.8.0", + "version": "9.9.0", "description": "React Unity WebGL provides a modern solution for embedding Unity WebGL builds in your React Application while providing advanced APIs for two way communication and interaction between Unity and React.", "keywords": [ "React", From 9e5ca188023f7d1dbf2018147e4ddee400677c8c Mon Sep 17 00:00:00 2001 From: Jeffrey Lanters Date: Mon, 16 Jun 2025 11:39:21 +0200 Subject: [PATCH 006/194] Update cache action to v4 in workflow files --- .github/workflows/publish-module.yml | 2 +- .github/workflows/validate-documentation.yml | 2 +- .github/workflows/validate-module.yml | 6 ++++++ 3 files changed, 8 insertions(+), 2 deletions(-) diff --git a/.github/workflows/publish-module.yml b/.github/workflows/publish-module.yml index b07ecd3a..b80d72b1 100644 --- a/.github/workflows/publish-module.yml +++ b/.github/workflows/publish-module.yml @@ -23,7 +23,7 @@ jobs: registry-url: https://registry.npmjs.org # Cache Node Module Dependencies - name: Cache Node Module Dependencies - uses: actions/cache@v2 + uses: actions/cache@v4 with: path: "module/node_modules" key: nodemodules-${{ runner.os }}-${{ hashFiles('module/package-lock.json') }} diff --git a/.github/workflows/validate-documentation.yml b/.github/workflows/validate-documentation.yml index 789fb9b2..b7833b5e 100644 --- a/.github/workflows/validate-documentation.yml +++ b/.github/workflows/validate-documentation.yml @@ -25,7 +25,7 @@ jobs: registry-url: https://registry.npmjs.org # Cache Node Module Dependencies - name: Cache Node Module Dependencies - uses: actions/cache@v2 + uses: actions/cache@v4 with: path: "documentation/node_modules" key: nodemodules-${{ runner.os }}-${{ hashFiles('documentation/package-lock.json') }} diff --git a/.github/workflows/validate-module.yml b/.github/workflows/validate-module.yml index 33e3dd30..f3013664 100644 --- a/.github/workflows/validate-module.yml +++ b/.github/workflows/validate-module.yml @@ -21,6 +21,12 @@ jobs: with: node-version: 16 registry-url: https://registry.npmjs.org + # Cache Node Module Dependencies + - name: Cache Node Module Dependencies + uses: actions/cache@v4 + with: + path: "module/node_modules" + key: nodemodules-${{ runner.os }}-${{ hashFiles('module/package-lock.json') }} # Install Dependencies - name: Install Dependencies working-directory: module From 1de544911ec8725aec62b0179a6b5dc947681e58 Mon Sep 17 00:00:00 2001 From: Jeffrey Lanters Date: Tue, 15 Jul 2025 11:53:47 +0200 Subject: [PATCH 007/194] Started reworking module source --- module/source/components/unity-component.ts | 79 ------- module/source/constants/error-messages.ts | 42 ---- .../constants/is-browser-environment.ts | 6 - module/source/enums/unity-loader-status.ts | 26 --- module/source/hooks/use-event-system.ts | 149 ------------ module/source/hooks/use-nullable-state.ts | 14 -- module/source/hooks/use-unity-arguments.ts | 101 -------- module/source/hooks/use-unity-canvas-id.ts | 40 ---- module/source/hooks/use-unity-context.ts | 221 ------------------ module/source/hooks/use-unity-instance.ts | 68 ------ module/source/hooks/use-unity-loader.ts | 89 ------- module/source/types/event-listener.ts | 20 -- module/source/types/event-system-hook.ts | 32 --- .../types/react-unity-event-parameters.ts | 27 --- module/source/types/unity-arguments.ts | 159 ------------- .../source/types/unity-cache-control-mode.ts | 28 --- module/source/types/unity-config.ts | 39 ---- module/source/types/unity-context-hook.ts | 106 --------- .../types/unity-instance-banner-type.ts | 7 - module/source/types/unity-props.ts | 56 ----- module/source/types/unity-provider.ts | 35 --- .../source/types/webgl-context-attributes.ts | 98 -------- 22 files changed, 1442 deletions(-) delete mode 100644 module/source/components/unity-component.ts delete mode 100644 module/source/constants/error-messages.ts delete mode 100644 module/source/constants/is-browser-environment.ts delete mode 100644 module/source/enums/unity-loader-status.ts delete mode 100644 module/source/hooks/use-event-system.ts delete mode 100644 module/source/hooks/use-nullable-state.ts delete mode 100644 module/source/hooks/use-unity-arguments.ts delete mode 100644 module/source/hooks/use-unity-canvas-id.ts delete mode 100644 module/source/hooks/use-unity-context.ts delete mode 100644 module/source/hooks/use-unity-instance.ts delete mode 100644 module/source/hooks/use-unity-loader.ts delete mode 100644 module/source/types/event-listener.ts delete mode 100644 module/source/types/event-system-hook.ts delete mode 100644 module/source/types/react-unity-event-parameters.ts delete mode 100644 module/source/types/unity-arguments.ts delete mode 100644 module/source/types/unity-cache-control-mode.ts delete mode 100644 module/source/types/unity-config.ts delete mode 100644 module/source/types/unity-context-hook.ts delete mode 100644 module/source/types/unity-instance-banner-type.ts delete mode 100644 module/source/types/unity-props.ts delete mode 100644 module/source/types/unity-provider.ts delete mode 100644 module/source/types/webgl-context-attributes.ts diff --git a/module/source/components/unity-component.ts b/module/source/components/unity-component.ts deleted file mode 100644 index 89a33f29..00000000 --- a/module/source/components/unity-component.ts +++ /dev/null @@ -1,79 +0,0 @@ -import { createElement, useImperativeHandle } from "react"; -import { forwardRef, useRef, ForwardRefExoticComponent } from "react"; -import { useUnityCanvasId } from "../hooks/use-unity-canvas-id"; -import { useUnityInstance } from "../hooks/use-unity-instance"; -import { useUnityArguments } from "../hooks/use-unity-arguments"; -import { useUnityLoader } from "../hooks/use-unity-loader"; -import { UnityProps } from "../types/unity-props"; - -/** - * Renders the provided Unity Application. - */ -const Unity: ForwardRefExoticComponent< - UnityProps & React.RefAttributes -> = forwardRef( - /** - * @param unityProps The Unity props provided the the Unity component. - * @param forwardedRef The forwarded ref to the Unity component. - * @returns The Unity canvas renderer. - */ - (unityProps, forwardedRef): JSX.Element => { - /** - * A reference to the HTML Canvas Element. This Canvas Element will eventually - * be passed to the Unity Instance hook which it will use to render the Unity - * application. - */ - const htmlCanvasElementRef = useRef(null); - - /** - * A unique Unity canvas ID. This is used internally by Unity since version - * 2021.2 to identify the canvas element in the DOM. This is not documented in - * the Unity documentation, but it is used in the Unity source code. - */ - const unityCanvasId = useUnityCanvasId(unityProps); - - /** - * The Unity Arguments object which can be passed to the create Unity instance - * method in order to initialize it. These arguments are created based on the - * provided Unity Props which also include the Unity Provider and thus the - * Unity Config. - */ - const unityArguments = useUnityArguments(unityProps); - - /** - * The corresponding Unity Loader will be loaded based on the provided loader - * URL from the Unity Provider's Unity Config. - */ - const unityLoaderStatus = useUnityLoader( - unityProps.unityProvider.unityConfig - ); - - // The Unity Instance is created based on the Unity Arguments. The loader - // status will be used to determine if the Unity instance should be created. - // The Unity is mounted to the Canvas Element. - useUnityInstance( - unityLoaderStatus, - htmlCanvasElementRef.current, - unityArguments, - unityProps.unityProvider - ); - - // The imperative handle is used to pass the Canvas Element to the parent - // component using the forwardRef. - useImperativeHandle( - forwardedRef, - () => htmlCanvasElementRef.current - ); - - // Returns the Unity Canvas Element which will render the Unity application. - return createElement("canvas", { - ref: htmlCanvasElementRef, - id: unityCanvasId, - style: unityProps.style, - className: unityProps.className, - tabIndex: unityProps.tabIndex, - }); - } -); - -export { Unity }; diff --git a/module/source/constants/error-messages.ts b/module/source/constants/error-messages.ts deleted file mode 100644 index 6203e24d..00000000 --- a/module/source/constants/error-messages.ts +++ /dev/null @@ -1,42 +0,0 @@ -const errorMessages = { - /** - * A generic error message when the Unity Instance is not available. - */ - genericNoUnityInstance: "No Unity Instance found.", - /** - * The error message for when no Unity Instance was found while trying to set - * the fullscreen mode. - */ - requestFullscreenNoUnityInstance: - "Unable to Set Fullscreen while Unity is not Instantiated.", - /** - * The error message for when no Unity Instance was found while trying to - * request the pointer lock. - */ - requestPointerLockNoUnityInstanceOrCanvas: - "Unable to Request Pointer Lock while Unity is not Instantiated or the Canvas is not found.", - /** - * The error message for when no Unity Instance was found while trying to send - * a message. - */ - sendMessageNoUnityInstance: - "Unable to Send Message while Unity is not Instantiated.", - /** - * The error message for when no Unity Instance was found while trying to quit - * the Unity Instance. - */ - quitNoUnityInstance: "Unable to Quit Unity while Unity is not Instantiated.", - /** - * The error message for when no Unity Instance or Canvas was found while - * trying to take a screenshot. - */ - screenshotNoUnityInstanceOrCanvas: - "Unable to Take Screenshot while Unity is not Instantiated or Canvas is not available.", - /** - * The error message for when no event listener was found in the event - * system. - */ - noEventListener: "Unable to find Event Listener in Event System for Event", -}; - -export { errorMessages }; diff --git a/module/source/constants/is-browser-environment.ts b/module/source/constants/is-browser-environment.ts deleted file mode 100644 index a49e6478..00000000 --- a/module/source/constants/is-browser-environment.ts +++ /dev/null @@ -1,6 +0,0 @@ -/** - * Defines if the current environment is a browser environment. This is - * determined by checking if the `window` and `document` objects are defined. - */ -export const isBrowserEnvironment = - typeof window !== "undefined" && typeof document !== "undefined"; diff --git a/module/source/enums/unity-loader-status.ts b/module/source/enums/unity-loader-status.ts deleted file mode 100644 index ced0549e..00000000 --- a/module/source/enums/unity-loader-status.ts +++ /dev/null @@ -1,26 +0,0 @@ -/** - * The status of the Unity loader. - */ -enum UnityLoaderStatus { - /** - * The Unity loader is idling and awaiting a resource it be loaded. - */ - Idle = "Idle", - - /** - * The Unity loader is loading a resource. - */ - Loading = "Loading", - - /** - * The Unity loader has loaded a resource. - */ - Loaded = "Loaded", - - /** - * The Unity loader has failed to load a resource. - */ - Error = "Error", -} - -export { UnityLoaderStatus }; diff --git a/module/source/hooks/use-event-system.ts b/module/source/hooks/use-event-system.ts deleted file mode 100644 index fee47903..00000000 --- a/module/source/hooks/use-event-system.ts +++ /dev/null @@ -1,149 +0,0 @@ -import { useCallback, useEffect, useRef } from "react"; -import { errorMessages } from "../constants/error-messages"; -import { isBrowserEnvironment } from "../constants/is-browser-environment"; -import { EventListener } from "../types/event-listener"; -import { EventSystemHook } from "../types/event-system-hook"; -import { ReactUnityEventParameter } from "../types/react-unity-event-parameters"; - -/** - * An array of dispatch event methods from within the mounted event systems. - * This allows an event to be dispatched within all of the event system - * instances. - */ -const mountedEventDispatchers: (( - eventName: string, - ...parameters: ReactUnityEventParameter[] -) => ReactUnityEventParameter)[] = []; - -/** - * Dispatches an event to all mounted event systems. - * @param eventName The name of the event to dispatch. - * @param parameters The parameters to pass to the event listener. - */ -const dispatchReactUnityEvent = ( - eventName: string, - ...parameters: ReactUnityEventParameter[] -): ReactUnityEventParameter => { - // Loops through all of the mounted event systems and dispatches the event. - // In case there are multiple event systems, the return value origin is - // undefined. - let returnValue: ReactUnityEventParameter = undefined; - mountedEventDispatchers.forEach((dispatchEvent) => { - returnValue = dispatchEvent(eventName, ...parameters); - }); - return returnValue; -}; - -if (isBrowserEnvironment === true) { - // It is possible for the application being rendered server side. We'll check - // if the app is running in a browser environment and if so, we'll make the - // dispatch React Unity event function available to the global scope. - window.dispatchReactUnityEvent = dispatchReactUnityEvent; -} - -/** - * Event system for invoking external React Unity events. - * @returns The Event System hook. - */ -const useEventSystem = (): EventSystemHook => { - /** - * An array of all registered event listeners. - */ - const eventListeners = useRef([]); - - /** - * Adds an event listener for external React Unity events. - */ - const addEventListener = useCallback( - /** - * @param eventName The name of the event to listen to. - * @param callback The callback to invoke when the event is fired. - */ - ( - eventName: string, - callback: ( - ...parameters: ReactUnityEventParameter[] - ) => ReactUnityEventParameter - ) => { - // Add the event listener will be added to the array of event listeners. - eventListeners.current = [ - ...eventListeners.current, - { eventName, callback }, - ]; - }, - [eventListeners] - ); - - /** - * Removes an event listener for external React Unity events. - */ - const removeEventListener = useCallback( - /** - * @param eventName The name of the event to remove. - * @param callback The callback to remove. - */ - ( - eventName: string, - callback: ( - ...parameters: ReactUnityEventParameter[] - ) => ReactUnityEventParameter - ) => { - // The event listener will be filtered from the event listeners array - // based on its name and the reference to the callback. - eventListeners.current = eventListeners.current.filter( - (eventListener) => - eventListener.eventName !== eventName && - eventListener.callback !== callback - ); - }, - [eventListeners] - ); - - /** - * Dispatches an event. - */ - const dispatchEvent = useCallback( - /** - * @param eventName The name of the event to dispatch. - * @param parameters The parameters to pass to the event listener. - */ - ( - eventName: string, - ...parameters: ReactUnityEventParameter[] - ): ReactUnityEventParameter => { - // The event listener will be filtered from the event listeners array - // based on its name. - const eventListener = eventListeners.current.find( - (eventListener) => eventListener.eventName === eventName - ); - if (typeof eventListener === "undefined") { - // Guarding the event listener. - console.warn(errorMessages.noEventListener, { eventName }); - return; - } - // The event listener will be invoked with the parameters. - return eventListener.callback(...parameters); - }, - [eventListeners] - ); - - // Effect ensures that the dispatch event function is available to the - // global array of event listeners. This allows the global method to dispatch - // events within the event system hooks. - useEffect(() => { - mountedEventDispatchers.push(dispatchEvent); - return () => { - mountedEventDispatchers.splice( - mountedEventDispatchers.indexOf(dispatchEvent), - 1 - ); - }; - }, [dispatchEvent]); - - return { - addEventListener, - removeEventListener, - }; -}; - -export { useEventSystem }; diff --git a/module/source/hooks/use-nullable-state.ts b/module/source/hooks/use-nullable-state.ts deleted file mode 100644 index cad97be0..00000000 --- a/module/source/hooks/use-nullable-state.ts +++ /dev/null @@ -1,14 +0,0 @@ -import { Dispatch, SetStateAction, useState } from "react"; - -/** - * A hook that creates a nullable state. - * @param initialState Optional initial state, defaults to null. - * @returns a stateful value, and a function to update it. - */ -const useNullableState = ( - initialState?: Type | null | (() => Type | null) -): [Type | null, Dispatch>] => { - return useState(initialState || null); -}; - -export { useNullableState }; diff --git a/module/source/hooks/use-unity-arguments.ts b/module/source/hooks/use-unity-arguments.ts deleted file mode 100644 index 6e080026..00000000 --- a/module/source/hooks/use-unity-arguments.ts +++ /dev/null @@ -1,101 +0,0 @@ -import { useMemo } from "react"; -import { UnityArguments } from "../types/unity-arguments"; -import { UnityProps } from "../types/unity-props"; - -/** - * Creates a memoized Unity Arguments object which can be passed to the Unity - * instance in order to initialize it. - * @param unityProps The Unity props provided the the Unity component. - * @returns The Unity arguments to pass to the Unity instance. - */ -const useUnityArguments = (unityProps: UnityProps): UnityArguments => { - return useMemo( - () => ({ - // Assigns the data URL, framework URL, and code URL to the Unity - // arguments object. - dataUrl: unityProps.unityProvider.unityConfig.dataUrl, - frameworkUrl: unityProps.unityProvider.unityConfig.frameworkUrl, - codeUrl: unityProps.unityProvider.unityConfig.codeUrl, - - // Assigns the optional streaming assets URL, memory URL, symbols URL, - // and worker URL to the Unity arguments object. - streamingAssetsUrl: - unityProps.unityProvider.unityConfig.streamingAssetsUrl, - memoryUrl: unityProps.unityProvider.unityConfig.memoryUrl, - symbolsUrl: unityProps.unityProvider.unityConfig.symbolsUrl, - workerUrl: unityProps.unityProvider.unityConfig.workerUrl, - - // Assigns the optional company name, product name, and product version to - // the Unity arguments object. - companyName: unityProps.unityProvider.unityConfig.companyName, - productName: unityProps.unityProvider.unityConfig.productName, - productVersion: unityProps.unityProvider.unityConfig.productVersion, - - // Assigns the webgl context attributes to the Unity arguments object. - // If the webgl context attributes are not defined via the Unity Props, - // the default value of an empty object will be used. - webglContextAttributes: - unityProps.unityProvider.unityConfig.webglContextAttributes || {}, - - // Assigns the cache control value to the Unity arguments object. If the - // cache control value is not defined via the Unity Props, the default - // value of always `must-revalidate` will be used. - cacheControl: - unityProps.unityProvider.unityConfig.cacheControl || - (() => "must-revalidate"), - - // Assigns the device pixel ratio to the Unity arguments object. If the - // device pixel ratio is not defined via the Unity Props, the default - // value of `1` will be used. - devicePixelRatio: unityProps.devicePixelRatio || 1, - - // Assigns the auto sync persistent data path value to the Unity arguments - // object. If the auto sync persistent data path value is not defined via - // the Unity Props, the default value of `undefined` will be used. - autoSyncPersistentDataPath: unityProps.autoSyncPersistentDataPath, - - // Assigns the match WebGL to canvas size value to the Unity arguments - // object. If the match WebGL to canvas size value is not defined via the - // Unity Props, the default value of `true` will be used. - matchWebGLToCanvasSize: - typeof unityProps.matchWebGLToCanvasSize === "boolean" - ? unityProps.matchWebGLToCanvasSize - : true, - - // Assigns the disabled canvas events to the Unity arguments object. If - // the disabled canvas events are not defined via the Unity Props, the - // default value of `contextmenu` and `dragstart` will be used. - disabledCanvasEvents: unityProps.disabledCanvasEvents || [ - "contextmenu", - "dragstart", - ], - - // Assigns the print hook to the Unity arguments object. This hook will - // be called whenever the Unity instance prints a message. - print: - /** - * Intercept print events in order to catch messages and send them to - * the unity context instead. - * @param message The message to be printed. - */ - (message: string) => { - // TODO -- Re-implement this hook. - }, - - // Assigns the print error hook to the Unity arguments object. This hook - // will be called whenever the Unity instance prints an error. - printErr: - /** - * Intercept print error events in order to catch messages and send them - * to the unity context instead. - * @param error The error to be printed. - */ - (error: string) => { - // TODO -- Re-implement this hook. - }, - }), - [] - ); -}; - -export { useUnityArguments }; diff --git a/module/source/hooks/use-unity-canvas-id.ts b/module/source/hooks/use-unity-canvas-id.ts deleted file mode 100644 index 988cb805..00000000 --- a/module/source/hooks/use-unity-canvas-id.ts +++ /dev/null @@ -1,40 +0,0 @@ -import { useMemo } from "react"; -import { UnityProps } from "../exports"; - -/** - * The canvas count is used to generate a unique Unity canvas ID. - */ -let unityCanvasCount = 0; - -/** - * The prefix used to generate a unique Unity canvas ID. - */ -const unityCanvasIdPrefix = "react-unity-webgl-canvas"; - -/** - * Generates a unique Unity canvas ID. This is used internally by Unity since - * version 2021.2 to identify the canvas element in the DOM. This is not - * documented in the Unity documentation, but it is used in the Unity source - * code. - * @returns A unique identifier for a Unity canvas element. - */ -const useUnityCanvasId = (unityProps: UnityProps): string => { - // If the user has provided a Unity canvas ID, then this value is returned. - // This is useful for when the user wants to use a custom canvas ID. - if (unityProps.id !== undefined) { - return unityProps.id; - } - - /** - * A unique identifier for a Unity canvas element is memorized. - */ - const unityCanvasId = useMemo(() => { - // The Unity canvas ID is generated by concatenating the Unity canvas ID - // prefix with the canvas count. Every time this value is requested, the - // canvas count is incremented. - return [unityCanvasIdPrefix, ++unityCanvasCount].join("-"); - }, []); - return unityCanvasId; -}; - -export { useUnityCanvasId }; diff --git a/module/source/hooks/use-unity-context.ts b/module/source/hooks/use-unity-context.ts deleted file mode 100644 index 36fe560d..00000000 --- a/module/source/hooks/use-unity-context.ts +++ /dev/null @@ -1,221 +0,0 @@ -import { useCallback, useEffect, useRef, useState } from "react"; -import { UnityInstance } from "../../declarations/unity-instance"; -import { errorMessages } from "../constants/error-messages"; -import { ReactUnityEventParameter } from "../types/react-unity-event-parameters"; -import { UnityConfig } from "../types/unity-config"; -import { UnityContextHook } from "../types/unity-context-hook"; -import { UnityProvider } from "../types/unity-provider"; -import { useEventSystem } from "./use-event-system"; -import { useNullableState } from "./use-nullable-state"; - -/** - * Creates a Unity Context hook. - * @param unityConfig The Unity Config on which the Unity Context is based. - * @returns The Unity Context hook. - */ -const useUnityContext = (unityConfig: UnityConfig): UnityContextHook => { - // A reference to the Unity Instance. - const [unityInstance, setUnityInstance] = useNullableState(); - - // The Unity Instance's loading progression represents the percentage of the - // Unity Instance's loading process that has been completed. - const [loadingProgression, setLoadingProgression] = useState(0); - - // Defines whether the Unity Instance has been loaded. - const [isLoaded, setIsLoaded] = useState(false); - - // May contain an error that occurred during the initialisation of the Unity - // Instance. - const [initialisationError, setInitialisationError] = - useNullableState(); - - /** - * The Unity Context's event system stores the event listeners which will - * allow Unity or any global source to invoke events to the React application. - */ - const eventSystem = useEventSystem(); - - /** - * The Unity Context returns a Unity Provider instance. This is an immutable - * object that contains a series of methods and properties that are used to - * alter the Unity Context state externally. - */ - const unityProvider = useRef({ - setLoadingProgression, - setInitialisationError, - setUnityInstance, - setIsLoaded, - unityConfig, - }); - - /** - * Enables or disabled the Fullscreen mode of the Unity Instance. - */ - const requestFullscreen = useCallback( - /** - * @param enabled Defines whether Unity should be in fullscreen. - */ - (enabled: boolean) => { - if (unityInstance === null) { - // Guarding the Unity Instance. - console.warn(errorMessages.requestFullscreenNoUnityInstance); - return; - } - // For undocumented reasons, the fullscreen mode can only be enabled - // with an interger value where the value of "1" enables the fullscreen - // mode and the value of "0" disables the fullscreen mode. - unityInstance.SetFullscreen(enabled === true ? 1 : 0); - }, - [unityInstance] - ); - - /** - * Lets you asynchronously ask for the pointer to be locked on the given Unity - * Application's Canvas Element. - */ - const requestPointerLock = useCallback(() => { - if ( - unityInstance === null || - typeof unityInstance.Module.canvas === "undefined" - ) { - // Guarding the Unity Instance and the canvas. - console.warn(errorMessages.requestPointerLockNoUnityInstanceOrCanvas); - return; - } - // Requesting the pointer lock. - return unityInstance.Module.canvas.requestPointerLock(); - }, [unityInstance]); - - /** - * Sends a message to the UnityInstance to invoke a public method. - */ - const sendMessage = useCallback( - /** - * @param gameObjectName the name of the game object in your Unity scene. - * @param methodName the name of the public method on the game object. - * @param parameter an optional parameter to pass along to the method. - */ - ( - gameObjectName: string, - methodName: string, - parameter?: ReactUnityEventParameter - ) => { - if (unityInstance === null) { - // Guarding the Unity Instance. - console.warn(errorMessages.sendMessageNoUnityInstance); - return; - } - unityInstance.SendMessage(gameObjectName, methodName, parameter); - }, - [unityInstance] - ); - - /** - * Takes a screenshot of the Unity Instance and returns a base64 encoded - * string. - */ - const takeScreenshot = useCallback( - /** - * @param dataType Defines the type of screenshot to take. - * @param quality Defines the quality of the screenshot. - * @returns A base 64 encoded string of the screenshot. - */ - (dataType?: string, quality?: number): string | undefined => { - if ( - unityInstance === null || - typeof unityInstance.Module.canvas === "undefined" - ) { - // Guarding the Unity Instance and the canvas. - console.warn(errorMessages.screenshotNoUnityInstanceOrCanvas); - return; - } - // Takes a screenshot by converting Canvas's render-context's buffer into - // a Data URL of the specified data type and quality. - return unityInstance.Module.canvas.toDataURL(dataType, quality); - }, - [unityInstance] - ); - - /** - * Requests the UnityInstance to be unloaded from memory in order to be - * unmounted from the DOM. - */ - const unload = useCallback( - /** - * @returns A promise that resolves when the UnityInstance has been unloaded. - */ - (): Promise => { - if (unityInstance === null) { - // Guarding the Unity Instance. - console.warn(errorMessages.quitNoUnityInstance); - return Promise.reject(); - } - return unityInstance.Quit(); - }, - [unityInstance] - ); - - /** - * Detaches the Unity Instance from the React DOM, by doing so, the Unity - * Instance can be unloaded from the memory while the Unity component can be - * unmounted safely. - * - * Warning! This is a workaround for the fact that the Unity WebGL instances - * which are build with Unity 2021.2 and newer cannot be unmounted before the - * Unity Instance is unloaded. - * @see https://github.com/jeffreylanters/react-unity-webgl/issues/22 - */ - const UNSAFE__detachAndUnloadImmediate = useCallback( - /** - * @returns A promise that resolves when the UnityInstance has been unloaded. - */ - async (): Promise => { - if ( - unityInstance === null || - typeof unityInstance.Module.canvas === "undefined" - ) { - // Guarding the Unity Instance. - console.warn(errorMessages.genericNoUnityInstance); - return Promise.reject(); - } - // Re-attaches the canvas to the body element of the document. This way it - // wont be removed from the DOM when the component is unmounted. Then the - // canvas will be hidden while it is being unloaded. - const canvas = unityInstance.Module.canvas as HTMLCanvasElement; - document.body.appendChild(canvas); - canvas.style.display = "none"; - // Unloads the Unity Instance. - await unload(); - // Eventually the canvas will be removed from the DOM. This has to be done - // manually since the canvas is no longer controlled by the React DOM. - canvas.remove(); - }, - [unityInstance] - ); - - // Effect invoked when the loading progression changes. When the loading - // progression is equal to or more than 1, the Unity Instance is considered - // loaded. This will update the isLoaded state. - useEffect(() => { - setIsLoaded(loadingProgression === 1); - }, [loadingProgression]); - - // Returns the Unity Context Hook. - return { - unityProvider: unityProvider.current, - loadingProgression, - initialisationError, - isLoaded, - UNSAFE__unityInstance: unityInstance, - requestFullscreen, - requestPointerLock, - sendMessage, - takeScreenshot, - unload, - UNSAFE__detachAndUnloadImmediate, - addEventListener: eventSystem.addEventListener, - removeEventListener: eventSystem.removeEventListener, - }; -}; - -export { useUnityContext }; diff --git a/module/source/hooks/use-unity-instance.ts b/module/source/hooks/use-unity-instance.ts deleted file mode 100644 index ca325fea..00000000 --- a/module/source/hooks/use-unity-instance.ts +++ /dev/null @@ -1,68 +0,0 @@ -import { useEffect } from "react"; -import { UnityArguments } from "../types/unity-arguments"; -import { UnityProvider } from "../types/unity-provider"; -import { UnityLoaderStatus } from "../enums/unity-loader-status"; -import { isBrowserEnvironment } from "../constants/is-browser-environment"; - -/** - * Creates a Unity Instance. - * @param unityLoaderStatus The loader status. - * @param htmlCanvasElement A reference to the html canvas element. - * @param unityArguments The Unity instance arguments. - * @param unityProvider The Unity provider. - * @returns the Unity Instance among with the status of the Unity Instance. - */ -const useUnityInstance = ( - unityLoaderStatus: UnityLoaderStatus, - htmlCanvasElement: HTMLCanvasElement | null, - unityArguments: UnityArguments, - unityProvider: UnityProvider -): void => { - // Effect invoked when the Unity Loader status or canvas reference changes. - useEffect(() => { - (async () => { - // It is possible for the application being rendered server side. In - // this scenario, the window is not available. We can't create the - // Unity Instance in this case. - if (isBrowserEnvironment === false) { - return; - } - if ( - unityLoaderStatus !== UnityLoaderStatus.Loaded || - htmlCanvasElement === null - ) { - // If the loader is not loaded, or the canvas is not available, - // we can't create the Unity instance yet. In case of a fresh load, - // we'll clear the initialisation error as well. - unityProvider.setUnityInstance(null); - unityProvider.setInitialisationError(null); - return; - } - // Creates the Unity Instance, this method is made available globally by - // the Unity Loader. - try { - /** - * The internal Unity Instance which has been initialized usign the - * create Unity Instance method exposed by the Unity Loader. - */ - const unityInstance = await window.createUnityInstance( - htmlCanvasElement, - unityArguments, - unityProvider.setLoadingProgression - ); - // When the Unity Instance is created, its reference is stored in the - // state while the error state is cleared. - unityProvider.setUnityInstance(unityInstance); - unityProvider.setInitialisationError(null); - } catch (error: any) { - // When the Unity Instance catches due to a fail during the creation, - // the Unity Instnace reference will be cleared while the error is - // placed into the state. - unityProvider.setUnityInstance(null); - unityProvider.setInitialisationError(error); - } - })(); - }, [unityLoaderStatus, htmlCanvasElement, unityArguments, unityProvider]); -}; - -export { useUnityInstance }; diff --git a/module/source/hooks/use-unity-loader.ts b/module/source/hooks/use-unity-loader.ts deleted file mode 100644 index eb2ad0fa..00000000 --- a/module/source/hooks/use-unity-loader.ts +++ /dev/null @@ -1,89 +0,0 @@ -import { useEffect, useState } from "react"; -import { isBrowserEnvironment } from "../constants/is-browser-environment"; -import { UnityLoaderStatus } from "../enums/unity-loader-status"; -import { UnityConfig } from "../exports"; - -/** - * Hook to embed a Unity Loader script. - * @param source The source of the unity loader. - * @returns a hook that returns the status of the loader. - */ -const useUnityLoader = (unityConfig: UnityConfig): UnityLoaderStatus => { - const [status, setStatus] = useState( - UnityLoaderStatus.Loading - ); - // Effect hook will be invoked when the source changes. - useEffect(() => { - // It is possible for the application being rendered server side. In - // this scenario, the window is not available. We can't create a Unity - // Loader in this case. - if (isBrowserEnvironment === false) { - return undefined; - } - // If the script's source is null, we'll reset the status to idle. - if (unityConfig.loaderUrl === null) { - setStatus(UnityLoaderStatus.Idle); - return undefined; - } - /** - * Find existing script element by source. It may have been added by - * another instance of this hook. - */ - let script: HTMLScriptElement | null = window.document.querySelector( - `script[src="${unityConfig.loaderUrl}"]` - ); - // If there wan't another instance of this script, we're going to create a - // new one with the provided source. - if (script === null) { - script = window.document.createElement("script"); - script.type = "text/javascript"; - script.src = unityConfig.loaderUrl; - script.async = true; - script.setAttribute("data-status", "loading"); - // Add script to window.document body. - window.document.body.appendChild(script); - // Store status in attribute on script. This can be read by other - // instances of this hook. - script.addEventListener("load", () => - script?.setAttribute("data-status", "loaded") - ); - script.addEventListener("error", () => - script?.setAttribute("data-status", "error") - ); - } else { - // If there already was a script with the same source, grab its existing - // script status from attribute and set to state. - setStatus( - script.getAttribute("data-status") === "loaded" - ? UnityLoaderStatus.Loaded - : UnityLoaderStatus.Error - ); - } - /** - * Script event handler to update status in state. Even if the script - * already exists we still need to add event handlers to update the state - * for this hook instance. - * @param event The event that was triggered. - */ - const setStateFromEvent = (event: Event) => - setStatus( - event.type === "load" - ? UnityLoaderStatus.Loaded - : UnityLoaderStatus.Error - ); - script.addEventListener("load", setStateFromEvent); - script.addEventListener("error", setStateFromEvent); - // Remove event listeners on cleanup. - return () => { - if (script !== null) { - script.removeEventListener("load", setStateFromEvent); - script.removeEventListener("error", setStateFromEvent); - script.remove(); - } - }; - }, [unityConfig.loaderUrl]); - - return status; -}; - -export { useUnityLoader }; diff --git a/module/source/types/event-listener.ts b/module/source/types/event-listener.ts deleted file mode 100644 index d6cafba3..00000000 --- a/module/source/types/event-listener.ts +++ /dev/null @@ -1,20 +0,0 @@ -import { ReactUnityEventParameter } from "./react-unity-event-parameters"; - -/** - * An event listener. - */ -type EventListener = { - /** - * The name of the event to listen to. - */ - eventName: string; - - /** - * The callback to invoke when the event is fired. - */ - callback: ( - ...parameters: ReactUnityEventParameter[] - ) => ReactUnityEventParameter; -}; - -export type { EventListener }; diff --git a/module/source/types/event-system-hook.ts b/module/source/types/event-system-hook.ts deleted file mode 100644 index 1311386a..00000000 --- a/module/source/types/event-system-hook.ts +++ /dev/null @@ -1,32 +0,0 @@ -import { ReactUnityEventParameter } from "./react-unity-event-parameters"; - -/** - * Event system for external React Unity events. - */ -type EventSystemHook = { - /** - * Adds an event listener for external React Unity events. - * @param eventName The name of the event to listen to. - * @param callback The callback to invoke when the event is fired. - */ - readonly addEventListener: ( - eventName: string, - callback: ( - ...parameters: ReactUnityEventParameter[] - ) => ReactUnityEventParameter - ) => void; - - /** - * Removes an event listener for external React Unity events. - * @param eventName The name of the event to remove. - * @param callback The callback to remove. - */ - readonly removeEventListener: ( - eventName: string, - callback: ( - ...parameters: ReactUnityEventParameter[] - ) => ReactUnityEventParameter - ) => void; -}; - -export type { EventSystemHook }; diff --git a/module/source/types/react-unity-event-parameters.ts b/module/source/types/react-unity-event-parameters.ts deleted file mode 100644 index 66014b81..00000000 --- a/module/source/types/react-unity-event-parameters.ts +++ /dev/null @@ -1,27 +0,0 @@ -/** - * Type definition for Unity event argument types. These are the supported - * types for the React Unity WebGL event system which can be used to dispatch - * events to the React Application from the Unity Instance. - * - * Simple numeric types can be passed to JavaScript in function parameters - * without requiring any conversion. Other data types will be passed as a - * pointer in the emscripten heap (which is really just a big array in - * JavaScript). For strings, you can use the Pointerstringify helper function - * to convert to a JavaScript string. - * - * To return a string value you need to call _malloc to allocate some memory and - * the writeStringToMemory helper function to write a JavaScript string to it. - * If the string is a return value, then the il2cpp runtime will take care of - * freeing the memory for you. - * - * For arrays of primitive types, emscripten provides different ArrayBufferViews - * into it’s heap for different sizes of integer, unsigned integer or floating - * point representations of memory: HEAP8, HEAPU8, HEAP16, HEAPU16, HEAP32, - * HEAPU32, HEAPF32, HEAPF64. To access a texture in WebGL, emscripten provides - * the GL.textures array which maps native texture IDs from Unity to WebGL - * texture objects. WebGL functions can be called on emscripten’s WebGL context, - * GLctx. - */ -type ReactUnityEventParameter = string | number | undefined | void; - -export type { ReactUnityEventParameter }; diff --git a/module/source/types/unity-arguments.ts b/module/source/types/unity-arguments.ts deleted file mode 100644 index 57e76125..00000000 --- a/module/source/types/unity-arguments.ts +++ /dev/null @@ -1,159 +0,0 @@ -import { UnityCacheControlMode } from "./unity-cache-control-mode"; -import { UnityInstanceBannerType } from "./unity-instance-banner-type"; -import { WebGLContextAttributes } from "./webgl-context-attributes"; - -/** - * The Unity Arguments can be passed to a create Unity instance method in order - * to initialize it. These arguments are created based on the provided Unity - * Props which also include the Unity Provider and thus the Unity Config. - */ -type UnityArguments = { - /** - * The url to the build data file generated by Unity. When using a relative url, - * keep in mind this is relative from the path where your html file is served. - * It is also possible to use an absolute url, for example when using a CDN. - */ - readonly dataUrl: string; - - /** - * The url to the framework file generated by Unity. When using a relative url, - * keep in mind this is relative from the path where your html file is served. - * It is also possible to use an absolute url, for example when using a CDN. - */ - readonly frameworkUrl: string; - - /** - * The url to the unity code file generated by Unity. When using a relative url, - * keep in mind this is relative from the path where your html file is served. - * It is also possible to use an absolute url, for example when using a CDN. - */ - readonly codeUrl: string; - - /** - * The url to the web worker file generated by Unity. When using a relative url, - * keep in mind this is relative from the path where your html file is served. - * It is also possible to use an absolute url, for example when using a CDN. - */ - readonly workerUrl?: string; - - /** - * The url where the streaming assets can be found. When using a relative url, - * keep in mind this is relative from the path where your html file is served. - * It is also possible to use an absolute url, for example when using a CDN. - */ - readonly streamingAssetsUrl?: string; - - /** - * The url to the framework file generated by Unity. When using a relative url, - * keep in mind this is relative from the path where your html file is served. - * It is also possible to use an absolute url, for example when using a CDN. - * This is set to the memory file when memory is stored in an external file, - * otherwise it is set to an empty string. - */ - readonly memoryUrl?: string; - - /** - * The url to the unity code file generated by Unity. When using a relative - * url, keep in mind this is relative from the path where your html file is - * served. It is also possible to use an absolute url, for example when using - * a CDN. This is set to the JSON file containing debug symbols when the - * current build is using debug symbols, otherwise it is set to an empty - * string. - */ - readonly symbolsUrl?: string; - - /** - * The application's company name. This argument is treated as meta data - * which will be provided to the Unity Instance. - */ - readonly companyName?: string; - - /** - * The application's product name. This argument is treated as meta data - * which will be provided to the Unity Instance. - */ - readonly productName?: string; - - /** - * The application's product version. This argument is treated as meta data - * which will be provided to the Unity Instance. - */ - readonly productVersion?: string; - - /** - * The Canvas can appear too blurry on retina screens. The devicePixelRatio - * determines how much extra pixel density should be added to allow for a - * sharper image. - * @see https://developer.mozilla.org/en-US/docs/Web/API/Window/devicePixelRatio - */ - readonly devicePixelRatio?: number; - - /** - * If set to true, all file writes inside the Unity Application - * persistentDataPath directory automatically persist so that the contents are - * remembered when the user revisits the website the next time. If unset (or - * set to false), you must manually sync file modifications inside the - * Application persistentDataPath directory by calling the - * JS_FileSystem_Sync() JavaScript function. - */ - readonly autoSyncPersistentDataPath?: boolean; - - /** - * When disabling the match WebGL to canvas size flag, the canvas allows for - * client side customization of the WebGL canvas target size instead of - * requiring it to always match 1:1 with the High DPI CSS size of the canvas. - * Supported since Unity 2021.1b - * @see https://issuetracker.unity3d.com/issues/webgl-builds-dont-allow-separate-control-on-canvas-render-buffer-size - */ - readonly matchWebGLToCanvasSize?: boolean; - - /** - * This object allow you to configure WebGLRenderingContext creation options - * which will be pass additional context attributes to the Unity canvas. - * @see https://developer.mozilla.org/en-US/docs/Web/API/WebGLRenderingContext - */ - readonly webglContextAttributes?: WebGLContextAttributes; - - /** - * An array of strings containing the names of the events that should be - * disabled on the canvas. This can be useful when you want to allow the user - * to interact with the canvas, but not with the Unity WebGL canvas. The - * default disabled events are `contextmenu` and `dragstart`. - */ - readonly disabledCanvasEvents?: (keyof GlobalEventHandlersEventMap)[]; - - /** - * By default, the WebGL Cache stores the asset data file .data and - * AssetBundle files .bundle, and revalidates them before loading them from - * the cache. You can change this behavior by overriding the default - * caching behavior. This argument is treated as meta data which will be - * provided to the Unity Instance. - */ - readonly cacheControl?: (url: string) => UnityCacheControlMode; - - /** - * Add an event listener using this function to receive non-critical warnings - * and error messages from the Unity Instance. - */ - readonly showBanner?: ( - message: string, - type?: UnityInstanceBannerType - ) => void; - - /** - * When assigned this method will intercept all incomming messages from the - * Unity Module into the console. These messages will contain both of the - * internal information messages as well as the debuggers log messages. - */ - readonly print?: (message: string) => void; - - /** - * When assigned this method will intercept all incomming error logs from the - * Unity Module into the console. These messages will contain both of the - * runtime problems as well as the jslib and javascript errors thrown by the - * Unity Instance. - */ - readonly printErr?: (message: string) => void; -}; - -export type { UnityArguments }; diff --git a/module/source/types/unity-cache-control-mode.ts b/module/source/types/unity-cache-control-mode.ts deleted file mode 100644 index de82fbf8..00000000 --- a/module/source/types/unity-cache-control-mode.ts +++ /dev/null @@ -1,28 +0,0 @@ -/** - * The cache control mode determines how the Unity should cache the resource. - * - `must-revalidate`: The cache returns to an enabled state and the file is - * revalidated before being loaded from the cache. - * - `immutable`: the cache is enabled and the file is loaded from the cache - * without revalidation. - * - `no-store`: The cache is disabled. - */ -type UnityCacheControlMode = - /** - * The cache returns to an enabled state and the file is revalidated before - * being loaded from the cache. - */ - | "must-revalidate" - /** - * the cache is enabled and the file is loaded from the cache without revalidation. - */ - | "immutable" - /** - * The cache is disabled. - */ - | "no-store" - /** - * Fallback for when the cache control mode is not recognized. - */ - | string; - -export type { UnityCacheControlMode }; diff --git a/module/source/types/unity-config.ts b/module/source/types/unity-config.ts deleted file mode 100644 index 34b01009..00000000 --- a/module/source/types/unity-config.ts +++ /dev/null @@ -1,39 +0,0 @@ -import { UnityArguments } from "./unity-arguments"; - -/** - * Most of the Unity Config's properties are also part of the Unity Arguments. - * This type is used to pick the properties that are configurable from the - * Unity Arguments. - */ -type ConfigurableUnityArguments = Pick< - UnityArguments, - | "dataUrl" - | "frameworkUrl" - | "codeUrl" - | "workerUrl" - | "streamingAssetsUrl" - | "memoryUrl" - | "symbolsUrl" - | "companyName" - | "productName" - | "productVersion" - | "webglContextAttributes" - | "cacheControl" - | "autoSyncPersistentDataPath" ->; - -/** - * The Unity config is provided when instantiating a Unity context. This config - * will eventually be used to create the Unity Arguments which will be passed - * to the create Unity instance method in order to initialize it. - */ -type UnityConfig = ConfigurableUnityArguments & { - /** - * The url to the build json file generated by Unity. When using a relative url, - * keep in mind this is relative from the path where your html file is served. - * It is also possible to use an absolute url, for example when using a CDN. - */ - readonly loaderUrl: string; -}; - -export type { UnityConfig }; diff --git a/module/source/types/unity-context-hook.ts b/module/source/types/unity-context-hook.ts deleted file mode 100644 index d7bf2abd..00000000 --- a/module/source/types/unity-context-hook.ts +++ /dev/null @@ -1,106 +0,0 @@ -import { UnityProvider } from "./unity-provider"; -import { EventSystemHook } from "./event-system-hook"; -import { ReactUnityEventParameter } from "./react-unity-event-parameters"; -import { UnityInstance } from "../../declarations/unity-instance"; - -/** - * The Unity Context hook. - */ -type UnityContextHook = EventSystemHook & { - /** - * The Unity Context returns a Unity Provider instance. This immutable object - * should be passed onto a Unity Component in order to be able to access the - * Unity Context's state. - */ - readonly unityProvider: UnityProvider; - - /** - * The Unity Instance's loading progression represents the percentage of the - * Unity Instance's loading process that has been completed. - */ - readonly loadingProgression: number; - - /** - * Defines whether the Unity Instance has been loaded. - */ - readonly isLoaded: boolean; - - /** - * May contain an error that occurred during the initialisation of the Unity - * Instance. - */ - readonly initialisationError: Error | null; - - /** - * A reference to the internal Unity Instance. This Unity Instance is the - * object that is exposed by the Unity Loader is meant to be used only - * internally by the module. In the event that you need to access the Unity - * Instance when for example using a third-party library, that requires access - * to the Unity Instance, you can use this variable. - * - * Warning! Please make sure that any changes made to, or events bound to the - * Unity Instance are not reflected inside of the module. This could lead to - * unexpected behaviour. - */ - readonly UNSAFE__unityInstance: UnityInstance | null; - - /** - * Enables or disabled the Fullscreen mode of the Unity Instance. - * @param enabled Defines whether Unity should be in fullscreen. - */ - readonly requestFullscreen: (enabled: boolean) => void; - - /** - * Sends a message to the UnityInstance to invoke a public method. - * @param gameObjectName the name of the game object in your Unity scene. - * @param methodName the name of the public method on the game object. - * @param parameter an optional parameter to pass along to the method. - */ - readonly sendMessage: ( - gameObjectName: string, - methodName: string, - parameter?: ReactUnityEventParameter - ) => void; - - /** - * Takes a screenshot of the Unity Instance and returns a base64 encoded - * string. - * @param type Defines the type of screenshot to take. - * @param quality Defines the quality of the screenshot. - * @returns A base 64 encoded string of the screenshot. - */ - readonly takeScreenshot: ( - dataType?: string, - quality?: number - ) => string | undefined; - - /** - * Lets you asynchronously ask for the pointer to be locked on the given Unity - * Application's Canvas Element. To track the success or failure of the - * request, it is necessary to listen for the pointerlockchange and - * pointerlockerror events at the Document level. - */ - readonly requestPointerLock: () => void; - - /** - * Requests the UnityInstance to be unloaded from memory in order to be - * unmounted from the DOM. - * @returns A promise that resolves when the UnityInstance has been unloaded. - */ - readonly unload: () => Promise; - - /** - * Detaches the Unity Instance from the React DOM, by doing so, the Unity - * Instance can be unloaded from the memory while the Unity component can be - * unmounted safely. - * - * Warning! This is a workaround for the fact that the Unity WebGL instances - * which are build with Unity 2021.2 and newer cannot be unmounted before the - * Unity Instance is unloaded. - * @see https://github.com/jeffreylanters/react-unity-webgl/issues/22 - * @returns A promise that resolves when the UnityInstance has been detached. - */ - readonly UNSAFE__detachAndUnloadImmediate: () => Promise; -}; - -export type { UnityContextHook }; diff --git a/module/source/types/unity-instance-banner-type.ts b/module/source/types/unity-instance-banner-type.ts deleted file mode 100644 index d5df52da..00000000 --- a/module/source/types/unity-instance-banner-type.ts +++ /dev/null @@ -1,7 +0,0 @@ -/** - * Banners can be used to display non-critical warnings and error messages from - * the Unity Instance. - */ -type UnityInstanceBannerType = "error" | "warning"; - -export type { UnityInstanceBannerType }; diff --git a/module/source/types/unity-props.ts b/module/source/types/unity-props.ts deleted file mode 100644 index 18f8f188..00000000 --- a/module/source/types/unity-props.ts +++ /dev/null @@ -1,56 +0,0 @@ -import { CSSProperties } from "react"; -import { UnityProvider } from "./unity-provider"; -import { UnityArguments } from "./unity-arguments"; - -/** - * Some of the Unity Props' properties are also part of the Unity Arguments. - * This type is used to pick the properties that are configurable from the - * Unity Arguments. - */ -type ConfigurableUnityArguments = Pick< - UnityArguments, - | "devicePixelRatio" - | "matchWebGLToCanvasSize" - | "disabledCanvasEvents" - | "autoSyncPersistentDataPath" ->; - -/** - * The Unity component's props. - */ -type UnityProps = ConfigurableUnityArguments & { - /** - * The Provider of the Unity Context which should be rendered be the Unity - * Component. - */ - readonly unityProvider: UnityProvider; - - /** - * The Class Name will be applied to the Canvas. - */ - readonly className?: string; - - /** - * The styles will be applied to the Canvas. - */ - readonly style?: CSSProperties; - - /** - * The tabIndex of the element. Mitigates the issue that once WebGL is loaded, - * the keyboard is captured and HTML inputs are not reacting to keyboard - * strokes anymore. - * @see https://stackoverflow.com/a/60854680 - */ - readonly tabIndex?: number; - - /** - * The ID of the canvas element. If not provided, a unique ID will be - * generated. This is useful for when the user wants to use a custom canvas - * ID. IDs are used internally by Unity since version 2021.2 to identify the - * canvas element in the DOM. This is not documented in the Unity - * documentation, but it is used in the Unity source code. - */ - readonly id?: string; -}; - -export type { UnityProps }; diff --git a/module/source/types/unity-provider.ts b/module/source/types/unity-provider.ts deleted file mode 100644 index 333a110e..00000000 --- a/module/source/types/unity-provider.ts +++ /dev/null @@ -1,35 +0,0 @@ -import { UnityInstance } from "../../declarations/unity-instance"; -import { UnityConfig } from "./unity-config"; - -/** - * The Unity Provider is a statefull object that contains a series of methods - * and properties that are used to alter the Unity Context state. - */ -type UnityProvider = { - /** - * Sets the Unity Context's loading progression. - */ - readonly setLoadingProgression: (loadingProgression: number) => void; - - /** - * Sets the Unity Context's initialisation error. - */ - readonly setInitialisationError: (error: Error | null) => void; - - /** - * Sets te Unity Context's loaded state. - */ - readonly setIsLoaded: (isLoaded: boolean) => void; - - /** - * Sets the Unity Context's Unity Instance. - */ - readonly setUnityInstance: (unityInstance: UnityInstance | null) => void; - - /** - * The Unity Context's Unity Config. - */ - readonly unityConfig: UnityConfig; -}; - -export type { UnityProvider }; diff --git a/module/source/types/webgl-context-attributes.ts b/module/source/types/webgl-context-attributes.ts deleted file mode 100644 index 91348730..00000000 --- a/module/source/types/webgl-context-attributes.ts +++ /dev/null @@ -1,98 +0,0 @@ -/** - * WebGLContextAttributes object that contains the actual context parameters. - * @see https://developer.mozilla.org/en-US/docs/Web/API/WebGLRenderingContext/getContextAttributes - */ -type WebGLContextAttributes = { - /** - * If set to true, the context will have an alpha (transparency) channel. - * @default true - */ - readonly alpha?: boolean; - - /** - * If set to true, the context will attempt to perform antialiased rendering - * if possible. - * @default true - */ - readonly antialias?: boolean; - - /** - * If set to true, the context will have a 16 bit depth buffer. Defaults to - * true. Use gl.enable(DEPTH_TEST) to enable the depth test and - * gl.depthFunc(), gl.depthMask(), and gl.depthRange() to configure the depth - * test. - * @default true - */ - readonly depth?: boolean; - - /** - * If the value is true, context creation will fail if the implementation - * determines that the performance of the created WebGL context would be - * dramatically lower than that of a native application making equivalent - * OpenGL calls. This could happen for a number of reasons, including an - * implementation might switch to a software rasterizer if the user's GPU - * driver is known to be unstable. And an implementation might require reading - * back the framebuffer from GPU memory to system memory before compositing it - * with the rest of the page, significantly reducing performance. - * @default false - */ - readonly failIfMajorPerformanceCaveat?: boolean; - - /** - * Provides a hint to the user agent indicating what configuration of GPU is - * suitable for this WebGL context. This may influence which GPU is used in a - * system with multiple GPUs. For example, a dual-GPU system might have one - * GPU that consumes less power at the expense of rendering performance. - * Note that this property is only a hint and a WebGL implementation may - * choose to ignore it. WebGL implementations use context lost and restored - * events to regulate power and memory consumption, regardless of the value of - * this attribute. Accepts the following values: - * 0: Default - * 1: Low Power - * 2: High Performance - * @default 0 - */ - readonly powerPreference?: 0 | 1 | 2; - - /** - * If set to true, the color channels in the framebuffer will be stored - * premultipled by the alpha channel to improve performance. - * @default true - */ - readonly premultipliedAlpha?: boolean; - - /** - * If set to false, the buffer will be cleared after rendering. If you wish to - * use canvas.toDataURL(), you will either need to draw to the canvas - * immediately before calling toDataURL(), or set preserveDrawingBuffer to - * true to keep the buffer available after the browser has displayed the - * buffer (at the cost of increased memory use). - * @default false - */ - readonly preserveDrawingBuffer?: boolean; - - /** - * Stenciling enables and disables drawing on a per-pixel basis. It is - * typically used in multipass rendering to achieve special effects. - * @default false - */ - readonly stencil?: boolean; - - /** - * If set to true, the context will have an 8 bit stencil buffer. Defaults to - * false. Use gl.enable(STENCIL_TEST) to enable depth test and - * gl.stencilFunc(), gl.stencilFuncSeparate(), gl.stencilMask(), - * gl.stencilMaskSeparate(), gl.stencilOp(), and gl.stencilOpSeparate() - * to configure the stencil test. - * @default false - */ - readonly desynchronized?: boolean; - - /** - * xrCompatible is a boolean that indicates whether the context is compatible. - * @default false - */ - readonly xrCompatible?: boolean; -}; - -export type { WebGLContextAttributes }; From af7320de8847e79b7c67252e26917f0d0105a76e Mon Sep 17 00:00:00 2001 From: Jeffrey Lanters Date: Tue, 15 Jul 2025 11:54:11 +0200 Subject: [PATCH 008/194] Initial Unity component --- module/source/components/unity.ts | 56 +++++++++++++++++++++++++++++++ 1 file changed, 56 insertions(+) create mode 100644 module/source/components/unity.ts diff --git a/module/source/components/unity.ts b/module/source/components/unity.ts new file mode 100644 index 00000000..007df00e --- /dev/null +++ b/module/source/components/unity.ts @@ -0,0 +1,56 @@ +/* eslint-disable @typescript-eslint/no-explicit-any */ +import { useState, useEffect, createElement } from "react"; + +let canvasCounter = 0; + +export const Unity = () => { + const [canvasRef, setCanvasRef] = useState(null); + const [unityInstance, setUnityInstance] = useState(null); + const [canvasId, setCanvasId] = useState("react-unity-webgl"); + + useEffect(() => { + const initializeUnity = async () => { + if (!canvasRef || unityInstance) { + return; + } + + setCanvasId(`react-unity-webgl-${++canvasCounter}`); + + const unityConfig = { + dataUrl: "/unity-build/unity.data", + frameworkUrl: "/unity-build/unity.framework.js", + codeUrl: "/unity-build/unity.wasm", + }; + + setUnityInstance( + await window.createUnityInstance(canvasRef, unityConfig) + ); + }; + + const detachUnity = async () => { + if (!unityInstance || !canvasRef) { + return; + } + + const cleanupCanvasRef = document.createElement("canvas"); + cleanupCanvasRef.id = canvasRef.id; + cleanupCanvasRef.setAttribute("react-unity-webgl-role", "cleanup"); + document.body.appendChild(cleanupCanvasRef); + unityInstance.Module.canvas = cleanupCanvasRef; + setUnityInstance(null); + await unityInstance.Quit(); + document.body.removeChild(cleanupCanvasRef); + }; + + initializeUnity(); + + return () => { + detachUnity(); + }; + }, [canvasRef, unityInstance]); + + return createElement("canvas", { + ref: setCanvasRef, + id: canvasId, + }); +}; From 21255e051f3c0e71ce5b7586fd5a6f394f78d5f2 Mon Sep 17 00:00:00 2001 From: Jeffrey Lanters Date: Tue, 15 Jul 2025 11:54:21 +0200 Subject: [PATCH 009/194] Removed unused exports --- module/source/exports.ts | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/module/source/exports.ts b/module/source/exports.ts index 5661b2ee..38c0bf9f 100644 --- a/module/source/exports.ts +++ b/module/source/exports.ts @@ -1,8 +1,3 @@ -import { Unity } from "./components/unity-component"; -import { useUnityContext } from "./hooks/use-unity-context"; -import { UnityConfig } from "./types/unity-config"; -import { UnityProps } from "./types/unity-props"; -import { WebGLContextAttributes } from "./types/webgl-context-attributes"; +import { Unity } from "./components/unity"; -export { Unity, useUnityContext }; -export type { UnityConfig, UnityProps, WebGLContextAttributes }; +export { Unity }; From 2177d85ef444e3b40fa4fc787f6fe45cd674ebfd Mon Sep 17 00:00:00 2001 From: Jeffrey Lanters Date: Tue, 15 Jul 2025 11:54:25 +0200 Subject: [PATCH 010/194] Updated packages --- module/package-lock.json | 4 ++-- module/package.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/module/package-lock.json b/module/package-lock.json index 83e3e6d7..0b60e2a9 100644 --- a/module/package-lock.json +++ b/module/package-lock.json @@ -1,12 +1,12 @@ { "name": "react-unity-webgl", - "version": "9.9.0", + "version": "10.0.0", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "react-unity-webgl", - "version": "9.8.0", + "version": "10.0.0", "funding": [ { "type": "github", diff --git a/module/package.json b/module/package.json index de46893d..3951db42 100644 --- a/module/package.json +++ b/module/package.json @@ -1,6 +1,6 @@ { "name": "react-unity-webgl", - "version": "9.9.0", + "version": "10.0.0", "description": "React Unity WebGL provides a modern solution for embedding Unity WebGL builds in your React Application while providing advanced APIs for two way communication and interaction between Unity and React.", "keywords": [ "React", From 49c3acdf27b1adc81d5feaee65d7d98d6854575b Mon Sep 17 00:00:00 2001 From: Jeffrey Lanters Date: Tue, 15 Jul 2025 15:26:56 +0200 Subject: [PATCH 011/194] Fix import path for UnityInstance in global type declarations --- module/declarations/global.d.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/module/declarations/global.d.ts b/module/declarations/global.d.ts index 3904f135..8946d386 100644 --- a/module/declarations/global.d.ts +++ b/module/declarations/global.d.ts @@ -1,6 +1,6 @@ import { ReactUnityEventParameter } from "../source/types/react-unity-event-parameters"; import { UnityArguments } from "../source/types/unity-arguments"; -import { UnityInstance } from "./unity-instance"; +import { UnityInstance } from "../source/types/unity-instance"; /** * Type declaration for global types. From c18e9032f4b6604cca01a4cecff63ff06bc41d77 Mon Sep 17 00:00:00 2001 From: Jeffrey Lanters Date: Tue, 15 Jul 2025 15:27:00 +0200 Subject: [PATCH 012/194] Remove unused type declarations for UnityBooleanLike, UnityInstance, and UnityModule --- module/declarations/unity-boolean-like.d.ts | 13 ------- module/declarations/unity-instance.d.ts | 40 --------------------- module/declarations/unity-module.d.ts | 29 --------------- 3 files changed, 82 deletions(-) delete mode 100644 module/declarations/unity-boolean-like.d.ts delete mode 100644 module/declarations/unity-instance.d.ts delete mode 100644 module/declarations/unity-module.d.ts diff --git a/module/declarations/unity-boolean-like.d.ts b/module/declarations/unity-boolean-like.d.ts deleted file mode 100644 index 1f3ada2a..00000000 --- a/module/declarations/unity-boolean-like.d.ts +++ /dev/null @@ -1,13 +0,0 @@ -/** - * Unity Boolean Like Type Declaration. This type declaration is used to - * represent the boolean values `true` and `false` in the Unity Module. - */ -declare type UnityBooleanLike = - /** - * Represents the boolean value `false`. - */ - | 0 - /** - * Represents the boolean value `true`. - */ - | 1; diff --git a/module/declarations/unity-instance.d.ts b/module/declarations/unity-instance.d.ts deleted file mode 100644 index a885e397..00000000 --- a/module/declarations/unity-instance.d.ts +++ /dev/null @@ -1,40 +0,0 @@ -import { ReactUnityEventParameter } from "../source/types/react-unity-event-parameters"; - -/** - * Type declaration for the UnityInstance. - */ -declare class UnityInstance { - /** - * Creates a new instance of Unity Instance. - */ - constructor(); - - /** - * Sends a message to the UnityInstance to invoke a public method. - * @param gameObjectName the name of the game object in your Unity scene. - * @param methodName the name of the public method on the game object. - * @param parameter an optional parameter to pass along to the method. - */ - public SendMessage( - gameObjectName: string, - methodName: string, - parameter?: ReactUnityEventParameter - ): void; - - /** - * Enables or disabled the fullscreen mode of the UnityInstance. - * @param fullScreen sets the fullscreen mode. - */ - public SetFullscreen(fullScreen: UnityBooleanLike): void; - - /** - * Quits the Unity WebGL application and removes it from the memory. - * @returns a promise which resolves when the application did quit. - */ - public Quit(): Promise; - - /** - * The internal Unity Module. - */ - public Module: UnityModule; -} diff --git a/module/declarations/unity-module.d.ts b/module/declarations/unity-module.d.ts deleted file mode 100644 index 1e8aa179..00000000 --- a/module/declarations/unity-module.d.ts +++ /dev/null @@ -1,29 +0,0 @@ -/** - * Type declaration for the UnityModule. - */ -declare type UnityModule = { - /** - * Stringifies a pointer to a string. - * @param pointer The pointer to the string. - * @param length The length of the string. - * @deprecated Deprecated in Unity 2021.2, use UTF8ToString instead. - */ - Pointer_stringify(pointer: number, length: number): string; - - /** - * Converts a pointer to a string. - * @param pointer The pointer to the string. - */ - UTF8ToString(pointer: number): string; - - /** - * Enables or disabled the fullscreen mode of the UnityInstance. - * @param fullScreen sets the fullscreen mode. - */ - SetFullscreen(fullScreen: UnityBooleanLike): void; - - /** - * A reference to the Unity Instance's Canvas. - */ - canvas?: HTMLCanvasElement; -}; From bd191de5a125d23a1322e78964e72221e8335afe Mon Sep 17 00:00:00 2001 From: Jeffrey Lanters Date: Tue, 15 Jul 2025 15:27:04 +0200 Subject: [PATCH 013/194] Refactor Unity component to use forwardRef and improve type safety --- module/source/components/unity.ts | 128 ++++++++++++++++++------------ 1 file changed, 79 insertions(+), 49 deletions(-) diff --git a/module/source/components/unity.ts b/module/source/components/unity.ts index 007df00e..4ecb9288 100644 --- a/module/source/components/unity.ts +++ b/module/source/components/unity.ts @@ -1,56 +1,86 @@ -/* eslint-disable @typescript-eslint/no-explicit-any */ -import { useState, useEffect, createElement } from "react"; +import { + useState, + useEffect, + createElement, + forwardRef, + ForwardRefExoticComponent, + JSX, + useImperativeHandle, +} from "react"; +import { UnityInstance } from "../types/unity-instance"; +import { UnityProps } from "../types/unity-props"; +import { useCanvasIdentifier } from "../hooks/use-canvas-identifier"; -let canvasCounter = 0; +const Unity: ForwardRefExoticComponent< + UnityProps & React.RefAttributes +> = forwardRef( + /** + * @param unityProps The Unity props provided the the Unity component. + * @param forwardedRef The forwarded ref to the Unity component. + * @returns The Unity canvas renderer. + */ + (props, forwardedRef): JSX.Element => { + const [canvasRef, setCanvasRef] = useState(null); + const [unityInstance, setUnityInstance] = useState( + null + ); -export const Unity = () => { - const [canvasRef, setCanvasRef] = useState(null); - const [unityInstance, setUnityInstance] = useState(null); - const [canvasId, setCanvasId] = useState("react-unity-webgl"); + const [canvasId, refreshCanvasId] = useCanvasIdentifier(props.id); - useEffect(() => { - const initializeUnity = async () => { - if (!canvasRef || unityInstance) { - return; - } + useEffect(() => { + const initializeUnity = async () => { + if (!canvasRef || unityInstance) { + return; + } - setCanvasId(`react-unity-webgl-${++canvasCounter}`); + refreshCanvasId(); - const unityConfig = { - dataUrl: "/unity-build/unity.data", - frameworkUrl: "/unity-build/unity.framework.js", - codeUrl: "/unity-build/unity.wasm", + const unityConfig = { + dataUrl: props.unityProvider.dataUrl, + frameworkUrl: props.unityProvider.frameworkUrl, + codeUrl: props.unityProvider.codeUrl, + }; + + // TODO: Inject loader script + + setUnityInstance( + await window.createUnityInstance(canvasRef, unityConfig) + ); + }; + + const detachUnity = async () => { + if (!unityInstance || !canvasRef) { + return; + } + + const cleanupCanvasRef = document.createElement("canvas"); + cleanupCanvasRef.id = canvasRef.id; + cleanupCanvasRef.setAttribute("react-unity-webgl-role", "cleanup"); + document.body.appendChild(cleanupCanvasRef); + unityInstance.Module.canvas = cleanupCanvasRef; + setUnityInstance(null); + await unityInstance.Quit(); + document.body.removeChild(cleanupCanvasRef); }; - setUnityInstance( - await window.createUnityInstance(canvasRef, unityConfig) - ); - }; - - const detachUnity = async () => { - if (!unityInstance || !canvasRef) { - return; - } - - const cleanupCanvasRef = document.createElement("canvas"); - cleanupCanvasRef.id = canvasRef.id; - cleanupCanvasRef.setAttribute("react-unity-webgl-role", "cleanup"); - document.body.appendChild(cleanupCanvasRef); - unityInstance.Module.canvas = cleanupCanvasRef; - setUnityInstance(null); - await unityInstance.Quit(); - document.body.removeChild(cleanupCanvasRef); - }; - - initializeUnity(); - - return () => { - detachUnity(); - }; - }, [canvasRef, unityInstance]); - - return createElement("canvas", { - ref: setCanvasRef, - id: canvasId, - }); -}; + initializeUnity(); + + return () => { + detachUnity(); + }; + }, [canvasRef, unityInstance]); + + useImperativeHandle( + forwardedRef, + () => canvasRef + ); + + return createElement("canvas", { + ref: setCanvasRef, + id: canvasId, + style: props.style, + }); + } +); + +export { Unity }; From 8ca63ab5929be25432aea88be19650b6c9c3a256 Mon Sep 17 00:00:00 2001 From: Jeffrey Lanters Date: Tue, 15 Jul 2025 15:27:07 +0200 Subject: [PATCH 014/194] Add useCanvasIdentifier hook to generate unique Unity canvas IDs --- module/source/hooks/use-canvas-identifier.ts | 54 ++++++++++++++++++++ 1 file changed, 54 insertions(+) create mode 100644 module/source/hooks/use-canvas-identifier.ts diff --git a/module/source/hooks/use-canvas-identifier.ts b/module/source/hooks/use-canvas-identifier.ts new file mode 100644 index 00000000..1f044ce4 --- /dev/null +++ b/module/source/hooks/use-canvas-identifier.ts @@ -0,0 +1,54 @@ +import { useCallback, useMemo, useState } from "react"; +import { UnityProps } from "../types/unity-props"; + +/** + * The canvas count is used to generate a unique Unity canvas ID. + */ +let unityCanvasCount = 0; + +/** + * The prefix used to generate a unique Unity canvas ID. + */ +const canvasIdPrefix = "react-unity-webgl-canvas"; + +/** + * Generates a unique Unity canvas ID. This is used internally by Unity since + * version 2021.2 to identify the canvas element in the DOM. This is not + * documented in the Unity documentation, but it is used in the Unity source + * code. + * @returns A unique identifier for a Unity canvas element. + */ +const useCanvasIdentifier = (id?: string): [string, VoidFunction] => { + /** + * The canvas incremention is used to generate a new unique Unity canvas ID. + */ + const [canvasIncremention, setCanvasIncremention] = useState(0); + + /** + * Refreshes the canvas ID by incrementing the canvas incremention. + */ + const refreshCanvasId = useCallback(() => { + // The canvas incremention is used to generate a new unique Unity canvas ID. + setCanvasIncremention((prev) => prev + 1); + }, []); + + // If the user has provided a Unity canvas ID, then this value is returned. + // This is useful for when the user wants to use a custom canvas ID. + if (id !== undefined) { + return [id, refreshCanvasId]; + } + + /** + * A unique identifier for a Unity canvas element is memorized. + */ + const canvasId = useMemo(() => { + // The Unity canvas ID is generated by concatenating the Unity canvas ID + // prefix with the canvas count. Every time this value is requested, the + // canvas count is incremented. + return [canvasIdPrefix, ++unityCanvasCount].join("-"); + }, [canvasIncremention]); + + return [canvasId, refreshCanvasId]; +}; + +export { useCanvasIdentifier }; From f17d87fe571ffea738d7829b26f95a21777250f7 Mon Sep 17 00:00:00 2001 From: Jeffrey Lanters Date: Tue, 15 Jul 2025 15:38:58 +0200 Subject: [PATCH 015/194] Add useUnityLoader hook to manage Unity loader status in Unity component --- module/source/components/unity.ts | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/module/source/components/unity.ts b/module/source/components/unity.ts index 4ecb9288..ed9c8595 100644 --- a/module/source/components/unity.ts +++ b/module/source/components/unity.ts @@ -10,6 +10,7 @@ import { import { UnityInstance } from "../types/unity-instance"; import { UnityProps } from "../types/unity-props"; import { useCanvasIdentifier } from "../hooks/use-canvas-identifier"; +import { useUnityLoader } from "../hooks/use-unity-loader"; const Unity: ForwardRefExoticComponent< UnityProps & React.RefAttributes @@ -27,9 +28,12 @@ const Unity: ForwardRefExoticComponent< const [canvasId, refreshCanvasId] = useCanvasIdentifier(props.id); + const unityLoaderStatus = useUnityLoader(props.unityProvider.loaderUrl); + useEffect(() => { const initializeUnity = async () => { - if (!canvasRef || unityInstance) { + console.info({ unityLoaderStatus }); + if (!canvasRef || unityInstance || unityLoaderStatus !== "Loaded") { return; } @@ -41,8 +45,6 @@ const Unity: ForwardRefExoticComponent< codeUrl: props.unityProvider.codeUrl, }; - // TODO: Inject loader script - setUnityInstance( await window.createUnityInstance(canvasRef, unityConfig) ); @@ -68,7 +70,7 @@ const Unity: ForwardRefExoticComponent< return () => { detachUnity(); }; - }, [canvasRef, unityInstance]); + }, [canvasRef, unityInstance, unityLoaderStatus, props.unityProvider]); useImperativeHandle( forwardedRef, From c0f74285a336f489ecf6cce2e1f355f00b778cbd Mon Sep 17 00:00:00 2001 From: Jeffrey Lanters Date: Tue, 15 Jul 2025 15:39:02 +0200 Subject: [PATCH 016/194] Add isBrowserEnvironment constant to check for browser environment --- module/source/constants/is-browser-environment.ts | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 module/source/constants/is-browser-environment.ts diff --git a/module/source/constants/is-browser-environment.ts b/module/source/constants/is-browser-environment.ts new file mode 100644 index 00000000..a49e6478 --- /dev/null +++ b/module/source/constants/is-browser-environment.ts @@ -0,0 +1,6 @@ +/** + * Defines if the current environment is a browser environment. This is + * determined by checking if the `window` and `document` objects are defined. + */ +export const isBrowserEnvironment = + typeof window !== "undefined" && typeof document !== "undefined"; From 6825b4f2b2a156c0aaea2264497834da7f4f5d78 Mon Sep 17 00:00:00 2001 From: Jeffrey Lanters Date: Tue, 15 Jul 2025 15:39:05 +0200 Subject: [PATCH 017/194] Add useUnityContext hook to manage Unity configuration and provider --- module/source/hooks/use-unity-context.ts | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) create mode 100644 module/source/hooks/use-unity-context.ts diff --git a/module/source/hooks/use-unity-context.ts b/module/source/hooks/use-unity-context.ts new file mode 100644 index 00000000..30b75940 --- /dev/null +++ b/module/source/hooks/use-unity-context.ts @@ -0,0 +1,19 @@ +import { useRef } from "react"; +import { UnityConfig } from "../types/unity-config"; +import { UnityContext } from "../types/unity-context"; +import { UnityProvider } from "../types/unity-provider"; + +const useUnityContext = (unityConfig: UnityConfig): UnityContext => { + const unityProvider = useRef({ + codeUrl: unityConfig.codeUrl, + dataUrl: unityConfig.dataUrl, + frameworkUrl: unityConfig.frameworkUrl, + loaderUrl: unityConfig.loaderUrl, + }); + + return { + unityProvider: unityProvider.current, + }; +}; + +export { useUnityContext }; From 56689c99beb41cb7ff04d9ec416e672fd947c383 Mon Sep 17 00:00:00 2001 From: Jeffrey Lanters Date: Tue, 15 Jul 2025 15:39:09 +0200 Subject: [PATCH 018/194] Add useUnityLoader hook to manage Unity loader script and status --- module/source/hooks/use-unity-loader.ts | 80 +++++++++++++++++++++++++ 1 file changed, 80 insertions(+) create mode 100644 module/source/hooks/use-unity-loader.ts diff --git a/module/source/hooks/use-unity-loader.ts b/module/source/hooks/use-unity-loader.ts new file mode 100644 index 00000000..a6da6336 --- /dev/null +++ b/module/source/hooks/use-unity-loader.ts @@ -0,0 +1,80 @@ +import { useEffect, useState } from "react"; +import { UnityLoaderStatus } from "../types/unity-loader-status"; +import { isBrowserEnvironment } from "../constants/is-browser-environment"; + +/** + * Hook to embed a Unity Loader script. + * @param source The source of the unity loader. + * @returns a hook that returns the status of the loader. + */ +const useUnityLoader = (loaderUrl: string): UnityLoaderStatus => { + const [status, setStatus] = useState("Loading"); + // Effect hook will be invoked when the source changes. + useEffect(() => { + // It is possible for the application being rendered server side. In + // this scenario, the window is not available. We can't create a Unity + // Loader in this case. + if (isBrowserEnvironment === false) { + return undefined; + } + // If the script's source is null, we'll reset the status to idle. + if (loaderUrl === null) { + setStatus("Idle"); + return undefined; + } + /** + * Find existing script element by source. It may have been added by + * another instance of this hook. + */ + let script: HTMLScriptElement | null = window.document.querySelector( + `script[src="${loaderUrl}"]` + ); + // If there wan't another instance of this script, we're going to create a + // new one with the provided source. + if (script === null) { + script = window.document.createElement("script"); + script.type = "text/javascript"; + script.src = loaderUrl; + script.async = true; + script.setAttribute("data-status", "loading"); + // Add script to window.document body. + window.document.body.appendChild(script); + // Store status in attribute on script. This can be read by other + // instances of this hook. + script.addEventListener("load", () => + script?.setAttribute("data-status", "loaded") + ); + script.addEventListener("error", () => + script?.setAttribute("data-status", "error") + ); + } else { + // If there already was a script with the same source, grab its existing + // script status from attribute and set to state. + setStatus( + script.getAttribute("data-status") === "loaded" ? "Loaded" : "Error" + ); + } + /** + * Script event handler to update status in state. Even if the script + * already exists we still need to add event handlers to update the state + * for this hook instance. + * @param event The event that was triggered. + */ + const setStateFromEvent = (event: Event) => + setStatus(event.type === "load" ? "Loaded" : "Error"); + script.addEventListener("load", setStateFromEvent); + script.addEventListener("error", setStateFromEvent); + // Remove event listeners on cleanup. + return () => { + if (script !== null) { + script.removeEventListener("load", setStateFromEvent); + script.removeEventListener("error", setStateFromEvent); + script.remove(); + } + }; + }, [loaderUrl]); + + return status; +}; + +export { useUnityLoader }; From 02bf8d9f45c772637b5f12a51a6dcc93caf48192 Mon Sep 17 00:00:00 2001 From: Jeffrey Lanters Date: Tue, 15 Jul 2025 15:39:13 +0200 Subject: [PATCH 019/194] Add type definition for ReactUnityEventParameter to support Unity event arguments --- .../types/react-unity-event-parameters.d.ts | 27 +++++++++++++++++++ 1 file changed, 27 insertions(+) create mode 100644 module/source/types/react-unity-event-parameters.d.ts diff --git a/module/source/types/react-unity-event-parameters.d.ts b/module/source/types/react-unity-event-parameters.d.ts new file mode 100644 index 00000000..66014b81 --- /dev/null +++ b/module/source/types/react-unity-event-parameters.d.ts @@ -0,0 +1,27 @@ +/** + * Type definition for Unity event argument types. These are the supported + * types for the React Unity WebGL event system which can be used to dispatch + * events to the React Application from the Unity Instance. + * + * Simple numeric types can be passed to JavaScript in function parameters + * without requiring any conversion. Other data types will be passed as a + * pointer in the emscripten heap (which is really just a big array in + * JavaScript). For strings, you can use the Pointerstringify helper function + * to convert to a JavaScript string. + * + * To return a string value you need to call _malloc to allocate some memory and + * the writeStringToMemory helper function to write a JavaScript string to it. + * If the string is a return value, then the il2cpp runtime will take care of + * freeing the memory for you. + * + * For arrays of primitive types, emscripten provides different ArrayBufferViews + * into it’s heap for different sizes of integer, unsigned integer or floating + * point representations of memory: HEAP8, HEAPU8, HEAP16, HEAPU16, HEAP32, + * HEAPU32, HEAPF32, HEAPF64. To access a texture in WebGL, emscripten provides + * the GL.textures array which maps native texture IDs from Unity to WebGL + * texture objects. WebGL functions can be called on emscripten’s WebGL context, + * GLctx. + */ +type ReactUnityEventParameter = string | number | undefined | void; + +export type { ReactUnityEventParameter }; From eb2dcf373f193d37ff173fe149a84716c3ce9932 Mon Sep 17 00:00:00 2001 From: Jeffrey Lanters Date: Tue, 15 Jul 2025 15:39:16 +0200 Subject: [PATCH 020/194] Add UnityArguments type definition to initialize Unity instance with various configuration options --- module/source/types/unity-arguments.d.ts | 158 +++++++++++++++++++++++ 1 file changed, 158 insertions(+) create mode 100644 module/source/types/unity-arguments.d.ts diff --git a/module/source/types/unity-arguments.d.ts b/module/source/types/unity-arguments.d.ts new file mode 100644 index 00000000..e2087bba --- /dev/null +++ b/module/source/types/unity-arguments.d.ts @@ -0,0 +1,158 @@ +import { UnityCacheControlMode } from "./unity-cache-control-mode"; +import { UnityInstanceBannerType } from "./unity-instance-banner-type"; + +/** + * The Unity Arguments can be passed to a create Unity instance method in order + * to initialize it. These arguments are created based on the provided Unity + * Props which also include the Unity Provider and thus the Unity Config. + */ +type UnityArguments = { + /** + * The url to the build data file generated by Unity. When using a relative url, + * keep in mind this is relative from the path where your html file is served. + * It is also possible to use an absolute url, for example when using a CDN. + */ + readonly dataUrl: string; + + /** + * The url to the framework file generated by Unity. When using a relative url, + * keep in mind this is relative from the path where your html file is served. + * It is also possible to use an absolute url, for example when using a CDN. + */ + readonly frameworkUrl: string; + + /** + * The url to the unity code file generated by Unity. When using a relative url, + * keep in mind this is relative from the path where your html file is served. + * It is also possible to use an absolute url, for example when using a CDN. + */ + readonly codeUrl: string; + + /** + * The url to the web worker file generated by Unity. When using a relative url, + * keep in mind this is relative from the path where your html file is served. + * It is also possible to use an absolute url, for example when using a CDN. + */ + readonly workerUrl?: string; + + /** + * The url where the streaming assets can be found. When using a relative url, + * keep in mind this is relative from the path where your html file is served. + * It is also possible to use an absolute url, for example when using a CDN. + */ + readonly streamingAssetsUrl?: string; + + /** + * The url to the framework file generated by Unity. When using a relative url, + * keep in mind this is relative from the path where your html file is served. + * It is also possible to use an absolute url, for example when using a CDN. + * This is set to the memory file when memory is stored in an external file, + * otherwise it is set to an empty string. + */ + readonly memoryUrl?: string; + + /** + * The url to the unity code file generated by Unity. When using a relative + * url, keep in mind this is relative from the path where your html file is + * served. It is also possible to use an absolute url, for example when using + * a CDN. This is set to the JSON file containing debug symbols when the + * current build is using debug symbols, otherwise it is set to an empty + * string. + */ + readonly symbolsUrl?: string; + + /** + * The application's company name. This argument is treated as meta data + * which will be provided to the Unity Instance. + */ + readonly companyName?: string; + + /** + * The application's product name. This argument is treated as meta data + * which will be provided to the Unity Instance. + */ + readonly productName?: string; + + /** + * The application's product version. This argument is treated as meta data + * which will be provided to the Unity Instance. + */ + readonly productVersion?: string; + + /** + * The Canvas can appear too blurry on retina screens. The devicePixelRatio + * determines how much extra pixel density should be added to allow for a + * sharper image. + * @see https://developer.mozilla.org/en-US/docs/Web/API/Window/devicePixelRatio + */ + readonly devicePixelRatio?: number; + + /** + * If set to true, all file writes inside the Unity Application + * persistentDataPath directory automatically persist so that the contents are + * remembered when the user revisits the website the next time. If unset (or + * set to false), you must manually sync file modifications inside the + * Application persistentDataPath directory by calling the + * JS_FileSystem_Sync() JavaScript function. + */ + readonly autoSyncPersistentDataPath?: boolean; + + /** + * When disabling the match WebGL to canvas size flag, the canvas allows for + * client side customization of the WebGL canvas target size instead of + * requiring it to always match 1:1 with the High DPI CSS size of the canvas. + * Supported since Unity 2021.1b + * @see https://issuetracker.unity3d.com/issues/webgl-builds-dont-allow-separate-control-on-canvas-render-buffer-size + */ + readonly matchWebGLToCanvasSize?: boolean; + + /** + * This object allow you to configure WebGLRenderingContext creation options + * which will be pass additional context attributes to the Unity canvas. + * @see https://developer.mozilla.org/en-US/docs/Web/API/WebGLRenderingContext + */ + readonly webglContextAttributes?: WebGLContextAttributes; + + /** + * An array of strings containing the names of the events that should be + * disabled on the canvas. This can be useful when you want to allow the user + * to interact with the canvas, but not with the Unity WebGL canvas. The + * default disabled events are `contextmenu` and `dragstart`. + */ + readonly disabledCanvasEvents?: (keyof GlobalEventHandlersEventMap)[]; + + /** + * By default, the WebGL Cache stores the asset data file .data and + * AssetBundle files .bundle, and revalidates them before loading them from + * the cache. You can change this behavior by overriding the default + * caching behavior. This argument is treated as meta data which will be + * provided to the Unity Instance. + */ + readonly cacheControl?: (url: string) => UnityCacheControlMode; + + /** + * Add an event listener using this function to receive non-critical warnings + * and error messages from the Unity Instance. + */ + readonly showBanner?: ( + message: string, + type?: UnityInstanceBannerType + ) => void; + + /** + * When assigned this method will intercept all incomming messages from the + * Unity Module into the console. These messages will contain both of the + * internal information messages as well as the debuggers log messages. + */ + readonly print?: (message: string) => void; + + /** + * When assigned this method will intercept all incomming error logs from the + * Unity Module into the console. These messages will contain both of the + * runtime problems as well as the jslib and javascript errors thrown by the + * Unity Instance. + */ + readonly printErr?: (message: string) => void; +}; + +export type { UnityArguments }; From e7053a3a77cb08481fab06e20a78c017faeb7f6f Mon Sep 17 00:00:00 2001 From: Jeffrey Lanters Date: Tue, 15 Jul 2025 15:39:19 +0200 Subject: [PATCH 021/194] Add UnityBooleanLike type declaration to represent boolean values in Unity Module --- module/source/types/unity-boolean-like.d.ts | 15 +++++++++++++++ 1 file changed, 15 insertions(+) create mode 100644 module/source/types/unity-boolean-like.d.ts diff --git a/module/source/types/unity-boolean-like.d.ts b/module/source/types/unity-boolean-like.d.ts new file mode 100644 index 00000000..75890d7e --- /dev/null +++ b/module/source/types/unity-boolean-like.d.ts @@ -0,0 +1,15 @@ +/** + * Unity Boolean Like Type Declaration. This type declaration is used to + * represent the boolean values `true` and `false` in the Unity Module. + */ +type UnityBooleanLike = + /** + * Represents the boolean value `false`. + */ + | 0 + /** + * Represents the boolean value `true`. + */ + | 1; + +export type { UnityBooleanLike }; From afefba742319106cea0785eec9c412946d46f8d2 Mon Sep 17 00:00:00 2001 From: Jeffrey Lanters Date: Tue, 15 Jul 2025 15:39:23 +0200 Subject: [PATCH 022/194] Add UnityCacheControlMode type definition to manage caching behavior in Unity --- .../types/unity-cache-control-mode.d.ts | 28 +++++++++++++++++++ 1 file changed, 28 insertions(+) create mode 100644 module/source/types/unity-cache-control-mode.d.ts diff --git a/module/source/types/unity-cache-control-mode.d.ts b/module/source/types/unity-cache-control-mode.d.ts new file mode 100644 index 00000000..de82fbf8 --- /dev/null +++ b/module/source/types/unity-cache-control-mode.d.ts @@ -0,0 +1,28 @@ +/** + * The cache control mode determines how the Unity should cache the resource. + * - `must-revalidate`: The cache returns to an enabled state and the file is + * revalidated before being loaded from the cache. + * - `immutable`: the cache is enabled and the file is loaded from the cache + * without revalidation. + * - `no-store`: The cache is disabled. + */ +type UnityCacheControlMode = + /** + * The cache returns to an enabled state and the file is revalidated before + * being loaded from the cache. + */ + | "must-revalidate" + /** + * the cache is enabled and the file is loaded from the cache without revalidation. + */ + | "immutable" + /** + * The cache is disabled. + */ + | "no-store" + /** + * Fallback for when the cache control mode is not recognized. + */ + | string; + +export type { UnityCacheControlMode }; From f5d711b238301320be0ba528eb403df135c4f766 Mon Sep 17 00:00:00 2001 From: Jeffrey Lanters Date: Tue, 15 Jul 2025 15:39:27 +0200 Subject: [PATCH 023/194] Add UnityConfig type definition to specify Unity configuration options --- module/source/types/unity-config.d.ts | 15 +++++++++++++++ 1 file changed, 15 insertions(+) create mode 100644 module/source/types/unity-config.d.ts diff --git a/module/source/types/unity-config.d.ts b/module/source/types/unity-config.d.ts new file mode 100644 index 00000000..6b091fb1 --- /dev/null +++ b/module/source/types/unity-config.d.ts @@ -0,0 +1,15 @@ +import { UnityArguments } from "./unity-arguments"; + +type UnityConfig = Pick< + UnityArguments, + "dataUrl" | "frameworkUrl" | "codeUrl" +> & { + /** + * The url to the build json file generated by Unity. When using a relative url, + * keep in mind this is relative from the path where your html file is served. + * It is also possible to use an absolute url, for example when using a CDN. + */ + readonly loaderUrl: string; +}; + +export type { UnityConfig }; From 290a947a162d273bf166029a620084f0f3d9cec3 Mon Sep 17 00:00:00 2001 From: Jeffrey Lanters Date: Tue, 15 Jul 2025 15:39:30 +0200 Subject: [PATCH 024/194] Add type definition for UnityContext to encapsulate Unity Provider instance --- module/source/types/unity-context.d.ts | 12 ++++++++++++ 1 file changed, 12 insertions(+) create mode 100644 module/source/types/unity-context.d.ts diff --git a/module/source/types/unity-context.d.ts b/module/source/types/unity-context.d.ts new file mode 100644 index 00000000..8c6c8cea --- /dev/null +++ b/module/source/types/unity-context.d.ts @@ -0,0 +1,12 @@ +import { UnityProvider } from "./unity-provider"; + +type UnityContext = { + /** + * The Unity Context returns a Unity Provider instance. This immutable object + * should be passed onto a Unity Component in order to be able to access the + * Unity Context's state. + */ + readonly unityProvider: UnityProvider; +}; + +export type { UnityContext }; From 1d0066a19df73e1f6926738811b43fd4303f8987 Mon Sep 17 00:00:00 2001 From: Jeffrey Lanters Date: Tue, 15 Jul 2025 15:39:33 +0200 Subject: [PATCH 025/194] Add type definition for UnityInstanceBannerType to represent banner messages --- module/source/types/unity-instance-banner-type.d.ts | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 module/source/types/unity-instance-banner-type.d.ts diff --git a/module/source/types/unity-instance-banner-type.d.ts b/module/source/types/unity-instance-banner-type.d.ts new file mode 100644 index 00000000..d5df52da --- /dev/null +++ b/module/source/types/unity-instance-banner-type.d.ts @@ -0,0 +1,7 @@ +/** + * Banners can be used to display non-critical warnings and error messages from + * the Unity Instance. + */ +type UnityInstanceBannerType = "error" | "warning"; + +export type { UnityInstanceBannerType }; From e2575aec55ed530dac85fa16c9385e28d1bd0530 Mon Sep 17 00:00:00 2001 From: Jeffrey Lanters Date: Tue, 15 Jul 2025 15:39:36 +0200 Subject: [PATCH 026/194] Add type declaration for UnityInstance to define its methods and properties --- module/source/types/unity-instance.d.ts | 39 +++++++++++++++++++++++++ 1 file changed, 39 insertions(+) create mode 100644 module/source/types/unity-instance.d.ts diff --git a/module/source/types/unity-instance.d.ts b/module/source/types/unity-instance.d.ts new file mode 100644 index 00000000..cad971c5 --- /dev/null +++ b/module/source/types/unity-instance.d.ts @@ -0,0 +1,39 @@ +import { ReactUnityEventParameter } from "./react-unity-event-parameters"; +import { UnityBooleanLike } from "./unity-boolean-like"; +import { UnityModule } from "./unity-module"; + +/** + * Type declaration for the UnityInstance. + */ +type UnityInstance = { + /** + * Sends a message to the UnityInstance to invoke a public method. + * @param gameObjectName the name of the game object in your Unity scene. + * @param methodName the name of the public method on the game object. + * @param parameter an optional parameter to pass along to the method. + */ + SendMessage( + gameObjectName: string, + methodName: string, + parameter?: ReactUnityEventParameter + ): void; + + /** + * Enables or disabled the fullscreen mode of the UnityInstance. + * @param fullScreen sets the fullscreen mode. + */ + SetFullscreen(fullScreen: UnityBooleanLike): void; + + /** + * Quits the Unity WebGL application and removes it from the memory. + * @returns a promise which resolves when the application did quit. + */ + Quit(): Promise; + + /** + * The internal Unity Module. + */ + Module: UnityModule; +}; + +export type { UnityInstance }; From 0acc28efdde41e68aa17b2f531d4ca9a3675f395 Mon Sep 17 00:00:00 2001 From: Jeffrey Lanters Date: Tue, 15 Jul 2025 15:39:40 +0200 Subject: [PATCH 027/194] Add type definition for UnityLoaderStatus to represent loader states --- module/source/types/unity-loader-status.d.ts | 25 ++++++++++++++++++++ 1 file changed, 25 insertions(+) create mode 100644 module/source/types/unity-loader-status.d.ts diff --git a/module/source/types/unity-loader-status.d.ts b/module/source/types/unity-loader-status.d.ts new file mode 100644 index 00000000..6f82d6e6 --- /dev/null +++ b/module/source/types/unity-loader-status.d.ts @@ -0,0 +1,25 @@ +/** + * The status of the Unity loader. + */ +type UnityLoaderStatus = + /** + * The Unity loader is idling and awaiting a resource it be loaded. + */ + | "Idle" + + /** + * The Unity loader is loading a resource. + */ + | "Loading" + + /** + * The Unity loader has loaded a resource. + */ + | "Loaded" + + /** + * The Unity loader has failed to load a resource. + */ + | "Error"; + +export type { UnityLoaderStatus }; From b64ca0b5527a1425f8ebd7c2f019fd1d8c6214d2 Mon Sep 17 00:00:00 2001 From: Jeffrey Lanters Date: Tue, 15 Jul 2025 15:39:43 +0200 Subject: [PATCH 028/194] Add type declaration for UnityModule to define its methods and properties --- module/source/types/unity-module.d.ts | 33 +++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) create mode 100644 module/source/types/unity-module.d.ts diff --git a/module/source/types/unity-module.d.ts b/module/source/types/unity-module.d.ts new file mode 100644 index 00000000..ca130073 --- /dev/null +++ b/module/source/types/unity-module.d.ts @@ -0,0 +1,33 @@ +import { UnityBooleanLike } from "./unity-boolean-like"; + +/** + * Type declaration for the UnityModule. + */ +type UnityModule = { + /** + * Stringifies a pointer to a string. + * @param pointer The pointer to the string. + * @param length The length of the string. + * @deprecated Deprecated in Unity 2021.2, use UTF8ToString instead. + */ + Pointer_stringify(pointer: number, length: number): string; + + /** + * Converts a pointer to a string. + * @param pointer The pointer to the string. + */ + UTF8ToString(pointer: number): string; + + /** + * Enables or disabled the fullscreen mode of the UnityInstance. + * @param fullScreen sets the fullscreen mode. + */ + SetFullscreen(fullScreen: UnityBooleanLike): void; + + /** + * A reference to the Unity Instance's Canvas. + */ + canvas?: HTMLCanvasElement; +}; + +export type { UnityModule }; From 0b336be314c13b93f3830c6ffa9ef0f7bd9a4744 Mon Sep 17 00:00:00 2001 From: Jeffrey Lanters Date: Tue, 15 Jul 2025 15:39:48 +0200 Subject: [PATCH 029/194] Add type declaration for UnityProps to define properties for Unity component --- module/source/types/unity-props.d.ts | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) create mode 100644 module/source/types/unity-props.d.ts diff --git a/module/source/types/unity-props.d.ts b/module/source/types/unity-props.d.ts new file mode 100644 index 00000000..1ee5c21d --- /dev/null +++ b/module/source/types/unity-props.d.ts @@ -0,0 +1,24 @@ +import { CSSProperties } from "react"; +import { UnityProvider } from "./unity-provider"; + +type UnityProps = { + /** + * The Unity provider that contains the necessary URLs to load the Unity + * instance. This is required to load the Unity WebGL build. + */ + unityProvider: UnityProvider; + + /** + * The ID of the Unity canvas element. If not provided, a unique ID will be + * generated. It is recommended to let the library generate a unique ID + * unless you have a specific reason to use a custom ID. + */ + id?: string; + + /** + * The style of the Unity canvas element. + */ + style?: CSSProperties; +}; + +export type { UnityProps }; From 71e44ac08cf739bbc4c554b5c8a70e6cf5e2330c Mon Sep 17 00:00:00 2001 From: Jeffrey Lanters Date: Tue, 15 Jul 2025 15:39:51 +0200 Subject: [PATCH 030/194] Add type declaration for UnityProvider to define properties for Unity configuration --- module/source/types/unity-provider.d.ts | 8 ++++++++ 1 file changed, 8 insertions(+) create mode 100644 module/source/types/unity-provider.d.ts diff --git a/module/source/types/unity-provider.d.ts b/module/source/types/unity-provider.d.ts new file mode 100644 index 00000000..e6c476c4 --- /dev/null +++ b/module/source/types/unity-provider.d.ts @@ -0,0 +1,8 @@ +import { UnityConfig } from "./unity-config"; + +type UnityProvider = Pick< + UnityConfig, + "loaderUrl" | "dataUrl" | "frameworkUrl" | "codeUrl" +> & {}; + +export type { UnityProvider }; From 27edd9c7d682a60b747674e54058c3e8ff5feaa8 Mon Sep 17 00:00:00 2001 From: Jeffrey Lanters Date: Tue, 15 Jul 2025 15:39:54 +0200 Subject: [PATCH 031/194] Export useUnityContext from the module for improved accessibility --- module/source/exports.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/module/source/exports.ts b/module/source/exports.ts index 38c0bf9f..90e8079d 100644 --- a/module/source/exports.ts +++ b/module/source/exports.ts @@ -1,3 +1,4 @@ import { Unity } from "./components/unity"; +import { useUnityContext } from "./hooks/use-unity-context"; -export { Unity }; +export { Unity, useUnityContext }; From 6847e3831c3be629a0f6acc75aa374e8e3d0e19e Mon Sep 17 00:00:00 2001 From: Jeffrey Lanters Date: Tue, 15 Jul 2025 15:40:00 +0200 Subject: [PATCH 032/194] Update TypeScript and @types/react to latest versions for improved compatibility --- module/package-lock.json | 42 ++++++++++++++-------------------------- module/package.json | 4 ++-- 2 files changed, 16 insertions(+), 30 deletions(-) diff --git a/module/package-lock.json b/module/package-lock.json index 0b60e2a9..8b551cab 100644 --- a/module/package-lock.json +++ b/module/package-lock.json @@ -19,26 +19,19 @@ ], "license": "Apache-2.0", "devDependencies": { - "@types/react": "18.3.3", - "typescript": "5.6.3" + "@types/react": "19.1.8", + "typescript": "5.8.3" }, "peerDependencies": { "react": ">=16.8.0" } }, - "node_modules/@types/prop-types": { - "version": "15.7.4", - "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.4.tgz", - "integrity": "sha512-rZ5drC/jWjrArrS8BR6SIr4cWpW09RNTYt9AMZo3Jwwif+iacXAqgVjm0B0Bv/S1jhDXKHqRVNCbACkJ89RAnQ==", - "dev": true - }, "node_modules/@types/react": { - "version": "18.3.3", - "resolved": "https://registry.npmjs.org/@types/react/-/react-18.3.3.tgz", - "integrity": "sha512-hti/R0pS0q1/xx+TsI73XIqk26eBsISZ2R0wUijXIngRK9R/e7Xw/cXVxQK7R5JjW+SV4zGcn5hXjudkN/pLIw==", + "version": "19.1.8", + "resolved": "https://registry.npmjs.org/@types/react/-/react-19.1.8.tgz", + "integrity": "sha512-AwAfQ2Wa5bCx9WP8nZL2uMZWod7J7/JSplxbTmBQ5ms6QpqNYm672H0Vu9ZVKVngQ+ii4R/byguVEUZQyeg44g==", "dev": true, "dependencies": { - "@types/prop-types": "*", "csstype": "^3.0.2" } }, @@ -89,9 +82,9 @@ } }, "node_modules/typescript": { - "version": "5.6.3", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.6.3.tgz", - "integrity": "sha512-hjcS1mhfuyi4WW8IWtjP7brDrG2cuDZukyrYrSauoXGNgx0S7zceP07adYkJycEr56BOUTNPzbInooiN3fn1qw==", + "version": "5.8.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.8.3.tgz", + "integrity": "sha512-p1diW6TqL9L07nNxvRMM7hMMw4c5XOo/1ibL4aAIGmSAt9slTE1Xgw5KWuof2uTOvCg9BY7ZRi+GaF+7sfgPeQ==", "dev": true, "bin": { "tsc": "bin/tsc", @@ -103,19 +96,12 @@ } }, "dependencies": { - "@types/prop-types": { - "version": "15.7.4", - "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.4.tgz", - "integrity": "sha512-rZ5drC/jWjrArrS8BR6SIr4cWpW09RNTYt9AMZo3Jwwif+iacXAqgVjm0B0Bv/S1jhDXKHqRVNCbACkJ89RAnQ==", - "dev": true - }, "@types/react": { - "version": "18.3.3", - "resolved": "https://registry.npmjs.org/@types/react/-/react-18.3.3.tgz", - "integrity": "sha512-hti/R0pS0q1/xx+TsI73XIqk26eBsISZ2R0wUijXIngRK9R/e7Xw/cXVxQK7R5JjW+SV4zGcn5hXjudkN/pLIw==", + "version": "19.1.8", + "resolved": "https://registry.npmjs.org/@types/react/-/react-19.1.8.tgz", + "integrity": "sha512-AwAfQ2Wa5bCx9WP8nZL2uMZWod7J7/JSplxbTmBQ5ms6QpqNYm672H0Vu9ZVKVngQ+ii4R/byguVEUZQyeg44g==", "dev": true, "requires": { - "@types/prop-types": "*", "csstype": "^3.0.2" } }, @@ -157,9 +143,9 @@ } }, "typescript": { - "version": "5.6.3", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.6.3.tgz", - "integrity": "sha512-hjcS1mhfuyi4WW8IWtjP7brDrG2cuDZukyrYrSauoXGNgx0S7zceP07adYkJycEr56BOUTNPzbInooiN3fn1qw==", + "version": "5.8.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.8.3.tgz", + "integrity": "sha512-p1diW6TqL9L07nNxvRMM7hMMw4c5XOo/1ibL4aAIGmSAt9slTE1Xgw5KWuof2uTOvCg9BY7ZRi+GaF+7sfgPeQ==", "dev": true } } diff --git a/module/package.json b/module/package.json index 3951db42..e99ee4fa 100644 --- a/module/package.json +++ b/module/package.json @@ -53,8 +53,8 @@ "lint": "echo 'Warning: lint is not implemented yet'" }, "devDependencies": { - "@types/react": "18.3.3", - "typescript": "5.6.3" + "@types/react": "19.1.8", + "typescript": "5.8.3" }, "peerDependencies": { "react": ">=16.8.0" From 7ca44964588ff1423eea45667fe498d7322bf25f Mon Sep 17 00:00:00 2001 From: Jeffrey Lanters Date: Tue, 15 Jul 2025 15:40:07 +0200 Subject: [PATCH 033/194] Add Unity WebGL loader and WebAssembly binary - Introduced unity.loader.js to handle Unity WebGL content loading, error handling, and caching mechanisms. - Added unity.wasm as the compiled WebAssembly binary for Unity content. --- .../{communication-tests.data => unity.data} | Bin ...cation-tests.framework.js => unity.framework.js} | 0 ...ommunication-tests.loader.js => unity.loader.js} | 0 .../{communication-tests.wasm => unity.wasm} | Bin 4 files changed, 0 insertions(+), 0 deletions(-) rename testing/public/unity-build/{communication-tests.data => unity.data} (100%) rename testing/public/unity-build/{communication-tests.framework.js => unity.framework.js} (100%) rename testing/public/unity-build/{communication-tests.loader.js => unity.loader.js} (100%) rename testing/public/unity-build/{communication-tests.wasm => unity.wasm} (100%) diff --git a/testing/public/unity-build/communication-tests.data b/testing/public/unity-build/unity.data similarity index 100% rename from testing/public/unity-build/communication-tests.data rename to testing/public/unity-build/unity.data diff --git a/testing/public/unity-build/communication-tests.framework.js b/testing/public/unity-build/unity.framework.js similarity index 100% rename from testing/public/unity-build/communication-tests.framework.js rename to testing/public/unity-build/unity.framework.js diff --git a/testing/public/unity-build/communication-tests.loader.js b/testing/public/unity-build/unity.loader.js similarity index 100% rename from testing/public/unity-build/communication-tests.loader.js rename to testing/public/unity-build/unity.loader.js diff --git a/testing/public/unity-build/communication-tests.wasm b/testing/public/unity-build/unity.wasm similarity index 100% rename from testing/public/unity-build/communication-tests.wasm rename to testing/public/unity-build/unity.wasm From abc20dbdf43fe615b9fbe27ab7d783ef39396a3a Mon Sep 17 00:00:00 2001 From: Jeffrey Lanters Date: Tue, 15 Jul 2025 15:40:10 +0200 Subject: [PATCH 034/194] Refactor Application component to simplify Unity integration and remove unused code --- testing/src/application.tsx | 166 ++++-------------------------------- 1 file changed, 16 insertions(+), 150 deletions(-) diff --git a/testing/src/application.tsx b/testing/src/application.tsx index b0ca13b9..1d89244f 100644 --- a/testing/src/application.tsx +++ b/testing/src/application.tsx @@ -1,162 +1,28 @@ -import { Fragment, useEffect, useRef, useState } from "react"; -import { Unity, useUnityContext } from "react-unity-webgl"; +import { Fragment, useState } from "react"; +import { Unity, useUnityContext } from "../../module/source/exports"; export function Application() { - function handleCacheControl(url: string) { - console.log(`Cache control for ${url}`); - return "no-cache"; - } + const [isMounted, setIsMounted] = useState(false); - const { - loadingProgression, - unityProvider, - isLoaded, - requestFullscreen, - requestPointerLock, - sendMessage, - initialisationError, - addEventListener, - removeEventListener, - takeScreenshot, - unload, - UNSAFE__unityInstance, - } = useUnityContext({ - codeUrl: `/unity-build/communication-tests.wasm`, - dataUrl: `/unity-build/communication-tests.data`, - frameworkUrl: `/unity-build/communication-tests.framework.js`, - loaderUrl: `/unity-build/communication-tests.loader.js`, - webglContextAttributes: { - preserveDrawingBuffer: true, - }, - cacheControl: handleCacheControl, + const { unityProvider } = useUnityContext({ + codeUrl: `/unity-build/unity.wasm`, + dataUrl: `/unity-build/unity.data`, + frameworkUrl: `/unity-build/unity.framework.js`, + loaderUrl: `/unity-build/unity.loader.js`, }); - const canvasRef = useRef(null); - const [screenshots, setScreenshots] = useState([]); - const [consoleEntries, setConsoleEntries] = useState([]); - const [canvasWidth, setCanvasWidth] = useState(500); - - function handleClickRequestFullScreen() { - requestFullscreen(true); - } - - function handleClickRequestPointerLock() { - requestPointerLock(); - } - - function handleClickUnload() { - unload(); - } - - function handleClickSetRandomCanvasWidth() { - setCanvasWidth(Math.floor(Math.random() * 500) + 250); - } - - function handleClickSetLogText() { - sendMessage( - "Persistent", - "SetLogText", - "Hello World, the time is " + new Date().toISOString() - ); - } - - function handleClickLogCanvasRefToConsole() { - console.log("Canvas Reference", { canvasRef: canvasRef.current }); - } - - function handleClickLogUnityInstanceRefToConsole() { - console.log("Unity Instance Reference", { UNSAFE__unityInstance }); - } - - function handleClickTakeScreenshot() { - const screenshot = takeScreenshot("image/jpg", 1); - if (screenshot) { - setScreenshots([...screenshots, screenshot]); - } - } - - useEffect(() => { - function logParametersToConsole(...parameters: any[]) { - setConsoleEntries((entries) => [ - ...entries, - `Event: ${parameters.join(", ")}`, - ]); - } - - addEventListener("ClickedTestButton", logParametersToConsole); - addEventListener("ClickedStringTestButton", logParametersToConsole); - addEventListener("ClickedNumberTestButton", logParametersToConsole); - addEventListener("ClickedNumbersTestButton", logParametersToConsole); - addEventListener("ClickedBoolTestButton", logParametersToConsole); - addEventListener("ClickedObjectTestButton", logParametersToConsole); - return () => { - removeEventListener("ClickedTestButton", logParametersToConsole); - removeEventListener("ClickedStringTestButton", logParametersToConsole); - removeEventListener("ClickedNumberTestButton", logParametersToConsole); - removeEventListener("ClickedNumbersTestButton", logParametersToConsole); - removeEventListener("ClickedBoolTestButton", logParametersToConsole); - removeEventListener("ClickedObjectTestButton", logParametersToConsole); - }; - }, [addEventListener, removeEventListener]); - return (

Unity Test

-

State

- Loading progression: {loadingProgression} -
- Loaded: {isLoaded ? "YES" : "NO"} -
- Error: {initialisationError?.message || "NONE"} -
-

Actions

- References: - - -
- Actions: - - - -
- Screenshots: - - {screenshots.map((screenshot, index) => ( - Screenshot - ))} -
- Communication: - -
- Other: - -

Unity

- -

Console

- - {consoleEntries.map((entry, index) => ( -
{entry}
- ))} -
+ {isMounted && ( + + )}
); } From 957a4cae0340d18c385c34aa9b2f2d1f12539cd5 Mon Sep 17 00:00:00 2001 From: Jeffrey Lanters Date: Tue, 15 Jul 2025 15:40:13 +0200 Subject: [PATCH 035/194] Remove react-unity-webgl dependency from package.json and package-lock.json --- testing/package-lock.json | 21 +-------------------- testing/package.json | 3 +-- 2 files changed, 2 insertions(+), 22 deletions(-) diff --git a/testing/package-lock.json b/testing/package-lock.json index 15607d71..29e4bd48 100644 --- a/testing/package-lock.json +++ b/testing/package-lock.json @@ -9,8 +9,7 @@ "version": "3.0.0", "dependencies": { "react": "^18.3.1", - "react-dom": "^18.3.1", - "react-unity-webgl": "9.8.0" + "react-dom": "^18.3.1" }, "devDependencies": { "@eslint/js": "^9.17.0", @@ -2612,24 +2611,6 @@ "node": ">=0.10.0" } }, - "node_modules/react-unity-webgl": { - "version": "9.8.0", - "resolved": "https://registry.npmjs.org/react-unity-webgl/-/react-unity-webgl-9.8.0.tgz", - "integrity": "sha512-YKy/0jOrTYXkfFx2nh6POECk4tWo8zHJhJ6hf798aeuNcllFn2PJUCmPAiXpZnfa8vDSpb8qwNawGTyjVuOjZw==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/jeffreylanters" - }, - { - "type": "website", - "url": "https://react-unity-webgl.dev/support" - } - ], - "peerDependencies": { - "react": ">=16.8.0" - } - }, "node_modules/resolve-from": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", diff --git a/testing/package.json b/testing/package.json index 13bfd529..050bb1bd 100644 --- a/testing/package.json +++ b/testing/package.json @@ -8,8 +8,7 @@ }, "dependencies": { "react": "^18.3.1", - "react-dom": "^18.3.1", - "react-unity-webgl": "9.8.0" + "react-dom": "^18.3.1" }, "devDependencies": { "@eslint/js": "^9.17.0", From fb21ed77c1f4240c5838e90615e67d53c5fb1f0c Mon Sep 17 00:00:00 2001 From: Jeffrey Lanters Date: Tue, 15 Jul 2025 15:44:58 +0200 Subject: [PATCH 036/194] Enhance Unity component to support dynamic initialization and cleanup of Unity instances --- module/source/components/unity.ts | 57 +++++++++++++++++++++++++++++-- 1 file changed, 54 insertions(+), 3 deletions(-) diff --git a/module/source/components/unity.ts b/module/source/components/unity.ts index ed9c8595..8d11921d 100644 --- a/module/source/components/unity.ts +++ b/module/source/components/unity.ts @@ -11,6 +11,8 @@ import { UnityInstance } from "../types/unity-instance"; import { UnityProps } from "../types/unity-props"; import { useCanvasIdentifier } from "../hooks/use-canvas-identifier"; import { useUnityLoader } from "../hooks/use-unity-loader"; +import { UnityConfig } from "../types/unity-config"; +import { UnityArguments } from "../types/unity-arguments"; const Unity: ForwardRefExoticComponent< UnityProps & React.RefAttributes @@ -21,40 +23,77 @@ const Unity: ForwardRefExoticComponent< * @returns The Unity canvas renderer. */ (props, forwardedRef): JSX.Element => { + // State to hold the canvas reference and Unity instance. + // The canvas reference is used to render the Unity instance. const [canvasRef, setCanvasRef] = useState(null); const [unityInstance, setUnityInstance] = useState( null ); + // Use a custom hook to generate a unique canvas ID or use the provided one. + // This ensures that each Unity instance has a unique canvas ID. + // This is important for multiple Unity instances on the same page. + // The hook also provides a function to refresh the canvas ID if needed. const [canvasId, refreshCanvasId] = useCanvasIdentifier(props.id); + // Use a custom hook to load the Unity loader script. + // This hook returns the status of the loader, which can be used to + // determine if the Unity instance is ready to be initialized. const unityLoaderStatus = useUnityLoader(props.unityProvider.loaderUrl); + // Effect to initialize the Unity instance when the component mounts or + // when the canvas reference or Unity loader status changes. useEffect(() => { + // Function to initialize the Unity instance. + // This function is called when the component mounts or when the + // canvas reference or Unity loader status changes. const initializeUnity = async () => { - console.info({ unityLoaderStatus }); if (!canvasRef || unityInstance || unityLoaderStatus !== "Loaded") { + // If there is no canvas reference, or if the Unity instance is already + // initialized, or if the Unity loader is not ready yet, we simply return. + // This prevents unnecessary re-initialization of the Unity instance. return; } + // Create a new canvas element with the unique ID. + // This ensures that the Unity instance is rendered in the correct canvas. + // The canvas element is created with the ID provided in the props or a + // unique ID generated by the useCanvasIdentifier hook. refreshCanvasId(); - const unityConfig = { + // Create a Unity instance using the createUnityInstance function. + const unityArguments: UnityArguments = { dataUrl: props.unityProvider.dataUrl, frameworkUrl: props.unityProvider.frameworkUrl, codeUrl: props.unityProvider.codeUrl, }; + // The createUnityInstance function is provided by the Unity loader script. + // It initializes the Unity instance with the provided canvas and arguments. + // The function returns a Promise that resolves to the Unity instance. + // We await the Promise to get the Unity instance and set it in the state. + // This allows us to use the Unity instance in the component. setUnityInstance( - await window.createUnityInstance(canvasRef, unityConfig) + await window.createUnityInstance(canvasRef, unityArguments) ); }; + // Function to detach the Unity instance and clean up the canvas. + // This function is called when the component unmounts or when the + // Unity instance is no longer needed. const detachUnity = async () => { if (!unityInstance || !canvasRef) { + // If there is no Unity instance or canvas reference available, + // we simply return to avoid any errors. return; } + // Create a new canvas element to clean up the Unity instance. + // This is necessary to ensure that the Unity instance is properly + // disposed of and the canvas is removed from the DOM. + // The new canvas element is created with the same ID as the original + // canvas element, but with a special attribute to indicate that it is + // a cleanup canvas. const cleanupCanvasRef = document.createElement("canvas"); cleanupCanvasRef.id = canvasRef.id; cleanupCanvasRef.setAttribute("react-unity-webgl-role", "cleanup"); @@ -65,18 +104,30 @@ const Unity: ForwardRefExoticComponent< document.body.removeChild(cleanupCanvasRef); }; + // Initialize the Unity instance when the component mounts or when the + // canvas reference or Unity loader status changes. initializeUnity(); return () => { + // Cleanup the Unity instance and canvas when the component unmounts. + // This ensures that the Unity instance is properly disposed of and + // the canvas is removed from the DOM. detachUnity(); }; }, [canvasRef, unityInstance, unityLoaderStatus, props.unityProvider]); + // Use the forwarded ref to expose the canvas reference to the parent + // component. This allows the parent component to access the canvas element + // directly if needed, for example, to manipulate the canvas or pass it to + // other libraries. useImperativeHandle( forwardedRef, () => canvasRef ); + // If the Unity instance is not ready yet, we return a placeholder canvas + // element with the unique ID. This canvas will be replaced by the Unity + // instance once it is initialized. return createElement("canvas", { ref: setCanvasRef, id: canvasId, From ae0237ece7f3cd46c586bab714bf2faebc266f38 Mon Sep 17 00:00:00 2001 From: Jeffrey Lanters Date: Tue, 15 Jul 2025 15:45:01 +0200 Subject: [PATCH 037/194] Fix canvas ID generation to prevent incrementing canvas count prematurely --- module/source/hooks/use-canvas-identifier.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/module/source/hooks/use-canvas-identifier.ts b/module/source/hooks/use-canvas-identifier.ts index 1f044ce4..38d62598 100644 --- a/module/source/hooks/use-canvas-identifier.ts +++ b/module/source/hooks/use-canvas-identifier.ts @@ -45,7 +45,7 @@ const useCanvasIdentifier = (id?: string): [string, VoidFunction] => { // The Unity canvas ID is generated by concatenating the Unity canvas ID // prefix with the canvas count. Every time this value is requested, the // canvas count is incremented. - return [canvasIdPrefix, ++unityCanvasCount].join("-"); + return [canvasIdPrefix, unityCanvasCount].join("-"); }, [canvasIncremention]); return [canvasId, refreshCanvasId]; From 1bee99f16d826a15f5c7157e1016c79d89c8015c Mon Sep 17 00:00:00 2001 From: Jeffrey Lanters Date: Tue, 15 Jul 2025 15:46:42 +0200 Subject: [PATCH 038/194] Refactor event parameter types to unify Unity event handling and remove React-specific types --- module/declarations/global.d.ts | 4 ++-- module/source/components/unity.ts | 1 - module/source/hooks/use-canvas-identifier.ts | 1 - ...nity-event-parameters.d.ts => unity-event-parameters.d.ts} | 4 ++-- module/source/types/unity-instance.d.ts | 4 ++-- 5 files changed, 6 insertions(+), 8 deletions(-) rename module/source/types/{react-unity-event-parameters.d.ts => unity-event-parameters.d.ts} (92%) diff --git a/module/declarations/global.d.ts b/module/declarations/global.d.ts index 8946d386..7dfd59c3 100644 --- a/module/declarations/global.d.ts +++ b/module/declarations/global.d.ts @@ -1,4 +1,4 @@ -import { ReactUnityEventParameter } from "../source/types/react-unity-event-parameters"; +import { UnityEventParameter } from "../source/types/unity-event-parameters"; import { UnityArguments } from "../source/types/unity-arguments"; import { UnityInstance } from "../source/types/unity-instance"; @@ -13,7 +13,7 @@ declare global { */ function dispatchReactUnityEvent( eventName: string, - ...parameters: ReactUnityEventParameter[] + ...parameters: UnityEventParameter[] ): void; /** diff --git a/module/source/components/unity.ts b/module/source/components/unity.ts index 8d11921d..d7ff2195 100644 --- a/module/source/components/unity.ts +++ b/module/source/components/unity.ts @@ -11,7 +11,6 @@ import { UnityInstance } from "../types/unity-instance"; import { UnityProps } from "../types/unity-props"; import { useCanvasIdentifier } from "../hooks/use-canvas-identifier"; import { useUnityLoader } from "../hooks/use-unity-loader"; -import { UnityConfig } from "../types/unity-config"; import { UnityArguments } from "../types/unity-arguments"; const Unity: ForwardRefExoticComponent< diff --git a/module/source/hooks/use-canvas-identifier.ts b/module/source/hooks/use-canvas-identifier.ts index 38d62598..0129ceb1 100644 --- a/module/source/hooks/use-canvas-identifier.ts +++ b/module/source/hooks/use-canvas-identifier.ts @@ -1,5 +1,4 @@ import { useCallback, useMemo, useState } from "react"; -import { UnityProps } from "../types/unity-props"; /** * The canvas count is used to generate a unique Unity canvas ID. diff --git a/module/source/types/react-unity-event-parameters.d.ts b/module/source/types/unity-event-parameters.d.ts similarity index 92% rename from module/source/types/react-unity-event-parameters.d.ts rename to module/source/types/unity-event-parameters.d.ts index 66014b81..1d2837c2 100644 --- a/module/source/types/react-unity-event-parameters.d.ts +++ b/module/source/types/unity-event-parameters.d.ts @@ -22,6 +22,6 @@ * texture objects. WebGL functions can be called on emscripten’s WebGL context, * GLctx. */ -type ReactUnityEventParameter = string | number | undefined | void; +type UnityEventParameter = string | number | undefined | void; -export type { ReactUnityEventParameter }; +export type { UnityEventParameter }; diff --git a/module/source/types/unity-instance.d.ts b/module/source/types/unity-instance.d.ts index cad971c5..58e640d6 100644 --- a/module/source/types/unity-instance.d.ts +++ b/module/source/types/unity-instance.d.ts @@ -1,4 +1,4 @@ -import { ReactUnityEventParameter } from "./react-unity-event-parameters"; +import { UnityEventParameter } from "./unity-event-parameters"; import { UnityBooleanLike } from "./unity-boolean-like"; import { UnityModule } from "./unity-module"; @@ -15,7 +15,7 @@ type UnityInstance = { SendMessage( gameObjectName: string, methodName: string, - parameter?: ReactUnityEventParameter + parameter?: UnityEventParameter ): void; /** From b5477c9723ecbe7ce6fd6c33d27b0bd173cff011 Mon Sep 17 00:00:00 2001 From: Jeffrey Lanters Date: Tue, 15 Jul 2025 16:00:12 +0200 Subject: [PATCH 039/194] Pass loading progression callback to createUnityInstance for enhanced loading feedback --- module/source/components/unity.ts | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/module/source/components/unity.ts b/module/source/components/unity.ts index d7ff2195..c42dfdc1 100644 --- a/module/source/components/unity.ts +++ b/module/source/components/unity.ts @@ -73,7 +73,11 @@ const Unity: ForwardRefExoticComponent< // We await the Promise to get the Unity instance and set it in the state. // This allows us to use the Unity instance in the component. setUnityInstance( - await window.createUnityInstance(canvasRef, unityArguments) + await window.createUnityInstance( + canvasRef, + unityArguments, + props.unityProvider.setLoadingProgression + ) ); }; From b4918f22e95e37f3230751f3a70f414a9e013b9c Mon Sep 17 00:00:00 2001 From: Jeffrey Lanters Date: Tue, 15 Jul 2025 16:00:15 +0200 Subject: [PATCH 040/194] Add loading progression state to useUnityContext for enhanced loading feedback --- module/source/hooks/use-unity-context.ts | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/module/source/hooks/use-unity-context.ts b/module/source/hooks/use-unity-context.ts index 30b75940..6eb6354c 100644 --- a/module/source/hooks/use-unity-context.ts +++ b/module/source/hooks/use-unity-context.ts @@ -1,18 +1,22 @@ -import { useRef } from "react"; +import { useRef, useState } from "react"; import { UnityConfig } from "../types/unity-config"; import { UnityContext } from "../types/unity-context"; import { UnityProvider } from "../types/unity-provider"; const useUnityContext = (unityConfig: UnityConfig): UnityContext => { + const [loadingProgression, setLoadingProgression] = useState(0); + const unityProvider = useRef({ codeUrl: unityConfig.codeUrl, dataUrl: unityConfig.dataUrl, frameworkUrl: unityConfig.frameworkUrl, loaderUrl: unityConfig.loaderUrl, + setLoadingProgression: setLoadingProgression, }); return { unityProvider: unityProvider.current, + loadingProgression, }; }; From f36f6b6dcea26fa953b92689347e9dfd5cb4b0ad Mon Sep 17 00:00:00 2001 From: Jeffrey Lanters Date: Tue, 15 Jul 2025 16:00:19 +0200 Subject: [PATCH 041/194] Add loading progression property to UnityContext type for improved loading feedback --- module/source/types/unity-context.d.ts | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/module/source/types/unity-context.d.ts b/module/source/types/unity-context.d.ts index 8c6c8cea..2600dab5 100644 --- a/module/source/types/unity-context.d.ts +++ b/module/source/types/unity-context.d.ts @@ -7,6 +7,12 @@ type UnityContext = { * Unity Context's state. */ readonly unityProvider: UnityProvider; + + /** + * The Unity Instance's loading progression represents the percentage of the + * Unity Instance's loading process that has been completed. + */ + readonly loadingProgression: number; }; export type { UnityContext }; From 29b8d5c6b4d03fe40917b43932db1d8cd62b7590 Mon Sep 17 00:00:00 2001 From: Jeffrey Lanters Date: Tue, 15 Jul 2025 16:00:23 +0200 Subject: [PATCH 042/194] Add setLoadingProgression method to UnityProvider type for loading feedback --- module/source/types/unity-provider.d.ts | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/module/source/types/unity-provider.d.ts b/module/source/types/unity-provider.d.ts index e6c476c4..9171a5bf 100644 --- a/module/source/types/unity-provider.d.ts +++ b/module/source/types/unity-provider.d.ts @@ -3,6 +3,11 @@ import { UnityConfig } from "./unity-config"; type UnityProvider = Pick< UnityConfig, "loaderUrl" | "dataUrl" | "frameworkUrl" | "codeUrl" -> & {}; +> & { + /** + * Sets the Unity Context's loading progression. + */ + readonly setLoadingProgression: (loadingProgression: number) => void; +}; export type { UnityProvider }; From 6bf610d86e42ca370ddbb64429abdb0d0f4eb4fa Mon Sep 17 00:00:00 2001 From: Jeffrey Lanters Date: Tue, 15 Jul 2025 16:00:26 +0200 Subject: [PATCH 043/194] Update Application component to display loading progression and adjust initial mount state --- testing/src/application.tsx | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/testing/src/application.tsx b/testing/src/application.tsx index 1d89244f..a94322cc 100644 --- a/testing/src/application.tsx +++ b/testing/src/application.tsx @@ -2,9 +2,9 @@ import { Fragment, useState } from "react"; import { Unity, useUnityContext } from "../../module/source/exports"; export function Application() { - const [isMounted, setIsMounted] = useState(false); + const [isMounted, setIsMounted] = useState(true); - const { unityProvider } = useUnityContext({ + const { unityProvider, loadingProgression } = useUnityContext({ codeUrl: `/unity-build/unity.wasm`, dataUrl: `/unity-build/unity.data`, frameworkUrl: `/unity-build/unity.framework.js`, @@ -17,10 +17,12 @@ export function Application() { +

Loading Progression: {loadingProgression}%

+
{isMounted && ( )} From b236235218fe0e05e748057e672ff9733c8df997 Mon Sep 17 00:00:00 2001 From: Jeffrey Lanters Date: Tue, 15 Jul 2025 16:11:59 +0200 Subject: [PATCH 044/194] Implement loading progression callback in Unity component for enhanced loading feedback --- module/source/components/unity.ts | 33 ++++++++++++++++++++++++++++++- 1 file changed, 32 insertions(+), 1 deletion(-) diff --git a/module/source/components/unity.ts b/module/source/components/unity.ts index c42dfdc1..bdc385e4 100644 --- a/module/source/components/unity.ts +++ b/module/source/components/unity.ts @@ -6,6 +6,7 @@ import { ForwardRefExoticComponent, JSX, useImperativeHandle, + useCallback, } from "react"; import { UnityInstance } from "../types/unity-instance"; import { UnityProps } from "../types/unity-props"; @@ -40,6 +41,26 @@ const Unity: ForwardRefExoticComponent< // determine if the Unity instance is ready to be initialized. const unityLoaderStatus = useUnityLoader(props.unityProvider.loaderUrl); + /** + * Callback function to handle the Unity loading progression. + * This function is called by the Unity loader to update the loading + * progression of the Unity instance. + * @param progress The loading progression of the Unity instance. + */ + const onUnityProgress = useCallback( + (progress: number) => { + // This function is called to update the loading progression of the Unity + // instance. + props.unityProvider.setLoadingProgression(progress); + if (progress === 1) { + // If the loading progression reaches 100%, we can set the isLoaded state + // to true. + props.unityProvider.setIsLoaded?.(true); + } + }, + [props.unityProvider] + ); + // Effect to initialize the Unity instance when the component mounts or // when the canvas reference or Unity loader status changes. useEffect(() => { @@ -54,6 +75,8 @@ const Unity: ForwardRefExoticComponent< return; } + console.log("React Unity WebGL: Initializing Unity instance..."); + // Create a new canvas element with the unique ID. // This ensures that the Unity instance is rendered in the correct canvas. // The canvas element is created with the ID provided in the props or a @@ -76,7 +99,7 @@ const Unity: ForwardRefExoticComponent< await window.createUnityInstance( canvasRef, unityArguments, - props.unityProvider.setLoadingProgression + onUnityProgress ) ); }; @@ -91,6 +114,14 @@ const Unity: ForwardRefExoticComponent< return; } + console.log("React Unity WebGL: Detaching Unity instance..."); + + // Reset the loading progression and isLoaded state to their initial + // values. This is important to ensure that the Unity context is + // properly reset when the Unity instance is detached. + props.unityProvider.setLoadingProgression(0); + props.unityProvider.setIsLoaded?.(false); + // Create a new canvas element to clean up the Unity instance. // This is necessary to ensure that the Unity instance is properly // disposed of and the canvas is removed from the DOM. From 5d0237fd4e465ea8c9db9293fca13c4ed011d8af Mon Sep 17 00:00:00 2001 From: Jeffrey Lanters Date: Tue, 15 Jul 2025 16:12:02 +0200 Subject: [PATCH 045/194] Add isLoaded state to useUnityContext for tracking loading completion --- module/source/hooks/use-unity-context.ts | 3 +++ 1 file changed, 3 insertions(+) diff --git a/module/source/hooks/use-unity-context.ts b/module/source/hooks/use-unity-context.ts index 6eb6354c..43be6af6 100644 --- a/module/source/hooks/use-unity-context.ts +++ b/module/source/hooks/use-unity-context.ts @@ -5,6 +5,7 @@ import { UnityProvider } from "../types/unity-provider"; const useUnityContext = (unityConfig: UnityConfig): UnityContext => { const [loadingProgression, setLoadingProgression] = useState(0); + const [isLoaded, setIsLoaded] = useState(false); const unityProvider = useRef({ codeUrl: unityConfig.codeUrl, @@ -12,11 +13,13 @@ const useUnityContext = (unityConfig: UnityConfig): UnityContext => { frameworkUrl: unityConfig.frameworkUrl, loaderUrl: unityConfig.loaderUrl, setLoadingProgression: setLoadingProgression, + setIsLoaded: setIsLoaded, }); return { unityProvider: unityProvider.current, loadingProgression, + isLoaded, }; }; From 8d1ae0ecad25793da0892cc11d582e8f3298d53d Mon Sep 17 00:00:00 2001 From: Jeffrey Lanters Date: Tue, 15 Jul 2025 16:12:05 +0200 Subject: [PATCH 046/194] Add isLoaded property to UnityContext type for loading state tracking --- module/source/types/unity-context.d.ts | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/module/source/types/unity-context.d.ts b/module/source/types/unity-context.d.ts index 2600dab5..23500c69 100644 --- a/module/source/types/unity-context.d.ts +++ b/module/source/types/unity-context.d.ts @@ -13,6 +13,11 @@ type UnityContext = { * Unity Instance's loading process that has been completed. */ readonly loadingProgression: number; + + /** + * Defines whether the Unity Instance has been loaded. + */ + readonly isLoaded: boolean; }; export type { UnityContext }; From 54b8c125910c67f478efed5b159a875db9ebada7 Mon Sep 17 00:00:00 2001 From: Jeffrey Lanters Date: Tue, 15 Jul 2025 16:12:09 +0200 Subject: [PATCH 047/194] Add optional setIsLoaded method to UnityProvider type for loading state management --- module/source/types/unity-provider.d.ts | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/module/source/types/unity-provider.d.ts b/module/source/types/unity-provider.d.ts index 9171a5bf..c15d4487 100644 --- a/module/source/types/unity-provider.d.ts +++ b/module/source/types/unity-provider.d.ts @@ -8,6 +8,11 @@ type UnityProvider = Pick< * Sets the Unity Context's loading progression. */ readonly setLoadingProgression: (loadingProgression: number) => void; + + /** + * Sets the Unity Context's loaded state. + */ + readonly setIsLoaded?: (isLoaded: boolean) => void; }; export type { UnityProvider }; From e422dc7bd28a4a060b92e58a1b2e723ea38986fa Mon Sep 17 00:00:00 2001 From: Jeffrey Lanters Date: Tue, 15 Jul 2025 16:12:12 +0200 Subject: [PATCH 048/194] Export UnityEventParameter type from exports.ts for improved type accessibility --- module/source/exports.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/module/source/exports.ts b/module/source/exports.ts index 90e8079d..5604a0b6 100644 --- a/module/source/exports.ts +++ b/module/source/exports.ts @@ -1,4 +1,6 @@ import { Unity } from "./components/unity"; import { useUnityContext } from "./hooks/use-unity-context"; +import { UnityEventParameter } from "./types/unity-event-parameters"; export { Unity, useUnityContext }; +export type { UnityEventParameter }; From d9005024a7217155ce159aaa429f492f59d61de1 Mon Sep 17 00:00:00 2001 From: Jeffrey Lanters Date: Tue, 15 Jul 2025 16:12:15 +0200 Subject: [PATCH 049/194] Enhance Application component with loading state tracking and console logging features --- testing/src/application.tsx | 158 ++++++++++++++++++++++++++++++++++-- 1 file changed, 150 insertions(+), 8 deletions(-) diff --git a/testing/src/application.tsx b/testing/src/application.tsx index a94322cc..86ea1d43 100644 --- a/testing/src/application.tsx +++ b/testing/src/application.tsx @@ -1,30 +1,172 @@ -import { Fragment, useState } from "react"; -import { Unity, useUnityContext } from "../../module/source/exports"; +import { Fragment, useEffect, useRef, useState } from "react"; +import { + Unity, + UnityEventParameter, + useUnityContext, +} from "../../module/source/exports"; export function Application() { - const [isMounted, setIsMounted] = useState(true); + function handleCacheControl(url: string) { + console.log(`Cache control for ${url}`); + return "no-cache"; + } - const { unityProvider, loadingProgression } = useUnityContext({ + const { + loadingProgression, + unityProvider, + isLoaded, + // requestFullscreen, + // requestPointerLock, + // sendMessage, + initialisationError, + // addEventListener, + // removeEventListener, + // takeScreenshot, + // unload, + // UNSAFE__unityInstance, + } = useUnityContext({ codeUrl: `/unity-build/unity.wasm`, dataUrl: `/unity-build/unity.data`, frameworkUrl: `/unity-build/unity.framework.js`, loaderUrl: `/unity-build/unity.loader.js`, + // webglContextAttributes: { + // preserveDrawingBuffer: true, + // }, + // cacheControl: handleCacheControl, }); + const canvasRef = useRef(null); + const [isMounted, setIsMounted] = useState(true); + const [screenshots, setScreenshots] = useState([]); + const [consoleEntries, setConsoleEntries] = useState([]); + const [canvasWidth, setCanvasWidth] = useState(500); + + function handleClickRequestFullScreen() { + // requestFullscreen(true); + } + + function handleClickRequestPointerLock() { + // requestPointerLock(); + } + + function handleClickUnload() { + // unload(); + } + + function handleClickSetRandomCanvasWidth() { + setCanvasWidth(Math.floor(Math.random() * 500) + 250); + } + + function handleClickSetLogText() { + // sendMessage( + // "Persistent", + // "SetLogText", + // "Hello World, the time is " + new Date().toISOString() + // ); + } + + function handleClickLogCanvasRefToConsole() { + console.log("Canvas Reference", { canvasRef: canvasRef.current }); + } + + function handleClickLogUnityInstanceRefToConsole() { + // console.log("Unity Instance Reference", { UNSAFE__unityInstance }); + } + + function handleClickTakeScreenshot() { + // const screenshot = takeScreenshot("image/jpg", 1); + // if (screenshot) { + // setScreenshots([...screenshots, screenshot]); + // } + } + + useEffect(() => { + function logParametersToConsole(...parameters: UnityEventParameter[]) { + setConsoleEntries((entries) => [ + ...entries, + `Event: ${parameters.join(", ")}`, + ]); + } + + // addEventListener("ClickedTestButton", logParametersToConsole); + // addEventListener("ClickedStringTestButton", logParametersToConsole); + // addEventListener("ClickedNumberTestButton", logParametersToConsole); + // addEventListener("ClickedNumbersTestButton", logParametersToConsole); + // addEventListener("ClickedBoolTestButton", logParametersToConsole); + // addEventListener("ClickedObjectTestButton", logParametersToConsole); + return () => { + // removeEventListener("ClickedTestButton", logParametersToConsole); + // removeEventListener("ClickedStringTestButton", logParametersToConsole); + // removeEventListener("ClickedNumberTestButton", logParametersToConsole); + // removeEventListener("ClickedNumbersTestButton", logParametersToConsole); + // removeEventListener("ClickedBoolTestButton", logParametersToConsole); + // removeEventListener("ClickedObjectTestButton", logParametersToConsole); + }; + }, [addEventListener, removeEventListener]); + return (

Unity Test

- + -

Loading Progression: {loadingProgression}%


+ Actions: + + + +
+ Screenshots: + + {screenshots.map((screenshot, index) => ( + Screenshot + ))} +
+ Communication: + +
+ Other: + + +

Unity

{isMounted && ( )} +

Console

+ + {consoleEntries.map((entry, index) => ( +
{entry}
+ ))} +
); } From a342974d6609520476cf7e0a4a6751d2b275eb5a Mon Sep 17 00:00:00 2001 From: Jeffrey Lanters Date: Tue, 15 Jul 2025 16:24:11 +0200 Subject: [PATCH 050/194] Reset loading state and handle initialization errors in Unity component --- module/source/components/unity.ts | 32 +++++++++++++++++++++++++++---- 1 file changed, 28 insertions(+), 4 deletions(-) diff --git a/module/source/components/unity.ts b/module/source/components/unity.ts index bdc385e4..661680b6 100644 --- a/module/source/components/unity.ts +++ b/module/source/components/unity.ts @@ -77,6 +77,13 @@ const Unity: ForwardRefExoticComponent< console.log("React Unity WebGL: Initializing Unity instance..."); + // Reset the loading progression and isLoaded state to their initial + // values. This is important to ensure that the Unity context is + // properly reset when the Unity instance is detached. + props.unityProvider.setLoadingProgression(0); + props.unityProvider.setIsLoaded?.(false); + props.unityProvider.setInitialisationError(undefined); + // Create a new canvas element with the unique ID. // This ensures that the Unity instance is rendered in the correct canvas. // The canvas element is created with the ID provided in the props or a @@ -95,13 +102,29 @@ const Unity: ForwardRefExoticComponent< // The function returns a Promise that resolves to the Unity instance. // We await the Promise to get the Unity instance and set it in the state. // This allows us to use the Unity instance in the component. - setUnityInstance( - await window.createUnityInstance( + try { + const unityInstance = await window.createUnityInstance( canvasRef, unityArguments, onUnityProgress - ) - ); + ); + + // If the Unity instance is successfully created, we set it in the state. + // This allows us to use the Unity instance in the component. + setUnityInstance(unityInstance); + } catch (error) { + // If there is an error during the initialization, we log it to the console. + // This is important for debugging purposes. + console.error( + "React Unity WebGL: Error initializing Unity instance:", + error + ); + // We also set the initialisation error in the Unity provider. + // This allows the parent component to handle the error if needed. + // The initialisation error can be used to display an error message or + // take other actions based on the error. + props.unityProvider.setInitialisationError(error as Error); + } }; // Function to detach the Unity instance and clean up the canvas. @@ -121,6 +144,7 @@ const Unity: ForwardRefExoticComponent< // properly reset when the Unity instance is detached. props.unityProvider.setLoadingProgression(0); props.unityProvider.setIsLoaded?.(false); + props.unityProvider.setInitialisationError(undefined); // Create a new canvas element to clean up the Unity instance. // This is necessary to ensure that the Unity instance is properly From 03c40bd192c7623722dd2bffc77ab4f3601c7eda Mon Sep 17 00:00:00 2001 From: Jeffrey Lanters Date: Tue, 15 Jul 2025 16:24:13 +0200 Subject: [PATCH 051/194] Add initialisationError state management to useUnityContext hook --- module/source/hooks/use-unity-context.ts | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/module/source/hooks/use-unity-context.ts b/module/source/hooks/use-unity-context.ts index 43be6af6..f8d5dd05 100644 --- a/module/source/hooks/use-unity-context.ts +++ b/module/source/hooks/use-unity-context.ts @@ -6,20 +6,23 @@ import { UnityProvider } from "../types/unity-provider"; const useUnityContext = (unityConfig: UnityConfig): UnityContext => { const [loadingProgression, setLoadingProgression] = useState(0); const [isLoaded, setIsLoaded] = useState(false); + const [initialisationError, setInitialisationError] = useState(); const unityProvider = useRef({ codeUrl: unityConfig.codeUrl, dataUrl: unityConfig.dataUrl, frameworkUrl: unityConfig.frameworkUrl, loaderUrl: unityConfig.loaderUrl, - setLoadingProgression: setLoadingProgression, - setIsLoaded: setIsLoaded, + setLoadingProgression, + setIsLoaded, + setInitialisationError, }); return { unityProvider: unityProvider.current, loadingProgression, isLoaded, + initialisationError, }; }; From f305e14604aa3f218db61fcc765739d16edc4c1a Mon Sep 17 00:00:00 2001 From: Jeffrey Lanters Date: Tue, 15 Jul 2025 16:24:16 +0200 Subject: [PATCH 052/194] Add initialisationError property to UnityContext type for error handling --- module/source/types/unity-context.d.ts | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/module/source/types/unity-context.d.ts b/module/source/types/unity-context.d.ts index 23500c69..78a3d796 100644 --- a/module/source/types/unity-context.d.ts +++ b/module/source/types/unity-context.d.ts @@ -18,6 +18,11 @@ type UnityContext = { * Defines whether the Unity Instance has been loaded. */ readonly isLoaded: boolean; + + /** + * The Unity Instance's initialisation error, if any. + */ + readonly initialisationError?: Error; }; export type { UnityContext }; From 9315e2cce63c1726e3fd0fa20fed14e180da909e Mon Sep 17 00:00:00 2001 From: Jeffrey Lanters Date: Tue, 15 Jul 2025 16:24:19 +0200 Subject: [PATCH 053/194] Make setIsLoaded property mandatory in UnityProvider type definition --- module/source/types/unity-provider.d.ts | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/module/source/types/unity-provider.d.ts b/module/source/types/unity-provider.d.ts index c15d4487..b89d4ae9 100644 --- a/module/source/types/unity-provider.d.ts +++ b/module/source/types/unity-provider.d.ts @@ -12,7 +12,12 @@ type UnityProvider = Pick< /** * Sets the Unity Context's loaded state. */ - readonly setIsLoaded?: (isLoaded: boolean) => void; + readonly setIsLoaded: (isLoaded: boolean) => void; + + /** + * Sets the Unity Context's initialisation error. + */ + readonly setInitialisationError: (error?: Error) => void; }; export type { UnityProvider }; From c4d67ad67b3e3a737de3e280dbb3ed0fdf2f4350 Mon Sep 17 00:00:00 2001 From: Jeffrey Lanters Date: Tue, 15 Jul 2025 16:24:21 +0200 Subject: [PATCH 054/194] Use nullish coalescing operator for initialisationError message display --- testing/src/application.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/testing/src/application.tsx b/testing/src/application.tsx index 86ea1d43..1f934edc 100644 --- a/testing/src/application.tsx +++ b/testing/src/application.tsx @@ -112,7 +112,7 @@ export function Application() {
Loaded: {isLoaded ? "YES" : "NO"}
- Error: {initialisationError?.message || "NONE"} + Error: {initialisationError?.message ?? "NONE"}

Actions

References: From ad574e1599afdb1eda0e836104cc40e82c92f107 Mon Sep 17 00:00:00 2001 From: Jeffrey Lanters Date: Tue, 15 Jul 2025 16:27:41 +0200 Subject: [PATCH 055/194] Add devicePixelRatio to Unity instance creation for improved rendering --- module/source/components/unity.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/module/source/components/unity.ts b/module/source/components/unity.ts index 661680b6..1dac7014 100644 --- a/module/source/components/unity.ts +++ b/module/source/components/unity.ts @@ -95,6 +95,7 @@ const Unity: ForwardRefExoticComponent< dataUrl: props.unityProvider.dataUrl, frameworkUrl: props.unityProvider.frameworkUrl, codeUrl: props.unityProvider.codeUrl, + devicePixelRatio: props.devicePixelRatio, }; // The createUnityInstance function is provided by the Unity loader script. From fd4ae0ddc14e8fe89b418a3a0c447e31666e4fee Mon Sep 17 00:00:00 2001 From: Jeffrey Lanters Date: Tue, 15 Jul 2025 16:27:44 +0200 Subject: [PATCH 056/194] Refactor UnityProps type to include devicePixelRatio from UnityArguments --- module/source/types/unity-props.d.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/module/source/types/unity-props.d.ts b/module/source/types/unity-props.d.ts index 1ee5c21d..1d25434b 100644 --- a/module/source/types/unity-props.d.ts +++ b/module/source/types/unity-props.d.ts @@ -1,7 +1,8 @@ import { CSSProperties } from "react"; import { UnityProvider } from "./unity-provider"; +import { UnityArguments } from "./unity-arguments"; -type UnityProps = { +type UnityProps = Pick & { /** * The Unity provider that contains the necessary URLs to load the Unity * instance. This is required to load the Unity WebGL build. From 874ce7d83938d3b0f2f43e2acae7aba8a0d49bb1 Mon Sep 17 00:00:00 2001 From: Jeffrey Lanters Date: Tue, 15 Jul 2025 16:27:47 +0200 Subject: [PATCH 057/194] Add devicePixelRatio to canvas for improved rendering quality --- testing/src/application.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/testing/src/application.tsx b/testing/src/application.tsx index 1f934edc..ed087889 100644 --- a/testing/src/application.tsx +++ b/testing/src/application.tsx @@ -155,7 +155,7 @@ export function Application() { height: 400, width: canvasWidth, }} - // devicePixelRatio={window.devicePixelRatio} + devicePixelRatio={window.devicePixelRatio} // disabledCanvasEvents={["dragstart"]} ref={canvasRef} // id="my-custom-cancas-id" From 22e7a67b34c573062c349cde774cca1218199aee Mon Sep 17 00:00:00 2001 From: Jeffrey Lanters Date: Tue, 15 Jul 2025 16:58:16 +0200 Subject: [PATCH 058/194] Enhance documentation for useUnityContext hook and Unity component error handling --- module/source/components/unity.ts | 1 + module/source/hooks/use-unity-context.ts | 14 ++++++++++++++ 2 files changed, 15 insertions(+) diff --git a/module/source/components/unity.ts b/module/source/components/unity.ts index 1dac7014..6477bf83 100644 --- a/module/source/components/unity.ts +++ b/module/source/components/unity.ts @@ -120,6 +120,7 @@ const Unity: ForwardRefExoticComponent< "React Unity WebGL: Error initializing Unity instance:", error ); + // We also set the initialisation error in the Unity provider. // This allows the parent component to handle the error if needed. // The initialisation error can be used to display an error message or diff --git a/module/source/hooks/use-unity-context.ts b/module/source/hooks/use-unity-context.ts index f8d5dd05..f1297baa 100644 --- a/module/source/hooks/use-unity-context.ts +++ b/module/source/hooks/use-unity-context.ts @@ -3,11 +3,22 @@ import { UnityConfig } from "../types/unity-config"; import { UnityContext } from "../types/unity-context"; import { UnityProvider } from "../types/unity-provider"; +/** + * Custom hook to create a Unity context. + * This hook initializes the Unity instance and provides the necessary state and methods. + * + * @param unityConfig - Configuration object for the Unity instance. + * @returns An object containing the Unity context state and methods. + */ const useUnityContext = (unityConfig: UnityConfig): UnityContext => { const [loadingProgression, setLoadingProgression] = useState(0); const [isLoaded, setIsLoaded] = useState(false); const [initialisationError, setInitialisationError] = useState(); + // Create a ref to hold the UnityProvider instance + // This allows us to keep the same instance across renders + // while still being able to update its properties + // without causing unnecessary re-renders. const unityProvider = useRef({ codeUrl: unityConfig.codeUrl, dataUrl: unityConfig.dataUrl, @@ -18,6 +29,9 @@ const useUnityContext = (unityConfig: UnityConfig): UnityContext => { setInitialisationError, }); + // Initialize the UnityProvider with the provided configuration + // This is where you would typically load the Unity instance + // and set up event listeners, etc. return { unityProvider: unityProvider.current, loadingProgression, From 8e9dfc4f87a62e9182db4c5ad5d614c438bd5349 Mon Sep 17 00:00:00 2001 From: Jeffrey Lanters Date: Tue, 15 Jul 2025 16:58:20 +0200 Subject: [PATCH 059/194] Enable requestFullscreen functionality in Application component --- testing/src/application.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/testing/src/application.tsx b/testing/src/application.tsx index ed087889..8001e131 100644 --- a/testing/src/application.tsx +++ b/testing/src/application.tsx @@ -15,7 +15,7 @@ export function Application() { loadingProgression, unityProvider, isLoaded, - // requestFullscreen, + requestFullscreen, // requestPointerLock, // sendMessage, initialisationError, From b287415899bc6c9ff5cd42c101905da5446bab7f Mon Sep 17 00:00:00 2001 From: Jeffrey Lanters Date: Wed, 16 Jul 2025 11:01:24 +0200 Subject: [PATCH 060/194] Refactor UnityInstance type declaration to use Pick for improved clarity and maintainability --- module/source/types/unity-instance.d.ts | 29 ++++--------------------- 1 file changed, 4 insertions(+), 25 deletions(-) diff --git a/module/source/types/unity-instance.d.ts b/module/source/types/unity-instance.d.ts index 58e640d6..d1dd6326 100644 --- a/module/source/types/unity-instance.d.ts +++ b/module/source/types/unity-instance.d.ts @@ -5,31 +5,10 @@ import { UnityModule } from "./unity-module"; /** * Type declaration for the UnityInstance. */ -type UnityInstance = { - /** - * Sends a message to the UnityInstance to invoke a public method. - * @param gameObjectName the name of the game object in your Unity scene. - * @param methodName the name of the public method on the game object. - * @param parameter an optional parameter to pass along to the method. - */ - SendMessage( - gameObjectName: string, - methodName: string, - parameter?: UnityEventParameter - ): void; - - /** - * Enables or disabled the fullscreen mode of the UnityInstance. - * @param fullScreen sets the fullscreen mode. - */ - SetFullscreen(fullScreen: UnityBooleanLike): void; - - /** - * Quits the Unity WebGL application and removes it from the memory. - * @returns a promise which resolves when the application did quit. - */ - Quit(): Promise; - +type UnityInstance = Pick< + UnityModule, + "SendMessage" | "SetFullscreen" | "Quit" +> & { /** * The internal Unity Module. */ From 62b22feffd386d23df5a77906a7bbcbb2a676df5 Mon Sep 17 00:00:00 2001 From: Jeffrey Lanters Date: Wed, 16 Jul 2025 11:11:51 +0200 Subject: [PATCH 061/194] Refactor UnityInstance type declaration to include Quit method for improved functionality --- module/source/types/unity-instance.d.ts | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/module/source/types/unity-instance.d.ts b/module/source/types/unity-instance.d.ts index d1dd6326..df0ac1e4 100644 --- a/module/source/types/unity-instance.d.ts +++ b/module/source/types/unity-instance.d.ts @@ -5,10 +5,13 @@ import { UnityModule } from "./unity-module"; /** * Type declaration for the UnityInstance. */ -type UnityInstance = Pick< - UnityModule, - "SendMessage" | "SetFullscreen" | "Quit" -> & { +type UnityInstance = Pick & { + /** + * Quits the Unity WebGL application and removes it from the memory. + * @returns a promise which resolves when the application did quit. + */ + Quit(): Promise; + /** * The internal Unity Module. */ From 0bbdda37370050c0856a6ed2b3ced2a7fa34cd3d Mon Sep 17 00:00:00 2001 From: Jeffrey Lanters Date: Wed, 16 Jul 2025 11:11:54 +0200 Subject: [PATCH 062/194] Refactor UnityModule type declaration to improve structure and add missing properties --- module/source/types/unity-module.d.ts | 62 +++++++++++++++++++++++++-- 1 file changed, 59 insertions(+), 3 deletions(-) diff --git a/module/source/types/unity-module.d.ts b/module/source/types/unity-module.d.ts index ca130073..c2ef0516 100644 --- a/module/source/types/unity-module.d.ts +++ b/module/source/types/unity-module.d.ts @@ -1,9 +1,19 @@ import { UnityBooleanLike } from "./unity-boolean-like"; +import { UnityEventParameter } from "./unity-event-parameters"; /** * Type declaration for the UnityModule. */ type UnityModule = { + HEAP8: Int8Array; + HEAP16: Int16Array; + HEAP32: Int32Array; + HEAPF32: Float32Array; + HEAPF64: Float64Array; + HEAPU8: Uint8Array; + HEAPU16: Uint16Array; + HEAPU32: Uint32Array; + /** * Stringifies a pointer to a string. * @param pointer The pointer to the string. @@ -13,10 +23,21 @@ type UnityModule = { Pointer_stringify(pointer: number, length: number): string; /** - * Converts a pointer to a string. - * @param pointer The pointer to the string. + * Cleans up the UnityInstance and releases resources. */ - UTF8ToString(pointer: number): string; + QuitCleanup: VoidFunction; + + /** + * Sends a message to the UnityInstance to invoke a public method. + * @param gameObjectName the name of the game object in your Unity scene. + * @param methodName the name of the public method on the game object. + * @param parameter an optional parameter to pass along to the method. + */ + SendMessage( + gameObjectName: string, + methodName: string, + parameter?: UnityEventParameter + ): void; /** * Enables or disabled the fullscreen mode of the UnityInstance. @@ -24,10 +45,45 @@ type UnityModule = { */ SetFullscreen(fullScreen: UnityBooleanLike): void; + /** + * Returns the current system information of the UnityInstance. + * @returns An object containing system information. + */ + SystemInfo: { + browser: string; + browserVersion: string; + gpu: string; + hasCursorLock: boolean; + hasFullscreen: boolean; + hasThreads: boolean; + hasWasm: boolean; + hasWasmThreads: boolean; + hasWebGL: 2 | 1; + height: number; + language: string; + mobile: boolean; + os: string; + osVersion: string; + userAgent: string; + width: number; + }; + + /** + * Converts a pointer to a string. + * @param pointer The pointer to the string. + */ + UTF8ToString(pointer: number): string; + /** * A reference to the Unity Instance's Canvas. */ canvas?: HTMLCanvasElement; + + /** + * A reference to the Unity Instance's WebGL context attributes. + * This is used to configure the WebGL context for the Unity instance. + */ + webglContextAttributes: WebGLContextAttributes; }; export type { UnityModule }; From fd2a89103550d40e542b2ed242229f18225666a5 Mon Sep 17 00:00:00 2001 From: Jeffrey Lanters Date: Wed, 16 Jul 2025 11:12:04 +0200 Subject: [PATCH 063/194] Remove unused imports from UnityInstance type declaration for cleaner code --- module/source/types/unity-instance.d.ts | 2 -- 1 file changed, 2 deletions(-) diff --git a/module/source/types/unity-instance.d.ts b/module/source/types/unity-instance.d.ts index df0ac1e4..b881363c 100644 --- a/module/source/types/unity-instance.d.ts +++ b/module/source/types/unity-instance.d.ts @@ -1,5 +1,3 @@ -import { UnityEventParameter } from "./unity-event-parameters"; -import { UnityBooleanLike } from "./unity-boolean-like"; import { UnityModule } from "./unity-module"; /** From a5acf4d982ac15d890089541cc732b905343ed59 Mon Sep 17 00:00:00 2001 From: Jeffrey Lanters Date: Wed, 16 Jul 2025 11:23:05 +0200 Subject: [PATCH 064/194] Enable requestFullscreen functionality and add missing properties in Application component --- testing/src/application.tsx | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/testing/src/application.tsx b/testing/src/application.tsx index 8001e131..adeb1bb4 100644 --- a/testing/src/application.tsx +++ b/testing/src/application.tsx @@ -33,6 +33,13 @@ export function Application() { // preserveDrawingBuffer: true, // }, // cacheControl: handleCacheControl, + companyName: "Unity Technologies", + productName: "Communication Tests", + productVersion: "1.0.0", + // memoryUrl: `/unity-build/communication-tests.mem`, + // streamingAssetsUrl: `/unity-build/StreamingAssets`, + // symbolsUrl: `/unity-build/communication-tests.symbols.json`, + // workerUrl: `/unity-build/communication-tests.worker.js`, }); const canvasRef = useRef(null); @@ -42,7 +49,7 @@ export function Application() { const [canvasWidth, setCanvasWidth] = useState(500); function handleClickRequestFullScreen() { - // requestFullscreen(true); + requestFullscreen(true); } function handleClickRequestPointerLock() { From eb16ebdc9359d67bcbb5b8624d479a1793f095ff Mon Sep 17 00:00:00 2001 From: Jeffrey Lanters Date: Wed, 16 Jul 2025 11:23:09 +0200 Subject: [PATCH 065/194] Refactor UnityProvider type declaration to include additional properties for improved functionality --- module/source/types/unity-provider.d.ts | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/module/source/types/unity-provider.d.ts b/module/source/types/unity-provider.d.ts index b89d4ae9..f70a4a1a 100644 --- a/module/source/types/unity-provider.d.ts +++ b/module/source/types/unity-provider.d.ts @@ -2,7 +2,13 @@ import { UnityConfig } from "./unity-config"; type UnityProvider = Pick< UnityConfig, - "loaderUrl" | "dataUrl" | "frameworkUrl" | "codeUrl" + | "loaderUrl" + | "dataUrl" + | "frameworkUrl" + | "codeUrl" + | "companyName" + | "productName" + | "productVersion" > & { /** * Sets the Unity Context's loading progression. From c2017865763b15ff0f71ea393772162a34eeb5d1 Mon Sep 17 00:00:00 2001 From: Jeffrey Lanters Date: Wed, 16 Jul 2025 11:23:14 +0200 Subject: [PATCH 066/194] Refactor UnityConfig type declaration to include additional properties for improved functionality --- module/source/types/unity-config.d.ts | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/module/source/types/unity-config.d.ts b/module/source/types/unity-config.d.ts index 6b091fb1..caf987fa 100644 --- a/module/source/types/unity-config.d.ts +++ b/module/source/types/unity-config.d.ts @@ -2,7 +2,12 @@ import { UnityArguments } from "./unity-arguments"; type UnityConfig = Pick< UnityArguments, - "dataUrl" | "frameworkUrl" | "codeUrl" + | "dataUrl" + | "frameworkUrl" + | "codeUrl" + | "companyName" + | "productName" + | "productVersion" > & { /** * The url to the build json file generated by Unity. When using a relative url, From 93d94917d5b70d4c2af5bdd4efb9d5d5b0a5d13c Mon Sep 17 00:00:00 2001 From: Jeffrey Lanters Date: Wed, 16 Jul 2025 11:23:28 +0200 Subject: [PATCH 067/194] Refactor useUnityContext to include companyName, productName, and productVersion in UnityProvider initialization --- module/source/hooks/use-unity-context.ts | 3 +++ 1 file changed, 3 insertions(+) diff --git a/module/source/hooks/use-unity-context.ts b/module/source/hooks/use-unity-context.ts index f1297baa..08ee51f3 100644 --- a/module/source/hooks/use-unity-context.ts +++ b/module/source/hooks/use-unity-context.ts @@ -20,6 +20,9 @@ const useUnityContext = (unityConfig: UnityConfig): UnityContext => { // while still being able to update its properties // without causing unnecessary re-renders. const unityProvider = useRef({ + companyName: unityConfig.companyName, + productName: unityConfig.productName, + productVersion: unityConfig.productVersion, codeUrl: unityConfig.codeUrl, dataUrl: unityConfig.dataUrl, frameworkUrl: unityConfig.frameworkUrl, From 1f0ebf57efae69900415510abf626cf0fad4ab1e Mon Sep 17 00:00:00 2001 From: Jeffrey Lanters Date: Wed, 16 Jul 2025 11:23:39 +0200 Subject: [PATCH 068/194] Add companyName, productName, and productVersion to Unity instance creation --- module/source/components/unity.ts | 3 +++ 1 file changed, 3 insertions(+) diff --git a/module/source/components/unity.ts b/module/source/components/unity.ts index 6477bf83..d2cc7dc5 100644 --- a/module/source/components/unity.ts +++ b/module/source/components/unity.ts @@ -92,6 +92,9 @@ const Unity: ForwardRefExoticComponent< // Create a Unity instance using the createUnityInstance function. const unityArguments: UnityArguments = { + companyName: props.unityProvider.companyName, + productName: props.unityProvider.productName, + productVersion: props.unityProvider.productVersion, dataUrl: props.unityProvider.dataUrl, frameworkUrl: props.unityProvider.frameworkUrl, codeUrl: props.unityProvider.codeUrl, From 27030f339999e01c95c74cc40b2735c722e8439c Mon Sep 17 00:00:00 2001 From: Jeffrey Lanters Date: Wed, 16 Jul 2025 11:34:06 +0200 Subject: [PATCH 069/194] Refactor UnityProvider type declaration to include setUnityInstance method for better Unity instance management --- module/source/types/unity-provider.d.ts | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/module/source/types/unity-provider.d.ts b/module/source/types/unity-provider.d.ts index f70a4a1a..29b482f3 100644 --- a/module/source/types/unity-provider.d.ts +++ b/module/source/types/unity-provider.d.ts @@ -1,4 +1,5 @@ import { UnityConfig } from "./unity-config"; +import { UnityInstance } from "./unity-instance"; type UnityProvider = Pick< UnityConfig, @@ -24,6 +25,12 @@ type UnityProvider = Pick< * Sets the Unity Context's initialisation error. */ readonly setInitialisationError: (error?: Error) => void; + + /** + * Sets the Unity instance, used for internally managing the Unity instance + * between the context and the UnityProvider. + */ + readonly setUnityInstance: (unityInstance: UnityInstance | null) => void; }; export type { UnityProvider }; From 0c162baace0e593d49865516ae49c601ea1acc90 Mon Sep 17 00:00:00 2001 From: Jeffrey Lanters Date: Wed, 16 Jul 2025 11:34:12 +0200 Subject: [PATCH 070/194] Refactor UnityContext type declaration to include requestFullscreen method for improved fullscreen management --- module/source/types/unity-context.d.ts | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/module/source/types/unity-context.d.ts b/module/source/types/unity-context.d.ts index 78a3d796..d6897bd6 100644 --- a/module/source/types/unity-context.d.ts +++ b/module/source/types/unity-context.d.ts @@ -23,6 +23,12 @@ type UnityContext = { * The Unity Instance's initialisation error, if any. */ readonly initialisationError?: Error; + + /** + * Requests the Unity Instance to enter or exit fullscreen mode. + * @param enabled - A boolean indicating whether to enter (true) or exit (false) fullscreen mode. + */ + readonly requestFullscreen: (enabled: boolean) => void; }; export type { UnityContext }; From 511c12279e0e67459f0e52a68aaa85bf429509ad Mon Sep 17 00:00:00 2001 From: Jeffrey Lanters Date: Wed, 16 Jul 2025 11:34:25 +0200 Subject: [PATCH 071/194] Refactor useUnityContext to include requestFullscreen method for improved fullscreen control --- module/source/hooks/use-unity-context.ts | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/module/source/hooks/use-unity-context.ts b/module/source/hooks/use-unity-context.ts index 08ee51f3..76736034 100644 --- a/module/source/hooks/use-unity-context.ts +++ b/module/source/hooks/use-unity-context.ts @@ -1,7 +1,8 @@ -import { useRef, useState } from "react"; +import { useCallback, useRef, useState } from "react"; import { UnityConfig } from "../types/unity-config"; import { UnityContext } from "../types/unity-context"; import { UnityProvider } from "../types/unity-provider"; +import { UnityInstance } from "../types/unity-instance"; /** * Custom hook to create a Unity context. @@ -11,6 +12,9 @@ import { UnityProvider } from "../types/unity-provider"; * @returns An object containing the Unity context state and methods. */ const useUnityContext = (unityConfig: UnityConfig): UnityContext => { + const [unityInstance, setUnityInstance] = useState( + null + ); const [loadingProgression, setLoadingProgression] = useState(0); const [isLoaded, setIsLoaded] = useState(false); const [initialisationError, setInitialisationError] = useState(); @@ -27,11 +31,20 @@ const useUnityContext = (unityConfig: UnityConfig): UnityContext => { dataUrl: unityConfig.dataUrl, frameworkUrl: unityConfig.frameworkUrl, loaderUrl: unityConfig.loaderUrl, + setUnityInstance, setLoadingProgression, setIsLoaded, setInitialisationError, }); + /** + * Requests the Unity Instance to enter or exit fullscreen mode. + */ + const requestFullscreen = useCallback( + (enabled: boolean) => unityInstance?.SetFullscreen(enabled ? 1 : 0), + [unityInstance] + ); + // Initialize the UnityProvider with the provided configuration // This is where you would typically load the Unity instance // and set up event listeners, etc. @@ -40,6 +53,7 @@ const useUnityContext = (unityConfig: UnityConfig): UnityContext => { loadingProgression, isLoaded, initialisationError, + requestFullscreen, }; }; From 5f8f4c274a87bb606d88b086b6ed23a9382c4a7c Mon Sep 17 00:00:00 2001 From: Jeffrey Lanters Date: Wed, 16 Jul 2025 11:34:37 +0200 Subject: [PATCH 072/194] Refactor Unity instance management to ensure proper detachment and reset in UnityProvider --- module/source/components/unity.ts | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/module/source/components/unity.ts b/module/source/components/unity.ts index d2cc7dc5..a82ca73f 100644 --- a/module/source/components/unity.ts +++ b/module/source/components/unity.ts @@ -77,6 +77,11 @@ const Unity: ForwardRefExoticComponent< console.log("React Unity WebGL: Initializing Unity instance..."); + // Remove the reference to the previous Unity instance if it exists and + // set the Unity instance in the Unity provider to null. + props.unityProvider.setUnityInstance(null); + setUnityInstance(null); + // Reset the loading progression and isLoaded state to their initial // values. This is important to ensure that the Unity context is // properly reset when the Unity instance is detached. @@ -116,6 +121,10 @@ const Unity: ForwardRefExoticComponent< // If the Unity instance is successfully created, we set it in the state. // This allows us to use the Unity instance in the component. setUnityInstance(unityInstance); + // We also set the Unity instance in the Unity provider. + // This allows the Unity provider to access the Unity instance and + // call its internal methods. + props.unityProvider.setUnityInstance(unityInstance); } catch (error) { // If there is an error during the initialization, we log it to the console. // This is important for debugging purposes. @@ -144,6 +153,11 @@ const Unity: ForwardRefExoticComponent< console.log("React Unity WebGL: Detaching Unity instance..."); + // Remove the reference to the previous Unity instance if it exists and + // set the Unity instance in the Unity provider to null. + props.unityProvider.setUnityInstance(null); + setUnityInstance(null); + // Reset the loading progression and isLoaded state to their initial // values. This is important to ensure that the Unity context is // properly reset when the Unity instance is detached. From 301066ccae87cc7eabef2f74523b1466e07be01e Mon Sep 17 00:00:00 2001 From: Jeffrey Lanters Date: Wed, 16 Jul 2025 11:45:59 +0200 Subject: [PATCH 073/194] Refactor Application component to enable requestPointerLock and sendMessage functionality --- testing/src/application.tsx | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/testing/src/application.tsx b/testing/src/application.tsx index adeb1bb4..77c7a17d 100644 --- a/testing/src/application.tsx +++ b/testing/src/application.tsx @@ -16,14 +16,14 @@ export function Application() { unityProvider, isLoaded, requestFullscreen, - // requestPointerLock, - // sendMessage, + requestPointerLock, + sendMessage, initialisationError, // addEventListener, // removeEventListener, // takeScreenshot, // unload, - // UNSAFE__unityInstance, + UNSAFE__unityInstance, } = useUnityContext({ codeUrl: `/unity-build/unity.wasm`, dataUrl: `/unity-build/unity.data`, @@ -36,10 +36,10 @@ export function Application() { companyName: "Unity Technologies", productName: "Communication Tests", productVersion: "1.0.0", - // memoryUrl: `/unity-build/communication-tests.mem`, - // streamingAssetsUrl: `/unity-build/StreamingAssets`, - // symbolsUrl: `/unity-build/communication-tests.symbols.json`, - // workerUrl: `/unity-build/communication-tests.worker.js`, + // memoryUrl: `/unity-build/communication-tests.mem`, // <- Tested, but not implemented in the demo project + // streamingAssetsUrl: `/unity-build/StreamingAssets`, // <- Tested, but not implemented in the demo project + // symbolsUrl: `/unity-build/communication-tests.symbols.json`, // <- Tested, but not implemented in the demo project + // workerUrl: `/unity-build/communication-tests.worker.js`, // <- Tested, but not implemented in the demo project }); const canvasRef = useRef(null); @@ -53,7 +53,7 @@ export function Application() { } function handleClickRequestPointerLock() { - // requestPointerLock(); + requestPointerLock(); } function handleClickUnload() { @@ -65,11 +65,11 @@ export function Application() { } function handleClickSetLogText() { - // sendMessage( - // "Persistent", - // "SetLogText", - // "Hello World, the time is " + new Date().toISOString() - // ); + sendMessage( + "Persistent", + "SetLogText", + "Hello World, the time is " + new Date().toISOString() + ); } function handleClickLogCanvasRefToConsole() { @@ -77,7 +77,7 @@ export function Application() { } function handleClickLogUnityInstanceRefToConsole() { - // console.log("Unity Instance Reference", { UNSAFE__unityInstance }); + console.log("Unity Instance Reference", { UNSAFE__unityInstance }); } function handleClickTakeScreenshot() { From 651de5f986f30ec73729461a58c25c9ba9ca3b8a Mon Sep 17 00:00:00 2001 From: Jeffrey Lanters Date: Wed, 16 Jul 2025 11:46:04 +0200 Subject: [PATCH 074/194] Refactor UnityProvider type declaration to include additional Unity asset properties for improved configuration --- module/source/types/unity-provider.d.ts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/module/source/types/unity-provider.d.ts b/module/source/types/unity-provider.d.ts index 29b482f3..0975d2e2 100644 --- a/module/source/types/unity-provider.d.ts +++ b/module/source/types/unity-provider.d.ts @@ -7,6 +7,10 @@ type UnityProvider = Pick< | "dataUrl" | "frameworkUrl" | "codeUrl" + | "memoryUrl" + | "symbolsUrl" + | "streamingAssetsUrl" + | "workerUrl" | "companyName" | "productName" | "productVersion" From ca669befe27d4a4f14bb4bf8a031a8e4fd0f3bb3 Mon Sep 17 00:00:00 2001 From: Jeffrey Lanters Date: Wed, 16 Jul 2025 11:46:10 +0200 Subject: [PATCH 075/194] Refactor UnityContext type declaration to include requestPointerLock and UNSAFE__unityInstance for enhanced Unity instance management --- module/source/types/unity-context.d.ts | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/module/source/types/unity-context.d.ts b/module/source/types/unity-context.d.ts index d6897bd6..64816442 100644 --- a/module/source/types/unity-context.d.ts +++ b/module/source/types/unity-context.d.ts @@ -1,3 +1,4 @@ +import { UnityInstance } from "./unity-instance"; import { UnityProvider } from "./unity-provider"; type UnityContext = { @@ -29,6 +30,25 @@ type UnityContext = { * @param enabled - A boolean indicating whether to enter (true) or exit (false) fullscreen mode. */ readonly requestFullscreen: (enabled: boolean) => void; + + /** + * Requests the Unity Instance to enter pointer lock mode. + * Pointer lock mode allows the Unity Instance to capture mouse movements + * without the cursor leaving the Unity canvas. + * This is useful for first-person games or applications where continuous + * mouse movement is required. + */ + readonly requestPointerLock: VoidFunction; + + /** + * An unsafe reference to the Unity Instance. + * This reference should be used with caution, as it may not be available + * at all times, and accessing it may lead to unexpected behavior if the + * Unity Instance is not fully initialized or has been unloaded. + * It is recommended to use the provided methods and properties of the Unity + * Context to interact with the Unity Instance safely. + */ + readonly UNSAFE__unityInstance: UnityInstance | null; }; export type { UnityContext }; From 7ab2f9ab71c2ae2786926c251b0798ee78f86135 Mon Sep 17 00:00:00 2001 From: Jeffrey Lanters Date: Wed, 16 Jul 2025 11:46:15 +0200 Subject: [PATCH 076/194] Refactor UnityConfig type declaration to include additional Unity asset properties for improved configuration --- module/source/types/unity-config.d.ts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/module/source/types/unity-config.d.ts b/module/source/types/unity-config.d.ts index caf987fa..d3f8aafd 100644 --- a/module/source/types/unity-config.d.ts +++ b/module/source/types/unity-config.d.ts @@ -5,6 +5,10 @@ type UnityConfig = Pick< | "dataUrl" | "frameworkUrl" | "codeUrl" + | "workerUrl" + | "streamingAssetsUrl" + | "memoryUrl" + | "symbolsUrl" | "companyName" | "productName" | "productVersion" From 8092119ef16cc3237749a47b09d9bf7604afc2ae Mon Sep 17 00:00:00 2001 From: Jeffrey Lanters Date: Wed, 16 Jul 2025 11:46:20 +0200 Subject: [PATCH 077/194] Refactor useUnityContext to include additional Unity asset properties and enhance requestPointerLock functionality --- module/source/hooks/use-unity-context.ts | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/module/source/hooks/use-unity-context.ts b/module/source/hooks/use-unity-context.ts index 76736034..45d00661 100644 --- a/module/source/hooks/use-unity-context.ts +++ b/module/source/hooks/use-unity-context.ts @@ -31,6 +31,10 @@ const useUnityContext = (unityConfig: UnityConfig): UnityContext => { dataUrl: unityConfig.dataUrl, frameworkUrl: unityConfig.frameworkUrl, loaderUrl: unityConfig.loaderUrl, + memoryUrl: unityConfig.memoryUrl, + symbolsUrl: unityConfig.symbolsUrl, + streamingAssetsUrl: unityConfig.streamingAssetsUrl, + workerUrl: unityConfig.workerUrl, setUnityInstance, setLoadingProgression, setIsLoaded, @@ -45,6 +49,15 @@ const useUnityContext = (unityConfig: UnityConfig): UnityContext => { [unityInstance] ); + /** + * Requests the Unity Instance to enter pointer lock mode. + * Pointer lock mode allows the Unity Instance to capture mouse movements + * without the cursor leaving the Unity canvas. + */ + const requestPointerLock = useCallback(() => { + unityInstance?.Module.canvas?.requestPointerLock(); + }, [unityInstance]); + // Initialize the UnityProvider with the provided configuration // This is where you would typically load the Unity instance // and set up event listeners, etc. @@ -54,6 +67,8 @@ const useUnityContext = (unityConfig: UnityConfig): UnityContext => { isLoaded, initialisationError, requestFullscreen, + requestPointerLock, + UNSAFE__unityInstance: unityInstance, }; }; From de54e2312df124726ae330b26598f275313e404f Mon Sep 17 00:00:00 2001 From: Jeffrey Lanters Date: Wed, 16 Jul 2025 11:46:26 +0200 Subject: [PATCH 078/194] Refactor Unity component to include additional Unity asset properties for improved configuration --- module/source/components/unity.ts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/module/source/components/unity.ts b/module/source/components/unity.ts index a82ca73f..b0c6aa7a 100644 --- a/module/source/components/unity.ts +++ b/module/source/components/unity.ts @@ -103,6 +103,10 @@ const Unity: ForwardRefExoticComponent< dataUrl: props.unityProvider.dataUrl, frameworkUrl: props.unityProvider.frameworkUrl, codeUrl: props.unityProvider.codeUrl, + workerUrl: props.unityProvider.workerUrl, + memoryUrl: props.unityProvider.memoryUrl, + symbolsUrl: props.unityProvider.symbolsUrl, + streamingAssetsUrl: props.unityProvider.streamingAssetsUrl, devicePixelRatio: props.devicePixelRatio, }; From 04ae1f3321800526c6ef8107bd3beaef9d535a05 Mon Sep 17 00:00:00 2001 From: Jeffrey Lanters Date: Wed, 16 Jul 2025 11:52:39 +0200 Subject: [PATCH 079/194] Refactor UnityContext type declaration to include sendMessage method for invoking public methods on Unity instances --- module/source/types/unity-context.d.ts | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/module/source/types/unity-context.d.ts b/module/source/types/unity-context.d.ts index 64816442..33b8261a 100644 --- a/module/source/types/unity-context.d.ts +++ b/module/source/types/unity-context.d.ts @@ -1,3 +1,4 @@ +import { UnityEventParameter } from "./unity-event-parameters"; import { UnityInstance } from "./unity-instance"; import { UnityProvider } from "./unity-provider"; @@ -40,6 +41,18 @@ type UnityContext = { */ readonly requestPointerLock: VoidFunction; + /** + * Sends a message to the UnityInstance to invoke a public method. + * @param gameObjectName the name of the game object in your Unity scene. + * @param methodName the name of the public method on the game object. + * @param parameter an optional parameter to pass along to the method. + */ + readonly sendMessage: ( + gameObjectName: string, + methodName: string, + parameter?: UnityEventParameter + ) => void; + /** * An unsafe reference to the Unity Instance. * This reference should be used with caution, as it may not be available From 529a36e0f303c4452a23ba50a7beaa92c5d2f9da Mon Sep 17 00:00:00 2001 From: Jeffrey Lanters Date: Wed, 16 Jul 2025 11:52:42 +0200 Subject: [PATCH 080/194] Add sendMessage method to useUnityContext for invoking public methods on Unity instances --- module/source/hooks/use-unity-context.ts | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/module/source/hooks/use-unity-context.ts b/module/source/hooks/use-unity-context.ts index 45d00661..41953903 100644 --- a/module/source/hooks/use-unity-context.ts +++ b/module/source/hooks/use-unity-context.ts @@ -3,6 +3,7 @@ import { UnityConfig } from "../types/unity-config"; import { UnityContext } from "../types/unity-context"; import { UnityProvider } from "../types/unity-provider"; import { UnityInstance } from "../types/unity-instance"; +import { UnityEventParameter } from "../exports"; /** * Custom hook to create a Unity context. @@ -58,6 +59,18 @@ const useUnityContext = (unityConfig: UnityConfig): UnityContext => { unityInstance?.Module.canvas?.requestPointerLock(); }, [unityInstance]); + /** + * Sends a message to the Unity Instance to invoke a public method. + */ + const sendMessage = useCallback( + ( + gameObjectName: string, + methodName: string, + parameter?: UnityEventParameter + ) => unityInstance?.SendMessage(gameObjectName, methodName, parameter), + [unityInstance] + ); + // Initialize the UnityProvider with the provided configuration // This is where you would typically load the Unity instance // and set up event listeners, etc. @@ -68,6 +81,7 @@ const useUnityContext = (unityConfig: UnityConfig): UnityContext => { initialisationError, requestFullscreen, requestPointerLock, + sendMessage, UNSAFE__unityInstance: unityInstance, }; }; From f511c49f589685ad999b2177c643bf329ad38d23 Mon Sep 17 00:00:00 2001 From: Jeffrey Lanters Date: Wed, 16 Jul 2025 12:08:11 +0200 Subject: [PATCH 081/194] Enable takeScreenshot functionality in Application component --- testing/src/application.tsx | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/testing/src/application.tsx b/testing/src/application.tsx index 77c7a17d..ee5aa46d 100644 --- a/testing/src/application.tsx +++ b/testing/src/application.tsx @@ -21,7 +21,7 @@ export function Application() { initialisationError, // addEventListener, // removeEventListener, - // takeScreenshot, + takeScreenshot, // unload, UNSAFE__unityInstance, } = useUnityContext({ @@ -81,10 +81,10 @@ export function Application() { } function handleClickTakeScreenshot() { - // const screenshot = takeScreenshot("image/jpg", 1); - // if (screenshot) { - // setScreenshots([...screenshots, screenshot]); - // } + const screenshot = takeScreenshot("image/jpg", 1); + if (screenshot) { + setScreenshots([...screenshots, screenshot]); + } } useEffect(() => { @@ -165,7 +165,7 @@ export function Application() { devicePixelRatio={window.devicePixelRatio} // disabledCanvasEvents={["dragstart"]} ref={canvasRef} - // id="my-custom-cancas-id" + // id="my-custom-cancas-id" // <- Tested, but not implemented in the demo project /> )}

Console

From c6ca53dd2520c6e65e6a63bc636cd8a5b68449e9 Mon Sep 17 00:00:00 2001 From: Jeffrey Lanters Date: Wed, 16 Jul 2025 12:08:16 +0200 Subject: [PATCH 082/194] Add takeScreenshot method to UnityContext for capturing screenshots --- module/source/types/unity-context.d.ts | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/module/source/types/unity-context.d.ts b/module/source/types/unity-context.d.ts index 33b8261a..cecd18aa 100644 --- a/module/source/types/unity-context.d.ts +++ b/module/source/types/unity-context.d.ts @@ -53,6 +53,18 @@ type UnityContext = { parameter?: UnityEventParameter ) => void; + /** + * Takes a screenshot of the Unity Instance and returns a base64 encoded + * string. + * @param type Defines the type of screenshot to take. + * @param quality Defines the quality of the screenshot. + * @returns A base 64 encoded string of the screenshot. + */ + readonly takeScreenshot: ( + dataType?: string, + quality?: number + ) => string | undefined; + /** * An unsafe reference to the Unity Instance. * This reference should be used with caution, as it may not be available From 35e3107689082b10ecced1c5689947505b3b99d0 Mon Sep 17 00:00:00 2001 From: Jeffrey Lanters Date: Wed, 16 Jul 2025 12:08:20 +0200 Subject: [PATCH 083/194] Add takeScreenshot method to useUnityContext for capturing screenshots --- module/source/hooks/use-unity-context.ts | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/module/source/hooks/use-unity-context.ts b/module/source/hooks/use-unity-context.ts index 41953903..48d72a90 100644 --- a/module/source/hooks/use-unity-context.ts +++ b/module/source/hooks/use-unity-context.ts @@ -71,6 +71,19 @@ const useUnityContext = (unityConfig: UnityConfig): UnityContext => { [unityInstance] ); + /** + * Takes a screenshot of the Unity Instance and returns a base64 encoded + * string. + * @param dataType Defines the type of screenshot to take. + * @param quality Defines the quality of the screenshot. + * @returns A base 64 encoded string of the screenshot. + */ + const takeScreenshot = useCallback( + (dataType: string, quality: number): string | undefined => + unityInstance?.Module.canvas?.toDataURL(dataType, quality), + [unityInstance] + ); + // Initialize the UnityProvider with the provided configuration // This is where you would typically load the Unity instance // and set up event listeners, etc. @@ -82,6 +95,7 @@ const useUnityContext = (unityConfig: UnityConfig): UnityContext => { requestFullscreen, requestPointerLock, sendMessage, + takeScreenshot, UNSAFE__unityInstance: unityInstance, }; }; From f2057f74ccd4c49b2b88bad154160b126a02c5fb Mon Sep 17 00:00:00 2001 From: Jeffrey Lanters Date: Wed, 16 Jul 2025 12:10:43 +0200 Subject: [PATCH 084/194] Refactor comments in useUnityContext and update takeScreenshot parameters for optional dataType and quality --- module/source/hooks/use-unity-context.ts | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/module/source/hooks/use-unity-context.ts b/module/source/hooks/use-unity-context.ts index 48d72a90..3867aa69 100644 --- a/module/source/hooks/use-unity-context.ts +++ b/module/source/hooks/use-unity-context.ts @@ -20,10 +20,10 @@ const useUnityContext = (unityConfig: UnityConfig): UnityContext => { const [isLoaded, setIsLoaded] = useState(false); const [initialisationError, setInitialisationError] = useState(); - // Create a ref to hold the UnityProvider instance - // This allows us to keep the same instance across renders - // while still being able to update its properties - // without causing unnecessary re-renders. + // Create a ref to hold the UnityProvider instance, it consists of a selection + // of properties from the UnityConfig and methods to interact with the Unity instance. + // This allows us to avoid unnecessary re-renders when the UnityProvider is updated. + // The useRef hook is used to persist the UnityProvider instance across renders. const unityProvider = useRef({ companyName: unityConfig.companyName, productName: unityConfig.productName, @@ -36,6 +36,7 @@ const useUnityContext = (unityConfig: UnityConfig): UnityContext => { symbolsUrl: unityConfig.symbolsUrl, streamingAssetsUrl: unityConfig.streamingAssetsUrl, workerUrl: unityConfig.workerUrl, + webglContextAttributes: unityConfig.webglContextAttributes, setUnityInstance, setLoadingProgression, setIsLoaded, @@ -79,7 +80,7 @@ const useUnityContext = (unityConfig: UnityConfig): UnityContext => { * @returns A base 64 encoded string of the screenshot. */ const takeScreenshot = useCallback( - (dataType: string, quality: number): string | undefined => + (dataType?: string, quality?: number): string | undefined => unityInstance?.Module.canvas?.toDataURL(dataType, quality), [unityInstance] ); From 8ead86b11ade6e6283de47cd0ed19bc6935c002b Mon Sep 17 00:00:00 2001 From: Jeffrey Lanters Date: Wed, 16 Jul 2025 12:11:10 +0200 Subject: [PATCH 085/194] Enable webglContextAttributes in Application component for preserving drawing buffer --- testing/src/application.tsx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/testing/src/application.tsx b/testing/src/application.tsx index ee5aa46d..a746497a 100644 --- a/testing/src/application.tsx +++ b/testing/src/application.tsx @@ -29,9 +29,9 @@ export function Application() { dataUrl: `/unity-build/unity.data`, frameworkUrl: `/unity-build/unity.framework.js`, loaderUrl: `/unity-build/unity.loader.js`, - // webglContextAttributes: { - // preserveDrawingBuffer: true, - // }, + webglContextAttributes: { + preserveDrawingBuffer: true, + }, // cacheControl: handleCacheControl, companyName: "Unity Technologies", productName: "Communication Tests", From def3cce967204ae41a14698a8da1f35a4edf4bb4 Mon Sep 17 00:00:00 2001 From: Jeffrey Lanters Date: Wed, 16 Jul 2025 12:11:15 +0200 Subject: [PATCH 086/194] Add webglContextAttributes to UnityProvider type definition --- module/source/types/unity-provider.d.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/module/source/types/unity-provider.d.ts b/module/source/types/unity-provider.d.ts index 0975d2e2..741326bc 100644 --- a/module/source/types/unity-provider.d.ts +++ b/module/source/types/unity-provider.d.ts @@ -14,6 +14,7 @@ type UnityProvider = Pick< | "companyName" | "productName" | "productVersion" + | "webglContextAttributes" > & { /** * Sets the Unity Context's loading progression. From 21b7da85624177c47928c2c6659be59ef0d0faa3 Mon Sep 17 00:00:00 2001 From: Jeffrey Lanters Date: Wed, 16 Jul 2025 12:11:21 +0200 Subject: [PATCH 087/194] Add webglContextAttributes to UnityConfig type definition --- module/source/types/unity-config.d.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/module/source/types/unity-config.d.ts b/module/source/types/unity-config.d.ts index d3f8aafd..4376e45e 100644 --- a/module/source/types/unity-config.d.ts +++ b/module/source/types/unity-config.d.ts @@ -12,6 +12,7 @@ type UnityConfig = Pick< | "companyName" | "productName" | "productVersion" + | "webglContextAttributes" > & { /** * The url to the build json file generated by Unity. When using a relative url, From dc58bd7e43783ef2af2b7c45fbdb534209467528 Mon Sep 17 00:00:00 2001 From: Jeffrey Lanters Date: Wed, 16 Jul 2025 12:11:25 +0200 Subject: [PATCH 088/194] Add webglContextAttributes to Unity instance creation --- module/source/components/unity.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/module/source/components/unity.ts b/module/source/components/unity.ts index b0c6aa7a..eadf8023 100644 --- a/module/source/components/unity.ts +++ b/module/source/components/unity.ts @@ -108,6 +108,7 @@ const Unity: ForwardRefExoticComponent< symbolsUrl: props.unityProvider.symbolsUrl, streamingAssetsUrl: props.unityProvider.streamingAssetsUrl, devicePixelRatio: props.devicePixelRatio, + webglContextAttributes: props.unityProvider.webglContextAttributes, }; // The createUnityInstance function is provided by the Unity loader script. From cb07eed0202fd259fe8bef032ef43fb683129f46 Mon Sep 17 00:00:00 2001 From: Jeffrey Lanters Date: Wed, 16 Jul 2025 12:16:19 +0200 Subject: [PATCH 089/194] Enable unload functionality in Application component --- testing/src/application.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/testing/src/application.tsx b/testing/src/application.tsx index a746497a..b1e5b93b 100644 --- a/testing/src/application.tsx +++ b/testing/src/application.tsx @@ -22,7 +22,7 @@ export function Application() { // addEventListener, // removeEventListener, takeScreenshot, - // unload, + unload, UNSAFE__unityInstance, } = useUnityContext({ codeUrl: `/unity-build/unity.wasm`, @@ -57,7 +57,7 @@ export function Application() { } function handleClickUnload() { - // unload(); + unload(); } function handleClickSetRandomCanvasWidth() { From 1711afac7eb1fed7cd40f296c10b8196d48e6520 Mon Sep 17 00:00:00 2001 From: Jeffrey Lanters Date: Wed, 16 Jul 2025 12:16:22 +0200 Subject: [PATCH 090/194] Add unload method to UnityContext for resource cleanup --- module/source/types/unity-context.d.ts | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/module/source/types/unity-context.d.ts b/module/source/types/unity-context.d.ts index cecd18aa..a0323318 100644 --- a/module/source/types/unity-context.d.ts +++ b/module/source/types/unity-context.d.ts @@ -65,6 +65,15 @@ type UnityContext = { quality?: number ) => string | undefined; + /** + * Unloads the Unity Instance, freeing up resources and memory. + * This method should be called when the Unity Instance is no longer needed + * to ensure proper cleanup. Note that this is done automatically when the + * Unity Context is unmounted, so manual unloading is typically not necessary + * no longer needed. + */ + readonly unload: () => Promise; + /** * An unsafe reference to the Unity Instance. * This reference should be used with caution, as it may not be available From 22b119df90e8f9e01c2d89d66004d4c0f21962ec Mon Sep 17 00:00:00 2001 From: Jeffrey Lanters Date: Wed, 16 Jul 2025 12:16:25 +0200 Subject: [PATCH 091/194] Add unload method to useUnityContext for resource cleanup --- module/source/hooks/use-unity-context.ts | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/module/source/hooks/use-unity-context.ts b/module/source/hooks/use-unity-context.ts index 3867aa69..4cc0f070 100644 --- a/module/source/hooks/use-unity-context.ts +++ b/module/source/hooks/use-unity-context.ts @@ -85,6 +85,14 @@ const useUnityContext = (unityConfig: UnityConfig): UnityContext => { [unityInstance] ); + /** + * Unloads the Unity Instance and cleans up resources. + */ + const unload = useCallback( + () => unityInstance?.Quit() ?? Promise.reject(), + [unityInstance] + ); + // Initialize the UnityProvider with the provided configuration // This is where you would typically load the Unity instance // and set up event listeners, etc. @@ -97,6 +105,7 @@ const useUnityContext = (unityConfig: UnityConfig): UnityContext => { requestPointerLock, sendMessage, takeScreenshot, + unload, UNSAFE__unityInstance: unityInstance, }; }; From 22373a8a44ae9c9ec57465b8df8ed409ab0c3597 Mon Sep 17 00:00:00 2001 From: Jeffrey Lanters Date: Wed, 16 Jul 2025 12:22:42 +0200 Subject: [PATCH 092/194] Enable cache control in Unity instance configuration --- testing/src/application.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/testing/src/application.tsx b/testing/src/application.tsx index b1e5b93b..ed80e950 100644 --- a/testing/src/application.tsx +++ b/testing/src/application.tsx @@ -32,7 +32,7 @@ export function Application() { webglContextAttributes: { preserveDrawingBuffer: true, }, - // cacheControl: handleCacheControl, + cacheControl: handleCacheControl, companyName: "Unity Technologies", productName: "Communication Tests", productVersion: "1.0.0", From 7717fe94a65011834d7ebbffec69820d0c693b14 Mon Sep 17 00:00:00 2001 From: Jeffrey Lanters Date: Wed, 16 Jul 2025 12:22:45 +0200 Subject: [PATCH 093/194] Add cacheControl to UnityProvider type definition --- module/source/types/unity-provider.d.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/module/source/types/unity-provider.d.ts b/module/source/types/unity-provider.d.ts index 741326bc..068d1b79 100644 --- a/module/source/types/unity-provider.d.ts +++ b/module/source/types/unity-provider.d.ts @@ -15,6 +15,7 @@ type UnityProvider = Pick< | "productName" | "productVersion" | "webglContextAttributes" + | "cacheControl" > & { /** * Sets the Unity Context's loading progression. From f24c83b7304d2da97b0616af7ce43f239832dffd Mon Sep 17 00:00:00 2001 From: Jeffrey Lanters Date: Wed, 16 Jul 2025 12:22:50 +0200 Subject: [PATCH 094/194] Add cacheControl to UnityConfig type definition --- module/source/types/unity-config.d.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/module/source/types/unity-config.d.ts b/module/source/types/unity-config.d.ts index 4376e45e..c23ea74c 100644 --- a/module/source/types/unity-config.d.ts +++ b/module/source/types/unity-config.d.ts @@ -13,6 +13,7 @@ type UnityConfig = Pick< | "productName" | "productVersion" | "webglContextAttributes" + | "cacheControl" > & { /** * The url to the build json file generated by Unity. When using a relative url, From e8dd549fc950a3e4dff18983aa7669ff086ab9cf Mon Sep 17 00:00:00 2001 From: Jeffrey Lanters Date: Wed, 16 Jul 2025 12:22:54 +0200 Subject: [PATCH 095/194] Fix documentation and ensure cacheControl is included in UnityProvider instance --- module/source/hooks/use-unity-context.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/module/source/hooks/use-unity-context.ts b/module/source/hooks/use-unity-context.ts index 4cc0f070..fb9a433a 100644 --- a/module/source/hooks/use-unity-context.ts +++ b/module/source/hooks/use-unity-context.ts @@ -8,7 +8,6 @@ import { UnityEventParameter } from "../exports"; /** * Custom hook to create a Unity context. * This hook initializes the Unity instance and provides the necessary state and methods. - * * @param unityConfig - Configuration object for the Unity instance. * @returns An object containing the Unity context state and methods. */ @@ -37,6 +36,7 @@ const useUnityContext = (unityConfig: UnityConfig): UnityContext => { streamingAssetsUrl: unityConfig.streamingAssetsUrl, workerUrl: unityConfig.workerUrl, webglContextAttributes: unityConfig.webglContextAttributes, + cacheControl: unityConfig.cacheControl, setUnityInstance, setLoadingProgression, setIsLoaded, From 94e0c0d71ae913180c415301e99aa95c8d1ac0b9 Mon Sep 17 00:00:00 2001 From: Jeffrey Lanters Date: Wed, 16 Jul 2025 12:22:58 +0200 Subject: [PATCH 096/194] Update Unity component to set loading state correctly and include cacheControl in Unity instance configuration --- module/source/components/unity.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/module/source/components/unity.ts b/module/source/components/unity.ts index eadf8023..bd68c3dd 100644 --- a/module/source/components/unity.ts +++ b/module/source/components/unity.ts @@ -55,7 +55,7 @@ const Unity: ForwardRefExoticComponent< if (progress === 1) { // If the loading progression reaches 100%, we can set the isLoaded state // to true. - props.unityProvider.setIsLoaded?.(true); + props.unityProvider.setIsLoaded(true); } }, [props.unityProvider] @@ -109,6 +109,7 @@ const Unity: ForwardRefExoticComponent< streamingAssetsUrl: props.unityProvider.streamingAssetsUrl, devicePixelRatio: props.devicePixelRatio, webglContextAttributes: props.unityProvider.webglContextAttributes, + cacheControl: props.unityProvider.cacheControl, }; // The createUnityInstance function is provided by the Unity loader script. From 7a3a2220ad9a4a04ec60702fc4fdeeca49e5e668 Mon Sep 17 00:00:00 2001 From: Jeffrey Lanters Date: Wed, 16 Jul 2025 12:25:48 +0200 Subject: [PATCH 097/194] Refactor comments for unimplemented features and add TODOs for future implementation --- testing/src/application.tsx | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/testing/src/application.tsx b/testing/src/application.tsx index ed80e950..aa6487d8 100644 --- a/testing/src/application.tsx +++ b/testing/src/application.tsx @@ -19,8 +19,8 @@ export function Application() { requestPointerLock, sendMessage, initialisationError, - // addEventListener, - // removeEventListener, + // addEventListener, // TODO: Implement this + // removeEventListener, // TODO: Implement this takeScreenshot, unload, UNSAFE__unityInstance, @@ -36,6 +36,7 @@ export function Application() { companyName: "Unity Technologies", productName: "Communication Tests", productVersion: "1.0.0", + // autoSyncPersistentDataPath: true, // TODO: Implement this // memoryUrl: `/unity-build/communication-tests.mem`, // <- Tested, but not implemented in the demo project // streamingAssetsUrl: `/unity-build/StreamingAssets`, // <- Tested, but not implemented in the demo project // symbolsUrl: `/unity-build/communication-tests.symbols.json`, // <- Tested, but not implemented in the demo project @@ -163,9 +164,12 @@ export function Application() { width: canvasWidth, }} devicePixelRatio={window.devicePixelRatio} - // disabledCanvasEvents={["dragstart"]} ref={canvasRef} // id="my-custom-cancas-id" // <- Tested, but not implemented in the demo project + // disabledCanvasEvents={["dragstart"]} // TODO: Implement this + // className="my-custom-canvas-class" // TODO: Implement this + // matchWebGLToCanvasSize={true} // TODO: Implement this + // tabIndex={0} // TODO: Implement this /> )}

Console

From a83a4967f79159607fb141063170ff3767f2f60c Mon Sep 17 00:00:00 2001 From: Jeffrey Lanters Date: Wed, 16 Jul 2025 13:07:37 +0200 Subject: [PATCH 098/194] Implement event listener functionality in Application component --- testing/src/application.tsx | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/testing/src/application.tsx b/testing/src/application.tsx index aa6487d8..be70d2fd 100644 --- a/testing/src/application.tsx +++ b/testing/src/application.tsx @@ -19,8 +19,8 @@ export function Application() { requestPointerLock, sendMessage, initialisationError, - // addEventListener, // TODO: Implement this - // removeEventListener, // TODO: Implement this + addEventListener, + removeEventListener, takeScreenshot, unload, UNSAFE__unityInstance, @@ -96,19 +96,19 @@ export function Application() { ]); } - // addEventListener("ClickedTestButton", logParametersToConsole); - // addEventListener("ClickedStringTestButton", logParametersToConsole); - // addEventListener("ClickedNumberTestButton", logParametersToConsole); - // addEventListener("ClickedNumbersTestButton", logParametersToConsole); - // addEventListener("ClickedBoolTestButton", logParametersToConsole); - // addEventListener("ClickedObjectTestButton", logParametersToConsole); + addEventListener("ClickedTestButton", logParametersToConsole); + addEventListener("ClickedStringTestButton", logParametersToConsole); + addEventListener("ClickedNumberTestButton", logParametersToConsole); + addEventListener("ClickedNumbersTestButton", logParametersToConsole); + addEventListener("ClickedBoolTestButton", logParametersToConsole); + addEventListener("ClickedObjectTestButton", logParametersToConsole); return () => { - // removeEventListener("ClickedTestButton", logParametersToConsole); - // removeEventListener("ClickedStringTestButton", logParametersToConsole); - // removeEventListener("ClickedNumberTestButton", logParametersToConsole); - // removeEventListener("ClickedNumbersTestButton", logParametersToConsole); - // removeEventListener("ClickedBoolTestButton", logParametersToConsole); - // removeEventListener("ClickedObjectTestButton", logParametersToConsole); + removeEventListener("ClickedTestButton", logParametersToConsole); + removeEventListener("ClickedStringTestButton", logParametersToConsole); + removeEventListener("ClickedNumberTestButton", logParametersToConsole); + removeEventListener("ClickedNumbersTestButton", logParametersToConsole); + removeEventListener("ClickedBoolTestButton", logParametersToConsole); + removeEventListener("ClickedObjectTestButton", logParametersToConsole); }; }, [addEventListener, removeEventListener]); From 453c4f8aeb393b44e0ce78359d28fdbaeb3b7c47 Mon Sep 17 00:00:00 2001 From: Jeffrey Lanters Date: Wed, 16 Jul 2025 13:07:40 +0200 Subject: [PATCH 099/194] Import EventSystem to enhance UnityContext type definition --- module/source/types/unity-context.d.ts | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/module/source/types/unity-context.d.ts b/module/source/types/unity-context.d.ts index a0323318..5914cfa1 100644 --- a/module/source/types/unity-context.d.ts +++ b/module/source/types/unity-context.d.ts @@ -1,8 +1,12 @@ +import { EventSystem } from "./event-system"; import { UnityEventParameter } from "./unity-event-parameters"; import { UnityInstance } from "./unity-instance"; import { UnityProvider } from "./unity-provider"; -type UnityContext = { +type UnityContext = Pick< + EventSystem, + "addEventListener" | "removeEventListener" +> & { /** * The Unity Context returns a Unity Provider instance. This immutable object * should be passed onto a Unity Component in order to be able to access the From ce56a88a972774c4283c4158189c587c0dbf293b Mon Sep 17 00:00:00 2001 From: Jeffrey Lanters Date: Wed, 16 Jul 2025 13:07:43 +0200 Subject: [PATCH 100/194] Add EventSystem type definition for external React Unity events --- module/source/types/event-system.d.ts | 28 +++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) create mode 100644 module/source/types/event-system.d.ts diff --git a/module/source/types/event-system.d.ts b/module/source/types/event-system.d.ts new file mode 100644 index 00000000..1c9721df --- /dev/null +++ b/module/source/types/event-system.d.ts @@ -0,0 +1,28 @@ +import { UnityEventParameter } from "./unity-event-parameters"; + +/** + * Event system for external React Unity events. + */ +type EventSystem = { + /** + * Adds an event listener for external React Unity events. + * @param eventName The name of the event to listen to. + * @param callback The callback to invoke when the event is fired. + */ + readonly addEventListener: ( + eventName: string, + callback: (...parameters: UnityEventParameter[]) => UnityEventParameter + ) => void; + + /** + * Removes an event listener for external React Unity events. + * @param eventName The name of the event to remove. + * @param callback The callback to remove. + */ + readonly removeEventListener: ( + eventName: string, + callback: (...parameters: UnityEventParameter[]) => UnityEventParameter + ) => void; +}; + +export type { EventSystem }; From c063cc01f8c0663ba1735e586f70709574d2d393 Mon Sep 17 00:00:00 2001 From: Jeffrey Lanters Date: Wed, 16 Jul 2025 13:07:47 +0200 Subject: [PATCH 101/194] Add EventListener type definition for handling Unity events --- module/source/types/event-listener.d.ts | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) create mode 100644 module/source/types/event-listener.d.ts diff --git a/module/source/types/event-listener.d.ts b/module/source/types/event-listener.d.ts new file mode 100644 index 00000000..a492f4e3 --- /dev/null +++ b/module/source/types/event-listener.d.ts @@ -0,0 +1,18 @@ +import { UnityEventParameter } from "./unity-event-parameters"; + +/** + * An event listener. + */ +type EventListener = { + /** + * The name of the event to listen to. + */ + eventName: string; + + /** + * The callback to invoke when the event is fired. + */ + callback: (...parameters: UnityEventParameter[]) => UnityEventParameter; +}; + +export type { EventListener }; From 7f2f43c146ee1c0e621a2ff2c78d2f574b018d56 Mon Sep 17 00:00:00 2001 From: Jeffrey Lanters Date: Wed, 16 Jul 2025 13:07:50 +0200 Subject: [PATCH 102/194] Add event system integration to useUnityContext for managing Unity events --- module/source/hooks/use-unity-context.ts | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/module/source/hooks/use-unity-context.ts b/module/source/hooks/use-unity-context.ts index fb9a433a..98bdba24 100644 --- a/module/source/hooks/use-unity-context.ts +++ b/module/source/hooks/use-unity-context.ts @@ -4,6 +4,7 @@ import { UnityContext } from "../types/unity-context"; import { UnityProvider } from "../types/unity-provider"; import { UnityInstance } from "../types/unity-instance"; import { UnityEventParameter } from "../exports"; +import { useEventSystem } from "./use-event-system"; /** * Custom hook to create a Unity context. @@ -19,6 +20,11 @@ const useUnityContext = (unityConfig: UnityConfig): UnityContext => { const [isLoaded, setIsLoaded] = useState(false); const [initialisationError, setInitialisationError] = useState(); + // Use the event system hook to manage external React Unity events. + // This hook provides methods to add and remove event listeners for Unity events. + // It returns an object with the methods addEventListener and removeEventListener. + const eventSystem = useEventSystem(); + // Create a ref to hold the UnityProvider instance, it consists of a selection // of properties from the UnityConfig and methods to interact with the Unity instance. // This allows us to avoid unnecessary re-renders when the UnityProvider is updated. @@ -106,6 +112,8 @@ const useUnityContext = (unityConfig: UnityConfig): UnityContext => { sendMessage, takeScreenshot, unload, + addEventListener: eventSystem.addEventListener, + removeEventListener: eventSystem.removeEventListener, UNSAFE__unityInstance: unityInstance, }; }; From e22d5ee107ff737a0e7f96a4315b10322904309c Mon Sep 17 00:00:00 2001 From: Jeffrey Lanters Date: Wed, 16 Jul 2025 13:07:53 +0200 Subject: [PATCH 103/194] Implement useEventSystem hook for managing external React Unity events --- module/source/hooks/use-event-system.ts | 143 ++++++++++++++++++++++++ 1 file changed, 143 insertions(+) create mode 100644 module/source/hooks/use-event-system.ts diff --git a/module/source/hooks/use-event-system.ts b/module/source/hooks/use-event-system.ts new file mode 100644 index 00000000..6720a89b --- /dev/null +++ b/module/source/hooks/use-event-system.ts @@ -0,0 +1,143 @@ +import { useCallback, useEffect, useRef } from "react"; +import { isBrowserEnvironment } from "../constants/is-browser-environment"; +import { EventListener } from "../types/event-listener"; +import { EventSystem } from "../types/event-system"; +import { UnityEventParameter } from "../types/unity-event-parameters"; + +/** + * An array of dispatch event methods from within the mounted event systems. + * This allows an event to be dispatched within all of the event system + * instances. + */ +const mountedEventDispatchers: (( + eventName: string, + ...parameters: UnityEventParameter[] +) => UnityEventParameter)[] = []; + +/** + * Dispatches an event to all mounted event systems. + * @param eventName The name of the event to dispatch. + * @param parameters The parameters to pass to the event listener. + */ +const dispatchReactUnityEvent = ( + eventName: string, + ...parameters: UnityEventParameter[] +): UnityEventParameter => { + // Loops through all of the mounted event systems and dispatches the event. + // In case there are multiple event systems, the return value origin is + // undefined. + let returnValue: UnityEventParameter = undefined; + mountedEventDispatchers.forEach((dispatchEvent) => { + returnValue = dispatchEvent(eventName, ...parameters); + }); + return returnValue; +}; + +if (isBrowserEnvironment === true) { + // It is possible for the application being rendered server side. We'll check + // if the app is running in a browser environment and if so, we'll make the + // dispatch React Unity event function available to the global scope. + window.dispatchReactUnityEvent = dispatchReactUnityEvent; +} + +/** + * Event system for invoking external React Unity events. + * @returns The Event System hook. + */ +const useEventSystem = (): EventSystem => { + /** + * An array of all registered event listeners. + */ + const eventListeners = useRef([]); + + /** + * Adds an event listener for external React Unity events. + */ + const addEventListener = useCallback( + /** + * @param eventName The name of the event to listen to. + * @param callback The callback to invoke when the event is fired. + */ + ( + eventName: string, + callback: (...parameters: UnityEventParameter[]) => UnityEventParameter + ) => { + // Add the event listener will be added to the array of event listeners. + eventListeners.current = [ + ...eventListeners.current, + { eventName, callback }, + ]; + }, + [eventListeners] + ); + + /** + * Removes an event listener for external React Unity events. + */ + const removeEventListener = useCallback( + /** + * @param eventName The name of the event to remove. + * @param callback The callback to remove. + */ + ( + eventName: string, + callback: (...parameters: UnityEventParameter[]) => UnityEventParameter + ) => { + // The event listener will be filtered from the event listeners array + // based on its name and the reference to the callback. + eventListeners.current = eventListeners.current.filter( + (eventListener) => + eventListener.eventName !== eventName && + eventListener.callback !== callback + ); + }, + [eventListeners] + ); + + /** + * Dispatches an event. + */ + const dispatchEvent = useCallback( + /** + * @param eventName The name of the event to dispatch. + * @param parameters The parameters to pass to the event listener. + */ + ( + eventName: string, + ...parameters: UnityEventParameter[] + ): UnityEventParameter => { + // The event listener will be filtered from the event listeners array + // based on its name. + const eventListener = eventListeners.current.find( + (eventListener) => eventListener.eventName === eventName + ); + if (typeof eventListener === "undefined") { + // Guarding the event listener. + return; + } + // The event listener will be invoked with the parameters. + return eventListener.callback(...parameters); + }, + [eventListeners] + ); + + // Effect ensures that the dispatch event function is available to the + // global array of event listeners. This allows the global method to dispatch + // events within the event system hooks. + useEffect(() => { + mountedEventDispatchers.push(dispatchEvent); + return () => { + mountedEventDispatchers.splice( + mountedEventDispatchers.indexOf(dispatchEvent), + 1 + ); + }; + }, [dispatchEvent]); + + return { + addEventListener, + removeEventListener, + }; +}; + +export { useEventSystem }; From 64c24036b7d1eb04558bc6ecd6f5228721a17caa Mon Sep 17 00:00:00 2001 From: Jeffrey Lanters Date: Wed, 16 Jul 2025 13:13:31 +0200 Subject: [PATCH 104/194] Add Unity communication loader and WebAssembly binary - Introduced `communication.loader.js` to handle Unity instance creation, error handling, and resource loading. - Added `communication.wasm` binary for Unity WebGL content execution. --- .../communication.data} | Bin .../communication.framework.js} | 0 .../communication.loader.js} | 0 .../communication.wasm} | Bin 4 files changed, 0 insertions(+), 0 deletions(-) rename testing/public/{unity-build/unity.data => unity-build-2022.1/communication.data} (100%) rename testing/public/{unity-build/unity.framework.js => unity-build-2022.1/communication.framework.js} (100%) rename testing/public/{unity-build/unity.loader.js => unity-build-2022.1/communication.loader.js} (100%) rename testing/public/{unity-build/unity.wasm => unity-build-2022.1/communication.wasm} (100%) diff --git a/testing/public/unity-build/unity.data b/testing/public/unity-build-2022.1/communication.data similarity index 100% rename from testing/public/unity-build/unity.data rename to testing/public/unity-build-2022.1/communication.data diff --git a/testing/public/unity-build/unity.framework.js b/testing/public/unity-build-2022.1/communication.framework.js similarity index 100% rename from testing/public/unity-build/unity.framework.js rename to testing/public/unity-build-2022.1/communication.framework.js diff --git a/testing/public/unity-build/unity.loader.js b/testing/public/unity-build-2022.1/communication.loader.js similarity index 100% rename from testing/public/unity-build/unity.loader.js rename to testing/public/unity-build-2022.1/communication.loader.js diff --git a/testing/public/unity-build/unity.wasm b/testing/public/unity-build-2022.1/communication.wasm similarity index 100% rename from testing/public/unity-build/unity.wasm rename to testing/public/unity-build-2022.1/communication.wasm From 8bb5f986f11275bedb486ee025d96db3d9d7e611 Mon Sep 17 00:00:00 2001 From: Jeffrey Lanters Date: Wed, 16 Jul 2025 13:17:35 +0200 Subject: [PATCH 105/194] Update Unity build paths and enable autoSyncPersistentDataPath --- testing/src/application.tsx | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/testing/src/application.tsx b/testing/src/application.tsx index be70d2fd..6a6c6142 100644 --- a/testing/src/application.tsx +++ b/testing/src/application.tsx @@ -25,10 +25,10 @@ export function Application() { unload, UNSAFE__unityInstance, } = useUnityContext({ - codeUrl: `/unity-build/unity.wasm`, - dataUrl: `/unity-build/unity.data`, - frameworkUrl: `/unity-build/unity.framework.js`, - loaderUrl: `/unity-build/unity.loader.js`, + codeUrl: `/unity-build-2022.1/communication.wasm`, + dataUrl: `/unity-build-2022.1/communication.data`, + frameworkUrl: `/unity-build-2022.1/communication.framework.js`, + loaderUrl: `/unity-build-2022.1/communication.loader.js`, webglContextAttributes: { preserveDrawingBuffer: true, }, @@ -36,7 +36,7 @@ export function Application() { companyName: "Unity Technologies", productName: "Communication Tests", productVersion: "1.0.0", - // autoSyncPersistentDataPath: true, // TODO: Implement this + autoSyncPersistentDataPath: true, // memoryUrl: `/unity-build/communication-tests.mem`, // <- Tested, but not implemented in the demo project // streamingAssetsUrl: `/unity-build/StreamingAssets`, // <- Tested, but not implemented in the demo project // symbolsUrl: `/unity-build/communication-tests.symbols.json`, // <- Tested, but not implemented in the demo project @@ -166,9 +166,9 @@ export function Application() { devicePixelRatio={window.devicePixelRatio} ref={canvasRef} // id="my-custom-cancas-id" // <- Tested, but not implemented in the demo project - // disabledCanvasEvents={["dragstart"]} // TODO: Implement this + matchWebGLToCanvasSize={true} + disabledCanvasEvents={["contextmenu"]} // className="my-custom-canvas-class" // TODO: Implement this - // matchWebGLToCanvasSize={true} // TODO: Implement this // tabIndex={0} // TODO: Implement this /> )} From a8ee686914f35d22f8d10c00e67f08d858003389 Mon Sep 17 00:00:00 2001 From: Jeffrey Lanters Date: Wed, 16 Jul 2025 13:17:39 +0200 Subject: [PATCH 106/194] Add autoSyncPersistentDataPath to UnityProvider type definition --- module/source/types/unity-provider.d.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/module/source/types/unity-provider.d.ts b/module/source/types/unity-provider.d.ts index 068d1b79..14382cd1 100644 --- a/module/source/types/unity-provider.d.ts +++ b/module/source/types/unity-provider.d.ts @@ -16,6 +16,7 @@ type UnityProvider = Pick< | "productVersion" | "webglContextAttributes" | "cacheControl" + | "autoSyncPersistentDataPath" > & { /** * Sets the Unity Context's loading progression. From 1fb0083186a48fd85b7c4c621da5b978f7c5eccd Mon Sep 17 00:00:00 2001 From: Jeffrey Lanters Date: Wed, 16 Jul 2025 13:17:42 +0200 Subject: [PATCH 107/194] Update UnityProps type to include matchWebGLToCanvasSize and disabledCanvasEvents --- module/source/types/unity-props.d.ts | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/module/source/types/unity-props.d.ts b/module/source/types/unity-props.d.ts index 1d25434b..b662bdc5 100644 --- a/module/source/types/unity-props.d.ts +++ b/module/source/types/unity-props.d.ts @@ -2,7 +2,10 @@ import { CSSProperties } from "react"; import { UnityProvider } from "./unity-provider"; import { UnityArguments } from "./unity-arguments"; -type UnityProps = Pick & { +type UnityProps = Pick< + UnityArguments, + "devicePixelRatio" | "matchWebGLToCanvasSize" | "disabledCanvasEvents" +> & { /** * The Unity provider that contains the necessary URLs to load the Unity * instance. This is required to load the Unity WebGL build. From a15226772372823e98530421e7d13f627fae0baa Mon Sep 17 00:00:00 2001 From: Jeffrey Lanters Date: Wed, 16 Jul 2025 13:17:45 +0200 Subject: [PATCH 108/194] Add autoSyncPersistentDataPath to UnityConfig type definition --- module/source/types/unity-config.d.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/module/source/types/unity-config.d.ts b/module/source/types/unity-config.d.ts index c23ea74c..a5c5e86f 100644 --- a/module/source/types/unity-config.d.ts +++ b/module/source/types/unity-config.d.ts @@ -14,6 +14,7 @@ type UnityConfig = Pick< | "productVersion" | "webglContextAttributes" | "cacheControl" + | "autoSyncPersistentDataPath" > & { /** * The url to the build json file generated by Unity. When using a relative url, From 1d6a831186417a9d27002ef11c7cdbbaa09d20de Mon Sep 17 00:00:00 2001 From: Jeffrey Lanters Date: Wed, 16 Jul 2025 13:17:48 +0200 Subject: [PATCH 109/194] Add autoSyncPersistentDataPath to UnityProvider instance in useUnityContext hook --- module/source/hooks/use-unity-context.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/module/source/hooks/use-unity-context.ts b/module/source/hooks/use-unity-context.ts index 98bdba24..065ad8ab 100644 --- a/module/source/hooks/use-unity-context.ts +++ b/module/source/hooks/use-unity-context.ts @@ -43,6 +43,7 @@ const useUnityContext = (unityConfig: UnityConfig): UnityContext => { workerUrl: unityConfig.workerUrl, webglContextAttributes: unityConfig.webglContextAttributes, cacheControl: unityConfig.cacheControl, + autoSyncPersistentDataPath: unityConfig.autoSyncPersistentDataPath, setUnityInstance, setLoadingProgression, setIsLoaded, From 49faffc0d7d0184728e8a0d3961e9aafc31805f6 Mon Sep 17 00:00:00 2001 From: Jeffrey Lanters Date: Wed, 16 Jul 2025 13:17:51 +0200 Subject: [PATCH 110/194] Add autoSyncPersistentDataPath, matchWebGLToCanvasSize, and disabledCanvasEvents to Unity instance creation --- module/source/components/unity.ts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/module/source/components/unity.ts b/module/source/components/unity.ts index bd68c3dd..cbeb56f3 100644 --- a/module/source/components/unity.ts +++ b/module/source/components/unity.ts @@ -110,6 +110,10 @@ const Unity: ForwardRefExoticComponent< devicePixelRatio: props.devicePixelRatio, webglContextAttributes: props.unityProvider.webglContextAttributes, cacheControl: props.unityProvider.cacheControl, + autoSyncPersistentDataPath: + props.unityProvider.autoSyncPersistentDataPath, + matchWebGLToCanvasSize: props.matchWebGLToCanvasSize, + disabledCanvasEvents: props.disabledCanvasEvents ?? [], }; // The createUnityInstance function is provided by the Unity loader script. From a3ab6452579678d3b21a82288fb837605b768c47 Mon Sep 17 00:00:00 2001 From: Jeffrey Lanters Date: Wed, 16 Jul 2025 13:19:08 +0200 Subject: [PATCH 111/194] Add className and tabIndex properties to canvas element in Application component --- testing/src/application.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/testing/src/application.tsx b/testing/src/application.tsx index 6a6c6142..04514e9d 100644 --- a/testing/src/application.tsx +++ b/testing/src/application.tsx @@ -168,8 +168,8 @@ export function Application() { // id="my-custom-cancas-id" // <- Tested, but not implemented in the demo project matchWebGLToCanvasSize={true} disabledCanvasEvents={["contextmenu"]} - // className="my-custom-canvas-class" // TODO: Implement this - // tabIndex={0} // TODO: Implement this + className="my-custom-canvas-class" + tabIndex={0} /> )}

Console

From fa5fc6d24400e1b8987f1f7e5b3c29e6e949bede Mon Sep 17 00:00:00 2001 From: Jeffrey Lanters Date: Wed, 16 Jul 2025 13:19:15 +0200 Subject: [PATCH 112/194] Add className and tabIndex properties to UnityProps type definition --- module/source/types/unity-props.d.ts | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/module/source/types/unity-props.d.ts b/module/source/types/unity-props.d.ts index b662bdc5..a2ff13c9 100644 --- a/module/source/types/unity-props.d.ts +++ b/module/source/types/unity-props.d.ts @@ -23,6 +23,18 @@ type UnityProps = Pick< * The style of the Unity canvas element. */ style?: CSSProperties; + + /** + * The class name of the Unity canvas element. This can be used to apply + * custom styles to the canvas. + */ + className?: string; + + /** + * The tab index of the Unity canvas element. This can be used to make the + * canvas focusable. + */ + tabIndex?: number; }; export type { UnityProps }; From 5ecc124594335cd20ea191bedc7587b51d19e236 Mon Sep 17 00:00:00 2001 From: Jeffrey Lanters Date: Wed, 16 Jul 2025 13:19:19 +0200 Subject: [PATCH 113/194] Add className and tabIndex properties to Unity component --- module/source/components/unity.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/module/source/components/unity.ts b/module/source/components/unity.ts index cbeb56f3..78f31d10 100644 --- a/module/source/components/unity.ts +++ b/module/source/components/unity.ts @@ -219,6 +219,8 @@ const Unity: ForwardRefExoticComponent< ref: setCanvasRef, id: canvasId, style: props.style, + className: props.className, + tabIndex: props.tabIndex, }); } ); From 53c4f5379b982dbe1bb8b24c1a3b5bc15159e966 Mon Sep 17 00:00:00 2001 From: Jeffrey Lanters Date: Wed, 16 Jul 2025 13:26:57 +0200 Subject: [PATCH 114/194] Migrating documentation to version 10 --- documentation/docs/api/unload.md | 8 - documentation/docusaurus.config.js | 8 +- documentation/sidebars.json | 5 - .../dynamic-device-pixel-ratio.md | 53 ++++ .../advanced-examples/loading-overlay.md | 75 ++++++ .../api/auto-sync-persistent-data-path.md | 34 +++ .../version-9.x.x/api/cache-control.md | 62 +++++ .../version-9.x.x/api/canvas-classname.md | 39 +++ .../api/canvas-device-pixel-ratio.md | 48 ++++ .../version-9.x.x/api/canvas-id.md | 38 +++ .../version-9.x.x/api/canvas-ref.md | 58 +++++ .../version-9.x.x/api/canvas-styles.md | 39 +++ .../api/disabled-canvas-events.md | 38 +++ .../version-9.x.x/api/event-system.md | 228 ++++++++++++++++++ .../version-9.x.x/api/introduction.md | 5 + .../version-9.x.x/api/is-loaded.md | 59 +++++ .../version-9.x.x/api/loading-progression.md | 60 +++++ .../version-9.x.x/api/meta-data.md | 36 +++ .../version-9.x.x/api/request-fullscreen.md | 62 +++++ .../version-9.x.x/api/request-pointer-lock.md | 64 +++++ .../version-9.x.x/api/send-message.md | 93 +++++++ .../version-9.x.x/api/streaming-assets.md | 36 +++ .../version-9.x.x/api/tab-index.md | 68 ++++++ .../version-9.x.x/api/take-screenshot.md | 80 ++++++ .../version-9.x.x/api/unload.md | 71 ++++++ .../api/unsafe-detach-unmount-immediate.md | 0 .../api/unsafe-unity-instance.md | 38 +++ .../version-9.x.x/api/web-worker.md | 33 +++ .../api/webgl-rendering-context.md | 104 ++++++++ .../version-9.x.x/contributing.md | 28 +++ .../getting-started/hello-world.md | 23 ++ .../getting-started/installation.md | 23 ++ .../version-9.x.x/introduction.md | 7 + .../main-concepts/data-conversion.md | 32 +++ .../main-concepts/project-structure.md | 7 + .../main-concepts/unity-config.md | 18 ++ .../browser-compatibility.md | 18 ++ .../building-unity-for-webgl.md | 32 +++ ...ds-and\342\200\223server-configuration.md" | 54 +++++ .../quick-start/simple-example.md | 21 ++ .../version-9.x.x/upgrading-from-version-8.md | 7 + .../version-9.x.x-sidebars.json | 213 ++++++++++++++++ documentation/versions.json | 2 +- 43 files changed, 2012 insertions(+), 15 deletions(-) create mode 100644 documentation/versioned_docs/version-9.x.x/advanced-examples/dynamic-device-pixel-ratio.md create mode 100644 documentation/versioned_docs/version-9.x.x/advanced-examples/loading-overlay.md create mode 100644 documentation/versioned_docs/version-9.x.x/api/auto-sync-persistent-data-path.md create mode 100644 documentation/versioned_docs/version-9.x.x/api/cache-control.md create mode 100644 documentation/versioned_docs/version-9.x.x/api/canvas-classname.md create mode 100644 documentation/versioned_docs/version-9.x.x/api/canvas-device-pixel-ratio.md create mode 100644 documentation/versioned_docs/version-9.x.x/api/canvas-id.md create mode 100644 documentation/versioned_docs/version-9.x.x/api/canvas-ref.md create mode 100644 documentation/versioned_docs/version-9.x.x/api/canvas-styles.md create mode 100644 documentation/versioned_docs/version-9.x.x/api/disabled-canvas-events.md create mode 100644 documentation/versioned_docs/version-9.x.x/api/event-system.md create mode 100644 documentation/versioned_docs/version-9.x.x/api/introduction.md create mode 100644 documentation/versioned_docs/version-9.x.x/api/is-loaded.md create mode 100644 documentation/versioned_docs/version-9.x.x/api/loading-progression.md create mode 100644 documentation/versioned_docs/version-9.x.x/api/meta-data.md create mode 100644 documentation/versioned_docs/version-9.x.x/api/request-fullscreen.md create mode 100644 documentation/versioned_docs/version-9.x.x/api/request-pointer-lock.md create mode 100644 documentation/versioned_docs/version-9.x.x/api/send-message.md create mode 100644 documentation/versioned_docs/version-9.x.x/api/streaming-assets.md create mode 100644 documentation/versioned_docs/version-9.x.x/api/tab-index.md create mode 100644 documentation/versioned_docs/version-9.x.x/api/take-screenshot.md create mode 100644 documentation/versioned_docs/version-9.x.x/api/unload.md rename documentation/{docs => versioned_docs/version-9.x.x}/api/unsafe-detach-unmount-immediate.md (100%) create mode 100644 documentation/versioned_docs/version-9.x.x/api/unsafe-unity-instance.md create mode 100644 documentation/versioned_docs/version-9.x.x/api/web-worker.md create mode 100644 documentation/versioned_docs/version-9.x.x/api/webgl-rendering-context.md create mode 100644 documentation/versioned_docs/version-9.x.x/contributing.md create mode 100644 documentation/versioned_docs/version-9.x.x/getting-started/hello-world.md create mode 100644 documentation/versioned_docs/version-9.x.x/getting-started/installation.md create mode 100644 documentation/versioned_docs/version-9.x.x/introduction.md create mode 100644 documentation/versioned_docs/version-9.x.x/main-concepts/data-conversion.md create mode 100644 documentation/versioned_docs/version-9.x.x/main-concepts/project-structure.md create mode 100644 documentation/versioned_docs/version-9.x.x/main-concepts/unity-config.md create mode 100644 documentation/versioned_docs/version-9.x.x/miscellaneous-instructions/browser-compatibility.md create mode 100644 documentation/versioned_docs/version-9.x.x/miscellaneous-instructions/building-unity-for-webgl.md create mode 100644 "documentation/versioned_docs/version-9.x.x/miscellaneous-instructions/compressed-builds-and\342\200\223server-configuration.md" create mode 100644 documentation/versioned_docs/version-9.x.x/quick-start/simple-example.md create mode 100644 documentation/versioned_docs/version-9.x.x/upgrading-from-version-8.md create mode 100644 documentation/versioned_sidebars/version-9.x.x-sidebars.json diff --git a/documentation/docs/api/unload.md b/documentation/docs/api/unload.md index 42b60ce5..8d13461a 100644 --- a/documentation/docs/api/unload.md +++ b/documentation/docs/api/unload.md @@ -14,14 +14,6 @@ function unload(): Promise | undefined; The unload function is only available in Unity Builds created with Unity 2020.1 or later. ::: -:::danger -In earlier versions of Unity, it was possible to unmount the Unity Application and its containing component immediately after invoking the unload function. However, due to a bug in newer Unity versions, this is no longer feasible when using builds made with Unity 2021.2 or later. While it is still possible to unload the Unity Application, the canvas must remain mounted until the associated promise is resolved. - -As of this writing, the issue has not been resolved. However, it is possible to manually unmount the Unity Application by halting navigation to the next page. A ticket has been submitted, and the Unity team has acknowledged this as a known issue. For more details, refer to the [GitHub issue](https://github.com/jeffreylanters/react-unity-webgl/issues/250). - -Alternatively, you can use the unsafe `detachAndUnloadImmediate` function to immediately unmount the Unity Application. However, this is not recommended unless you are an advanced user. For more information, refer to the [Unsafe Detach and Unload Immediate](/docs/api/unsafe-detach-unmount-immediate) documentation. -::: - When building a multi-page React Application, it is important to unload the Unity Application in order to completely unmount the component from the DOM to free up the memory taken by the Unity JavaScript heap, and without Unity throwing an error. Invoking the function will request the Unity Application to be unloaded from memory. The function will return a Promise that will be resolved when the Unity Application has been unloaded. To get started, destructure the unload function from the Unity Context. diff --git a/documentation/docusaurus.config.js b/documentation/docusaurus.config.js index 32fb9d68..d33784f2 100644 --- a/documentation/docusaurus.config.js +++ b/documentation/docusaurus.config.js @@ -36,8 +36,14 @@ const config = { badge: true, path: "", }, + "9.x.x": { + label: "Version 9 (Maintenance LTS)", + banner: "unmaintained", + badge: true, + path: "9.x.x", + }, "8.x.x": { - label: "Version 8 (Active LTS)", + label: "Version 8 (Maintenance LTS)", banner: "unmaintained", badge: true, path: "8.x.x", diff --git a/documentation/sidebars.json b/documentation/sidebars.json index 829f71ea..6babebc2 100644 --- a/documentation/sidebars.json +++ b/documentation/sidebars.json @@ -182,11 +182,6 @@ "id": "api/unsafe-unity-instance", "label": "Access the Unity Instance" }, - { - "type": "doc", - "id": "api/unsafe-detach-unmount-immediate", - "label": "Detach and Unmount Immediate" - }, { "type": "doc", "id": "api/cache-control", diff --git a/documentation/versioned_docs/version-9.x.x/advanced-examples/dynamic-device-pixel-ratio.md b/documentation/versioned_docs/version-9.x.x/advanced-examples/dynamic-device-pixel-ratio.md new file mode 100644 index 00000000..a7b154ff --- /dev/null +++ b/documentation/versioned_docs/version-9.x.x/advanced-examples/dynamic-device-pixel-ratio.md @@ -0,0 +1,53 @@ +# Dynamic Device Pixel Ratio + +In the following example, we'll render our Unity Application using a device pixel ratio which matches the device pixel ratio of the browser. We'll create an event listener using a media matcher which will update the device pixel ratio of the Unity Application when the device pixel ratio changes. + +```jsx showLineNumbers title="App.jsx" +import React, { useState, useEffect } from "react"; +import { Unity, useUnityContext } from "react-unity-webgl"; + +function App() { + const { unityProvider, isLoaded, loadingProgression } = useUnityContext({ + loaderUrl: "build/myunityapp.loader.js", + dataUrl: "build/myunityapp.data", + frameworkUrl: "build/myunityapp.framework.js", + codeUrl: "build/myunityapp.wasm", + }); + + // We'll use a state to store the device pixel ratio. + const [devicePixelRatio, setDevicePixelRatio] = useState( + window.devicePixelRatio + ); + + useEffect( + function () { + // A function which will update the device pixel ratio of the Unity + // Application to match the device pixel ratio of the browser. + const updateDevicePixelRatio = function () { + setDevicePixelRatio(window.devicePixelRatio); + }; + // A media matcher which watches for changes in the device pixel ratio. + const mediaMatcher = window.matchMedia( + `screen and (resolution: ${devicePixelRatio}dppx)` + ); + // Adding an event listener to the media matcher which will update the + // device pixel ratio of the Unity Application when the device pixel + // ratio changes. + mediaMatcher.addEventListener("change", updateDevicePixelRatio); + return function () { + // Removing the event listener when the component unmounts. + mediaMatcher.removeEventListener("change", updateDevicePixelRatio); + }; + }, + [devicePixelRatio] + ); + + return ( + + ); +} +``` diff --git a/documentation/versioned_docs/version-9.x.x/advanced-examples/loading-overlay.md b/documentation/versioned_docs/version-9.x.x/advanced-examples/loading-overlay.md new file mode 100644 index 00000000..528aedb4 --- /dev/null +++ b/documentation/versioned_docs/version-9.x.x/advanced-examples/loading-overlay.md @@ -0,0 +1,75 @@ +import Tabs from "@theme/Tabs"; +import TabItem from "@theme/TabItem"; + +# Loading Overlay + +In the following example, we'll be rendering a Unity Application in our React Application. The Unity Application will render within a container, this allows us to overlay the containing with a loading overlay. This overlay will be visible while the Unity Application is loading. + + + + +```jsx showLineNumbers title="App.jsx" +import React from "react"; +import { Unity, useUnityContext } from "react-unity-webgl"; + +function App() { + const { unityProvider, isLoaded, loadingProgression } = useUnityContext({ + loaderUrl: "build/myunityapp.loader.js", + dataUrl: "build/myunityapp.data", + frameworkUrl: "build/myunityapp.framework.js", + codeUrl: "build/myunityapp.wasm", + }); + + // We'll round the loading progression to a whole number to represent the + // percentage of the Unity Application that has loaded. + const loadingPercentage = Math.round(loadingProgression * 100); + + return ( +
+ {isLoaded === false && ( + // We'll conditionally render the loading overlay if the Unity + // Application is not loaded. +
+

Loading... ({loadingPercentage}%)

+
+ )} + +
+ ); +} +``` + +
+ + +```css showLineNumbers title="App.css" +.container { + position: relative; + /* The container determains the size. */ + width: 800px; + height: 600px; +} + +.container > .loading-overlay { + /* We'll render the overlay on top of the Unity Application. */ + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; + background: grey; + /* We'll set the following Flex properties in order to center the text. */ + display: flex; + justify-content: center; + align-items: center; +} + +.container > .unity { + /* The Unity Application matches it size to the container. */ + width: 100%; + height: 100%; +} +``` + + +
diff --git a/documentation/versioned_docs/version-9.x.x/api/auto-sync-persistent-data-path.md b/documentation/versioned_docs/version-9.x.x/api/auto-sync-persistent-data-path.md new file mode 100644 index 00000000..c8985315 --- /dev/null +++ b/documentation/versioned_docs/version-9.x.x/api/auto-sync-persistent-data-path.md @@ -0,0 +1,34 @@ +# Auto Sync Persistent Data Path + +Enables or disables auto synchronization of the persistent data path. + +## Type Definition + +```tsx title="Type Definition" +const autoSyncPersistentDataPath: boolean = false; +``` + +## Implementation + +If set to true, all file writes inside the Unity `Application.persistentDataPath` directory automatically persist so that the contents are remembered when the user revisits the website the next time. If unset (or set to false), you must manually sync file modifications inside the `Application.persistentDataPath` directory by calling the `JS_FileSystem_Sync()` JavaScript function. + +## Example Usage + +A basic implementation could look something like this. In the following example we'll enable auto synchronization of the persistent data path. + +```jsx {10} showLineNumbers title="App.jsx" +import React from "react"; +import { Unity, useUnityContext } from "react-unity-webgl"; + +function App() { + const { unityProvider } = useUnityContext({ + loaderUrl: "build/myunityapp.loader.js", + dataUrl: "build/myunityapp.data", + frameworkUrl: "build/myunityapp.framework.js", + codeUrl: "build/myunityapp.wasm", + autoSyncPersistentDataPath: true, + }); + + return ; +} +``` diff --git a/documentation/versioned_docs/version-9.x.x/api/cache-control.md b/documentation/versioned_docs/version-9.x.x/api/cache-control.md new file mode 100644 index 00000000..40a50586 --- /dev/null +++ b/documentation/versioned_docs/version-9.x.x/api/cache-control.md @@ -0,0 +1,62 @@ +# Cache Control + +The Cache Control API allows you to control the caching behavior of the Unity WebGL build. + +## Type Definition + +```tsx title="Type Definition" +function cacheControl(url: string): UnityCacheControlMode; +``` + +```tsx title="Type Definition" +type UnityCacheControlMode = "must-revalidate" | "immutable" | "no-store"; +``` + +## Implementation + +In Unity WebGL, the Cache API lets you store the asset data cached in .data files and AssetBundles within the browser cache. Storage limits for the browser cache such as maximum file size, maximum overall cache size, and eviction criteria are dependent on the browser and platform that you’re using. + +By default, the WebGL Cache stores the asset data file .data and AssetBundle files .bundle, and revalidates them before loading them from the cache. You can change this behavior by adding a new WebGL Template that changes the UnityLoader configuration. The Cache Control API allows you to control the caching behavior of the Unity WebGL build. + +:::info +To access Data Caching, open the Publishing Setings for WebGL from File > Build Settings > Player Settings. This enables the browser to cache the main data files into the IndexedDB database. +::: + +The cacheControl function takes the url of a request as a parameter and returns one of the following: + +- `must-revalidate` If the function returns must-revalidate, the cache returns to an enabled state and the file is revalidated before being loaded from the cache. +- `immutable` If the function returns immutable, the cache is enabled and the file is loaded from the cache without revalidation. +- `no-store` - If the function returns no-store, the cache is disabled. + +The browser automatically stores (caches) certain file types such as .html, .js, .css, .json, .jpg, .png, so they don’t need to be explicitly stored in the WebGL Cache. Typical candidates for the WebGL cache include large files and files that use a custom file format. + +## Example Usage + +A basic implementation could look something like this. In the following example we'll apply a method which will handle our custom cache control. Here we'll define various cache control modes for different file types. + +```jsx {5-13,20} showLineNumbers title="App.jsx" +import React from "react"; +import { Unity, useUnityContext } from "react-unity-webgl"; + +function App() { + function handleCacheControl(url) { + if (url.match(/\.data/) || url.match(/\.bundle/)) { + return "must-revalidate"; + } + if (url.match(/\.mp4/) || url.match(/\.wav/)) { + return "immutable"; + } + return "no-store"; + } + + const { unityProvider } = useUnityContext({ + loaderUrl: "build/myunityapp.loader.js", + dataUrl: "build/myunityapp.data", + frameworkUrl: "build/myunityapp.framework.js", + codeUrl: "build/myunityapp.wasm", + cacheControl: handleCacheControl, + }); + + return ; +} +``` diff --git a/documentation/versioned_docs/version-9.x.x/api/canvas-classname.md b/documentation/versioned_docs/version-9.x.x/api/canvas-classname.md new file mode 100644 index 00000000..5aedccf0 --- /dev/null +++ b/documentation/versioned_docs/version-9.x.x/api/canvas-classname.md @@ -0,0 +1,39 @@ +# Setting the Canvas Class Name + +Sets the class name of the Unity Application's canvas. + +## Type Definition + +```tsx title="Type Definition" + +``` + +## Implementation + +Just like you're used to while working on your other Components and Elements, you can add an optional class name to the Unity component. The class name attribute specifies one or more class names for the Unity Application's Canvas. The class name attribute is mostly used to point to a class in a style sheet. + +There are many ways to suplement your React Application with available classnames. The most common ways are by providing an external CSS or importing your stylesheet using a CSS module. It's also possible to use CSS-in-JS, this refers to a pattern where CSS is composed using JavaScript instead of defined in external files. Note that this functionality is not a part of React, but provided by third-party libraries. + +:::info +Some examples in the documentation use style for convenience, but using the style attribute as the primary means of styling elements is generally not recommended by React. In most cases, className should be used to reference classes defined in an external CSS stylesheet or CSS in JS. Style is most often used in React applications to add dynamically-computed styles at render time. +::: + +## Example Usage + +A basic implementation could look something like this. In the following example we'll simply add a classname to the Canvas. + +```jsx showLineNumbers title="App.jsx" +import React from "react"; +import { Unity, useUnityContext } from "react-unity-webgl"; + +function App() { + const { unityProvider } = useUnityContext({ + loaderUrl: "build/myunityapp.loader.js", + dataUrl: "build/myunityapp.data", + frameworkUrl: "build/myunityapp.framework.js", + codeUrl: "build/myunityapp.wasm", + }); + + return ; +} +``` diff --git a/documentation/versioned_docs/version-9.x.x/api/canvas-device-pixel-ratio.md b/documentation/versioned_docs/version-9.x.x/api/canvas-device-pixel-ratio.md new file mode 100644 index 00000000..faecdd36 --- /dev/null +++ b/documentation/versioned_docs/version-9.x.x/api/canvas-device-pixel-ratio.md @@ -0,0 +1,48 @@ +# Device Pixel Ratio and Retina Support + +Sets the device pixel ratio of the Unity Application's canvas. + +:::info +Usage of this feature requires your Unity Application to be built with Unity 2020.1 or newer. +::: + +## Type Definition + +```tsx title="Type Definition" + +``` + +## Implementation + +The Canvas can appear too blurry on retina screens. The device pixel ratio determines how much extra pixel density should be added to allow for a sharper image. Providing this prop will set the device pixel ratio of the Unity Application's canvas by multiplying the default resolution of the canvas by the provided value. + +You can use the browser's device pixel ratio to determine the device pixel ratio of the Unity Application's canvas. Head over to the advanced examples to see [how to implement a dynamic device pixel ratio](/docs/advanced-examples/dynamic-device-pixel-ratio). + +:::warning +The value will be used as a multiplier to the actual canvas scale and will litterally add extra pixels to the canvas. This will have a big impact on the performance of your Unity Application and overall performance of your browser. +::: + +## Example Usage + +A basic implementation could look something like this. In the following example we'll use the browser's device pixel ratio to determine the device pixel ratio of the Unity Application's canvas. You can change this value to 1 on retina screens to see blurry canvas. + +```jsx showLineNumbers title="App.jsx" +import React from "react"; +import { Unity, useUnityContext } from "react-unity-webgl"; + +function App() { + const { unityProvider } = useUnityContext({ + loaderUrl: "build/myunityapp.loader.js", + dataUrl: "build/myunityapp.data", + frameworkUrl: "build/myunityapp.framework.js", + codeUrl: "build/myunityapp.wasm", + }); + + return ( + + ); +} +``` diff --git a/documentation/versioned_docs/version-9.x.x/api/canvas-id.md b/documentation/versioned_docs/version-9.x.x/api/canvas-id.md new file mode 100644 index 00000000..c82e02d3 --- /dev/null +++ b/documentation/versioned_docs/version-9.x.x/api/canvas-id.md @@ -0,0 +1,38 @@ +import Tabs from "@theme/Tabs"; +import TabItem from "@theme/TabItem"; + +# Canvas ID + +Sets a custom ID for the Unity Application's canvas. + +## Type Definition + +```tsx title="Type Definition" + +``` + +## Implementation + +By default, Unity WebGL's canvas requires a unique ID which is used internally by Unity. React Unity WebGL will automatically generate a unique ID for the canvas if one is not provided. However, if you need to set a custom ID for the canvas, you can do so by passing the `id` prop to the `Unity` component. This can be useful if you need to target the canvas for custom implementations or other libraries. + +Using a custom static ID can also be useful for server-side rendering (SSR) where the ID needs to be consistent between the server and client. In this case, you can use the `id` prop to set a static ID for the canvas. + +## Example Usage + +A basic implementation could look something like this. In the following example we'll apply a custom ID to the Unity Application's canvas. + +```jsx {12} showLineNumbers title="App.jsx" +import React from "react"; +import { Unity, useUnityContext } from "react-unity-webgl"; + +function App() { + const { unityProvider } = useUnityContext({ + loaderUrl: "build/myunityapp.loader.js", + dataUrl: "build/myunityapp.data", + frameworkUrl: "build/myunityapp.framework.js", + codeUrl: "build/myunityapp.wasm", + }); + + return ; +} +``` diff --git a/documentation/versioned_docs/version-9.x.x/api/canvas-ref.md b/documentation/versioned_docs/version-9.x.x/api/canvas-ref.md new file mode 100644 index 00000000..d48cfe73 --- /dev/null +++ b/documentation/versioned_docs/version-9.x.x/api/canvas-ref.md @@ -0,0 +1,58 @@ +# Getting the Canvas Reference + +The ref provides a way to access the Unity Application's Canvas element created in the render method. + +:::warning +Even though it is possible to access the Canvas element directly using the ref, it is not recommended to do so. Try to use the built-in Unity Context API functions instead. If something is not working properly, or you're missing functionality, please consider opening an [issue](https://github.com/jeffreylanters/react-unity-webgl/issues), [discussion](https://github.com/jeffreylanters/react-unity-webgl/discussions) or a [pull request](https://github.com/jeffreylanters/react-unity-webgl/pulls). +::: + +## Type Definition + +```tsx title="Type Definition" +} /> +``` + +## Implementation + +The reference of the Unity Application's Canvas element is provided as a prop using a forwarded ref. To access the Canvas element, simply create a ref and pass it to the Unity component. + +```jsx showLineNumbers title="Example: Using a ref hook to store the reference" +const canvasRef = useRef(null); +``` + +```jsx showLineNumbers title="Example: Store the reference in the hook" + +``` + +## Example Usage + +A basic implementation could look something like this. In the following example we'll use a ref hook to store the reference to the Unity Application's Canvas element. We'll then add a button which will focus the canvas when clicked. + +```jsx showLineNumbers title="App.jsx" +import React, { Fragment } from "react"; +import { Unity, useUnityContext } from "react-unity-webgl"; + +function App() { + const { unityProvider } = useUnityContext({ + loaderUrl: "build/myunityapp.loader.js", + dataUrl: "build/myunityapp.data", + frameworkUrl: "build/myunityapp.framework.js", + codeUrl: "build/myunityapp.wasm", + }); + + const canvasRef = useRef(null); + + function focusCanvas() { + if (canvasRef.current) { + canvasRef.current.focus(); + } + } + + return ( + + + + + ); +} +``` diff --git a/documentation/versioned_docs/version-9.x.x/api/canvas-styles.md b/documentation/versioned_docs/version-9.x.x/api/canvas-styles.md new file mode 100644 index 00000000..044565dd --- /dev/null +++ b/documentation/versioned_docs/version-9.x.x/api/canvas-styles.md @@ -0,0 +1,39 @@ +# Adding Styles to the Canvas + +Sets the style of the Unity Application's canvas. + +## Type Definition + +```tsx title="Type Definition" + +``` + +## Implementation + +Just like you're used to while working on your other Components and Elements, the style attribute accepts a JavaScript object with camelCased properties rather than a CSS string. This is consistent with the DOM style JavaScript property, is more efficient, and prevents XSS security holes. + +:::info +Some examples in the documentation use style for convenience, but using the style attribute as the primary means of styling elements is generally not recommended by React. In most cases, className should be used to reference classes defined in an external CSS stylesheet or CSS in JS. Style is most often used in React applications to add dynamically-computed styles at render time. +::: + +## Example Usage + +A basic implementation could look something like this. In the following example we'll simply add some styles to the Canvas. + +```jsx showLineNumbers title="App.jsx" +import React from "react"; +import { Unity, useUnityContext } from "react-unity-webgl"; + +function App() { + const { unityProvider } = useUnityContext({ + loaderUrl: "build/myunityapp.loader.js", + dataUrl: "build/myunityapp.data", + frameworkUrl: "build/myunityapp.framework.js", + codeUrl: "build/myunityapp.wasm", + }); + + return ( + + ); +} +``` diff --git a/documentation/versioned_docs/version-9.x.x/api/disabled-canvas-events.md b/documentation/versioned_docs/version-9.x.x/api/disabled-canvas-events.md new file mode 100644 index 00000000..833477b2 --- /dev/null +++ b/documentation/versioned_docs/version-9.x.x/api/disabled-canvas-events.md @@ -0,0 +1,38 @@ +# Disabled Canvas Events + +Overwrites the default disabled canvas events. + +## Type Definition + +```tsx title="Type Definition" + +``` + +## Implementation + +By default Unity disables the `contextmenu` and `dragstart` events on the canvas element. This is done to prevent the user from right clicking on the canvas and dragging the page while interacting with the Unity Application. Note that by setting the `disabledCanvasEvents` property you'll override the default values. If you don't want this to happen, you'll need to add events these to the array. + +## Example Usage​ + +A basic implementation could look something like this. In the following example overwrite the default values and disable the `dragstart` and `scroll` events. This will also allow the user to right click on the canvas to open the context menu. + +```jsx {10-21} showLineNumbers title="App.jsx" +import React from "react"; +import { Unity, useUnityContext } from "react-unity-webgl"; + +function App() { + const { unityProvider } = useUnityContext({ + loaderUrl: "build/myunityapp.loader.js", + dataUrl: "build/myunityapp.data", + frameworkUrl: "build/myunityapp.framework.js", + codeUrl: "build/myunityapp.wasm", + }); + + return ( + + ); +} +``` diff --git a/documentation/versioned_docs/version-9.x.x/api/event-system.md b/documentation/versioned_docs/version-9.x.x/api/event-system.md new file mode 100644 index 00000000..521c813b --- /dev/null +++ b/documentation/versioned_docs/version-9.x.x/api/event-system.md @@ -0,0 +1,228 @@ +import Tabs from "@theme/Tabs"; +import TabItem from "@theme/TabItem"; + +# Communication from Unity to React + +The event system allows you to receive messages sent from the Unity game. + +## Type Definition + +```tsx title="Type Definition" +function addEventListener( + eventName: string, + callback: (...parameters: ReactUnityEventParameterType[]) => void +): void; +``` + +```tsx title="Type Definition" +function removeEventListener( + eventName: string, + callback: (...parameters: ReactUnityEventParameterType[]) => void +): void; +``` + +```tsx title="Type Definition" +function dispatchReactUnityEvent( + eventName: string, + ...parameters: ReactUnityEventParameterType[] +): void; +``` + +```tsx title="Type Definition" +type ReactUnityEventParameter = string | number | undefined; +``` + +## Implementation + +Sending messages from Unity to React is done by registering an event listener to the Unity Context instance. Event listeners are distinguished by the name of the event. The event listener takes a callback function as its second parameter. The callback function will be invoked when the event is fired, the passed parameters will be passed to the callback function. + +:::info +Keep in mind communication from Unity to React is handeld globally, this means event listeners with the same name will be invoked on all Unity Context instances. +::: + +:::info +Simple numeric types can be passed to JavaScript in function parameters without requiring any conversion. Other data types will be passed as a pointer in the emscripten heap (which is really just a big array in JavaScript). For strings, you can use the Pointerstringify helper function to convert to a JavaScript string. You can read more about [parameters and JavaScript to Unityscript types here](/docs/main-concepts/data-conversion). +::: + +Sending messages from Unity to React consists of two parts, registering an event listener and dispatching an event. + +### Registering event listeners + +An event listeners can be registered to and remove from the Unity Context instance. Start by registering the event listener using the `addEventListener` function as following. To remove an event listener, use the `removeEventListener` function. + +- Where `eventName` is the name of your listener +- The `eventListener` reference will be the function which will be invoked. It may or may not pass along any arguments based on your implementation + +To get started, destructure the add and remove event lister functions from the Unity Context. + +```jsx showLineNumbers title="Example: Destructuring the required functions" +const { addEventListener, removeEventListener } = useUnityContext(); +``` + +Next you'll be able to register and remove the event listeners to and from the Unity Context. + +#### Binding the callback to a state + +When your event listener's callback method's parameters match the parameters of a state, you can bind the callback to the state. This will allow you to update the state when the event is fired. + +```jsx showLineNumbers title="Example: Binding the callback to a state" +const [score, setScore] = useState(); + +useEffect(() => { + addEventListener("SetScore", setScore); + return () => { + removeEventListener("SetScore", setScore); + }; +}, [addEventListener, removeEventListener, setScore]); +``` + +#### Binding the callback to a function + +When your event listener's callback method's parameters don't match the parameters of a state, you can bind the callback to a function. This will allow you to act when the event is fired. + +```jsx showLineNumbers title="Example: Binding the callback to a function" +const handleSetScore = useCallback((score) => { + // Do something with the score +}, []); + +useEffect(() => { + addEventListener("SetScore", handleSetScore); + return () => { + removeEventListener("SetScore", handleSetScore); + }; +}, [addEventListener, removeEventListener, handleSetScore]); +``` + +:::info +While using a function component, always bind your callback using some sort of effect hook, so that the callback is removed when the component is unmounted or will re-render. +::: + +### Dispatching events + +To dispatch events, the module exposes a global function; `dispatchReactUnityEvent`. This function takes the event name and parameters as arguments and will dispatch the event to the corresponding Unity Context. + +To dispatch an event, a JSLib file has to be created within your Unity project's `/Plugins/WebGL` directory. JSLibs are used to invoke javascript functions from within your Unity Application. The React Unity WebGL module exposes a global function to the window which allows for the dispatchment of the Event Listeners. When creating your JSLib, simply invoke the eventName using the global function `dispatchReactUnityEvent` with an optional parameter. + +```js showLineNumbers title="Example: Dispatching an event from a JSLib" +mergeInto(LibraryManager.library, { + SetScore: function (score) { + try { + window.dispatchReactUnityEvent("SetScore", score); + } catch (e) { + console.warn("Failed to dispatch event"); + } + }, +}); +``` + +:::tip +When directly referring to a dispatch function in your JSLib, it is recommended to match the name of the JSLib's function to the name of the event. +::: + +:::tip +Wrap the dispatch event function in a try catch block to prevent errors from being thrown running outside of the React Unity WebGL module. +::: + +Unity makes the JSLib's functions available to the Unity application by merging them into the `LibraryManager.library` object. This allows you to invoke the JSLib's functions from within your Unity application by importing them using Unity's DLL Importer. To link the internal method to the JSLib's function, make sure to match both the name of the function as well as its signature. + +```cs showLineNumbers title="Example: Dispatching an JSLib function from CSharp" +public class GameController : MonoBehaviour { + [DllImport("__Internal")] + private static extern void SetScore (int score); + + public void GameOver () { +#if UNITY_WEBGL == true && UNITY_EDITOR == false + SetScore (259); +#endif + } +} +``` + +:::tip +WebGL methods in general are not available in the Unity Editor. Prevent invoking these methods when the Application is not running the WebGL environment, e.g The Unity Editor. +::: + +## Example Usage + +A basic implementation could look something like this. In the following example we'll register an event listener to listen to an event named "GameOver" with two parameters; the score and the name of the player. The event listener will update the state of the score and display the name of the player. + + + + +```jsx showLineNumbers title="App.jsx" +import React, { Fragment, useState, useCallback, useEffect } from "react"; +import { Unity, useUnityContext } from "react-unity-webgl"; + +function App() { + const [isGameOver, setIsGameOver] = useState(false); + const [userName, setUserName] = useState(); + const [score, setScore] = useState(); + + const { unityProvider, addEventListener, removeEventListener } = + useUnityContext({ + loaderUrl: "build/myunityapp.loader.js", + dataUrl: "build/myunityapp.data", + frameworkUrl: "build/myunityapp.framework.js", + codeUrl: "build/myunityapp.wasm", + }); + + const handleGameOver = useCallback((userName, score) => { + setIsGameOver(true); + setUserName(userName); + setScore(score); + }, []); + + useEffect(() => { + addEventListener("GameOver", handleGameOver); + return () => { + removeEventListener("GameOver", handleGameOver); + }; + }, [addEventListener, removeEventListener, handleGameOver]); + + return ( + + + {isGameOver === true && ( +

{`Game Over ${userName}! You've scored ${score} points.`}

+ )} +
+ ); +} +``` + +
+ + +```cs showLineNumbers title="GameController.cs" +using UnityEngine; +using System.Runtime.InteropServices; + +public class GameController : MonoBehaviour { + [DllImport("__Internal")] + private static extern void GameOver (string userName, int score); + + public void SomeMethod () { +#if UNITY_WEBGL == true && UNITY_EDITOR == false + GameOver ("Player1", 100); +#endif + } +} +``` + + + + +:::info +The name of this file is irrelevant, but it must be placed in the `/Plugins/WebGL` directory of your Unity project. +::: + +```js showLineNumbers title="React.jslib" +mergeInto(LibraryManager.library, { + GameOver: function (userName, score) { + window.dispatchReactUnityEvent("GameOver", UTF8ToString(userName), score); + }, +}); +``` + + +
diff --git a/documentation/versioned_docs/version-9.x.x/api/introduction.md b/documentation/versioned_docs/version-9.x.x/api/introduction.md new file mode 100644 index 00000000..c339dbd7 --- /dev/null +++ b/documentation/versioned_docs/version-9.x.x/api/introduction.md @@ -0,0 +1,5 @@ +# Introduction + +Welcome to the React Unity WebGL API Reference! + +Can't find what you're looking for? Feel free to open a new [discussion](https://github.com/jeffreylanters/react-unity-webgl/discussions) to ask any questions or request a new feature. diff --git a/documentation/versioned_docs/version-9.x.x/api/is-loaded.md b/documentation/versioned_docs/version-9.x.x/api/is-loaded.md new file mode 100644 index 00000000..d353350f --- /dev/null +++ b/documentation/versioned_docs/version-9.x.x/api/is-loaded.md @@ -0,0 +1,59 @@ +# Awaiting the Application Load + +Represents the loaded state of the Unity Application. + +## Type Definition + +```tsx title="Type Definition" +const isLoaded: boolean = false; +``` + +## Implementation + +While your Unity Application is being downloaded from the server and loaded into memory and the loading progression's stateful value is being updated to reflect the progression, you might want to hide your loading screen or display some sort of user interface when the Unity Application has finished loading and is started. + +The Unity Context's is loaded value can be used for such cases. This stateful value will updates based on whether the Unity Application has finished loading and is started. + +To get started, destructure the is loaded value from the Unity Context. + +```jsx showLineNumbers title="Example: Destructuring the is loaded value" +const { isLoaded } = useUnityContext(); +``` + +Next you'll be able to use the is loaded value to display a loading indicator. + +```jsx showLineNumbers title="Example: Using the is loaded value" +if (isLoaded === false) { + return

Loading...

; +} +return

Application Loaded!

; +``` + +:::tip +Display some kind of overlay over your Unity Application while it's loading to prevent the user from interacting with the Unity Application before it's completely ready. And use the [loading progression stateful value](/docs/api/loading-progression) to display a loading bar. +::: + +## Example Usage + +A basic implementation could look something like this. In the following example we'll hide the Unity Application while it's being loaded to prevent the user from interacting with the Unity Application before it's completely ready. + +```jsx showLineNumbers title="App.jsx" +import React from "react"; +import { Unity, useUnityContext } from "react-unity-webgl"; + +function App() { + const { unityProvider, isLoaded } = useUnityContext({ + loaderUrl: "build/myunityapp.loader.js", + dataUrl: "build/myunityapp.data", + frameworkUrl: "build/myunityapp.framework.js", + codeUrl: "build/myunityapp.wasm", + }); + + return ( + + ); +} +``` diff --git a/documentation/versioned_docs/version-9.x.x/api/loading-progression.md b/documentation/versioned_docs/version-9.x.x/api/loading-progression.md new file mode 100644 index 00000000..08e3f733 --- /dev/null +++ b/documentation/versioned_docs/version-9.x.x/api/loading-progression.md @@ -0,0 +1,60 @@ +# Tracking the Loading Progression + +Represents the percentual loading progression of the Unity Application. + +## Type Definition + +```tsx title="Type Definition" +const loadingProgression: number = 0; +``` + +## Implementation + +While your Unity Application is being downloaded from the server and loaded into memory, you might want to display some sort of loading indicator informing the user of the progression. The Unity Context's loading progression value can be used for such cases. This stateful value will update while the Unity Application is being loaded. Its value will be between 0 and 1, where 0 means the Unity Application has not started loading and 1 means the Unity Application has finished loading. + +To get started, destructure the loading progression value from the Unity Context. + +```jsx showLineNumbers title="Example: Destructuring the loading progression value" +const { loadingProgression } = useUnityContext(); +``` + +Next you'll be able to use the loading progression value to display a loading indicator. + +```jsx showLineNumbers title="Example: Using the loading progression value" +

Loading {loadingProgression}...

+``` + +You're not limited by just showing the percentage of the loading progression, you can for example also use it's value to display a loading bar. The posibilities are endless! + +```jsx showLineNumbers title="Example: Using the loading progression value" +
+``` + +:::tip +If you want to do something based on when the Unity Application has finished loading, you can use the [is loaded stateful value](/docs/api/is-loaded) rather than checking whether the loading progression's value is 1. +::: + +## Example Usage + +A basic implementation could look something like this. In the following example we'll track the loading progression and display a text which shows the loading progression as a percentage. + +```jsx showLineNumbers title="App.jsx" +import React from "react"; +import { Unity, useUnityContext } from "react-unity-webgl"; + +function App() { + const { unityProvider, loadingProgression } = useUnityContext({ + loaderUrl: "build/myunityapp.loader.js", + dataUrl: "build/myunityapp.data", + frameworkUrl: "build/myunityapp.framework.js", + codeUrl: "build/myunityapp.wasm", + }); + + return ( + +

Loading Application... {Math.round(loadingProgression * 100)}%

+ +
+ ); +} +``` diff --git a/documentation/versioned_docs/version-9.x.x/api/meta-data.md b/documentation/versioned_docs/version-9.x.x/api/meta-data.md new file mode 100644 index 00000000..c0da3a2b --- /dev/null +++ b/documentation/versioned_docs/version-9.x.x/api/meta-data.md @@ -0,0 +1,36 @@ +# Application Meta Data + +Sets the Unity Application meta data. + +## Type Definition + +```ts title="Type Definition" +type UnityConfig = { + readonly productName?: string; + readonly productVersion?: string; + readonly companyName?: string; +}; +``` + +## Example Usage + +A basic implementation could look something like this. In the following example we'll provide the application meta data. + +```jsx {10-12} showLineNumbers title="App.jsx" +import React from "react"; +import { Unity, useUnityContext } from "react-unity-webgl"; + +function App() { + const { unityProvider } = useUnityContext({ + loaderUrl: "build/myunityapp.loader.js", + dataUrl: "build/myunityapp.data", + frameworkUrl: "build/myunityapp.framework.js", + codeUrl: "build/myunityapp.wasm", + productName: "My Game", + productVersion: "1.0.0", + companyName: "Developer", + }); + + return ; +} +``` diff --git a/documentation/versioned_docs/version-9.x.x/api/request-fullscreen.md b/documentation/versioned_docs/version-9.x.x/api/request-fullscreen.md new file mode 100644 index 00000000..4711d72c --- /dev/null +++ b/documentation/versioned_docs/version-9.x.x/api/request-fullscreen.md @@ -0,0 +1,62 @@ +# Entering or Leaving Fullscreen + +Enabled or disabled te fullscreen mode of the Unity Application's Canvas. + +## Type Definition + +```tsx title="Type Definition" +function requestFullscreen(enabled: boolean): void; +``` + +## Implementation + +The exposed request fullscreen function allows you to enable and disable the fullscreen mode of your Unity Application. The parameter `enabled` is a boolean value that indicates if the fullscreen mode should be enabled or disabled. + +:::info +It is posible to also request locking the pointer within the canvas via the [request pointer lock function](/docs/api/request-pointer-lock) within the Unity Context. Cursor locking and full-screen mode are both supported simultaneously in React Unity WebGL, implemented using their respective HTML5 APIs. +::: + +To get started, destructure the request fullscreen function from the Unity Context. + +```jsx showLineNumbers title="Example: Destructuring the request fullscreen function" +const { requestFullscreen } = useUnityContext(); +``` + +Next you'll be able to invoke the request fullscreen function with the desired state. + +```jsx showLineNumbers title="Example: Using the request fullscreen function" +function handleClick() { + requestFullscreen(true); +} + +return ; +``` + +## Example Usage + +A basic implementation could look something like this. In the following example we'll display a button which will enter fullscreen mode. + +```jsx showLineNumbers title="App.jsx" +import React, { Fragment } from "react"; +import { Unity, useUnityContext } from "react-unity-webgl"; + +function App() { + const { unityProvider, requestFullscreen } = useUnityContext({ + loaderUrl: "build/myunityapp.loader.js", + dataUrl: "build/myunityapp.data", + frameworkUrl: "build/myunityapp.framework.js", + codeUrl: "build/myunityapp.wasm", + }); + + function handleClickEnterFullscreen() { + requestFullscreen(true); + } + + return ( + + + + + ); +} +``` diff --git a/documentation/versioned_docs/version-9.x.x/api/request-pointer-lock.md b/documentation/versioned_docs/version-9.x.x/api/request-pointer-lock.md new file mode 100644 index 00000000..293f363b --- /dev/null +++ b/documentation/versioned_docs/version-9.x.x/api/request-pointer-lock.md @@ -0,0 +1,64 @@ +# Requesting Pointer Locking + +The request pointer lock function lets you asynchronously ask for the pointer to be locked on the Unity Application's canvas. + +## Type Definition + +```tsx title="Type Definition" +function requestPointerLock(): void; +``` + +## Implementation + +The Pointer Lock API provides input methods based on the movement of the mouse over time (i.e., deltas), not just the absolute position of the mouse cursor in the viewport. It gives you access to raw mouse movement, locks the target of mouse events to a single element, eliminates limits on how far mouse movement can go in a single direction, and removes the cursor from view. It is ideal for first person 3D games, for example. + +More than that, the API is useful for any applications that require significant mouse input to control movements, rotate objects, and change entries, for example allowing users to control the viewing angle by moving the mouse around without any button clicking. The buttons are then freed up for other actions. Other examples include apps for viewing maps or satellite imagery. + +Pointer lock lets you access mouse events even when the cursor goes past the boundary of the browser or screen. For example, your users can continue to rotate or manipulate a 3D model by moving the mouse without end. Without Pointer lock, the rotation or manipulation stops the moment the pointer reaches the edge of the browser or screen. Game players can now click buttons and swipe the mouse cursor back and forth without worrying about leaving the game play area and accidentally clicking another application that would take mouse focus away from the game. + +:::info +It is posible to also request entering fullscreen within the canvas via the [request fullscreen function](/docs/api/request-fullscreen) within the Unity Context. Cursor locking and full-screen mode are both supported simultaneously in React Unity WebGL, implemented using their respective HTML5 APIs. +::: + +To get started, destructure the request pointer lock function from the Unity Context. + +```jsx showLineNumbers title="Example: Destructuring the request pointer lock function" +const { requestPointerLock } = useUnityContext(); +``` + +Next you'll be able to invoke the request pointer lock function with the desired state. + +```jsx showLineNumbers title="Example: Using the set fullscreen function" +function handleClick() { + requestPointerLock(); +} + +return
Lock Pointer
; +``` + +## Example Usage + +A basic implementation could look something like this. In the following example we'll add an event listener to the document where if the user clicks anywhere on the screen, the pointer lock will be requested. + +```jsx showLineNumbers title="App.jsx" +import React, { useEffect } from "react"; +import { Unity, useUnityContext } from "react-unity-webgl"; + +function App() { + const { unityProvider, requestPointerLock } = useUnityContext({ + loaderUrl: "build/myunityapp.loader.js", + dataUrl: "build/myunityapp.data", + frameworkUrl: "build/myunityapp.framework.js", + codeUrl: "build/myunityapp.wasm", + }); + + useEffect(() => { + document.addEventListener("click", requestPointerLock); + return () => { + document.removeEventListener("click", requestPointerLock); + }; + }, [requestPointerLock]); + + return ; +} +``` diff --git a/documentation/versioned_docs/version-9.x.x/api/send-message.md b/documentation/versioned_docs/version-9.x.x/api/send-message.md new file mode 100644 index 00000000..8f090a7c --- /dev/null +++ b/documentation/versioned_docs/version-9.x.x/api/send-message.md @@ -0,0 +1,93 @@ +import Tabs from "@theme/Tabs"; +import TabItem from "@theme/TabItem"; + +# Communication from React to Unity + +The send message function lets you asynchronously invoke a method in the Unity game. + +## Type Definition + +```tsx title="Type Definition" +function sendMessage( + gameObjectName: string, + methodName: string, + parameter?: ReactUnityEventParameterType +): void; +``` + +```tsx title="Type Definition" +type ReactUnityEventParameter = string | number | undefined; +``` + +## Implementation + +Sending messages from React to Unity is done using the send message function available via the Unity Context instance. The send message function is similar to the SendMessage Method found internally in Unity. The function will invoke a C-Sharp method of any protection level on an active GameObject in your Scene. + +- Where `gameObjectName` is the name of an object in your scene +- `methodName` is the name of a C-Sharp method in the script, currently attached to that object +- `parameter` can be a string, a number, boolean or not defined at all + +:::note +When invoking a C-Sharp method by sending a message, the name of the mono behaviour is not being used. We're only refering to the name of the GameObject within the Scene, thus the name of the mono behaviour is irrelevant. +::: + +:::warning +Make sure the parameter matches the actual existence and type of the C-Sharp method you're trying to invoke. Not +doing so may cause unintended behaviour or even a crash of the Unity Application. +::: + +:::info +Simple numeric types can be passed to JavaScript in function parameters without requiring any conversion. Other data types will be passed as a pointer in the emscripten heap (which is really just a big array in JavaScript). For strings, you can use the Pointerstringify helper function to convert to a JavaScript string. You can read more about [parameters and JavaScript to Unityscript types here](/docs/main-concepts/data-conversion). +::: + +## Example Usage + +A basic implementation could look something like this. In the following example a button is being rendered. When the button is clicked, a function will invoked telling the Unity Context to send a message to a GameObject named "GameController" to invoke the C-Sharp method named "SpawnEnemies" with an interger as the parameter. + + + + +```jsx showLineNumbers title="App.jsx" +import React, { Fragment } from "react"; +import { Unity, useUnityContext } from "react-unity-webgl"; + +function App() { + const { unityProvider, sendMessage } = useUnityContext({ + loaderUrl: "build/myunityapp.loader.js", + dataUrl: "build/myunityapp.data", + frameworkUrl: "build/myunityapp.framework.js", + codeUrl: "build/myunityapp.wasm", + }); + + function handleClickSpawnEnemies() { + sendMessage("GameController", "SpawnEnemies", 100); + } + + return ( + + + + + ); +} +``` + + + + +:::info +Script is attached to GameObject with name "GameController". +::: + +```cs showLineNumbers title="EnemyController.cs" +using UnityEngine; + +public class EnemyController : MonoBehaviour { + public void SpawnEnemies (int amount) { + Debug.Log ($"Spawning {amount} enemies!"); + } +} +``` + + + diff --git a/documentation/versioned_docs/version-9.x.x/api/streaming-assets.md b/documentation/versioned_docs/version-9.x.x/api/streaming-assets.md new file mode 100644 index 00000000..1769248f --- /dev/null +++ b/documentation/versioned_docs/version-9.x.x/api/streaming-assets.md @@ -0,0 +1,36 @@ +# Streaming Assets + +When using Streaming Assets, a URL (or Path) can be defined where your Unity Application can find these files. The URL will be used as the base of every Streaming Asset request. + +## Type Definition + +```ts title="Type Definition" +type UnityConfig = { + readonly streamingAssetsUrl?: string; +}; +``` + +:::caution +All of the URLs which can be provided to the Unity Config, including the ones mentioned above, are due to their enormous size **not included into your bundle**. You should place these files in a public directory within your project or use a CDN. This means the files behind these URLs are loaded during runtime and should be accessible by the browser via a public URL. +::: + +## Example Usage + +A basic implementation could look something like this. In the following example we'll set the streaming assets url to the "streamingassets" directory. + +```jsx {10} showLineNumbers title="App.jsx" +import React from "react"; +import { Unity, useUnityContext } from "react-unity-webgl"; + +function App() { + const { unityProvider } = useUnityContext({ + loaderUrl: "build/myunityapp.loader.js", + dataUrl: "build/myunityapp.data", + frameworkUrl: "build/myunityapp.framework.js", + codeUrl: "build/myunityapp.wasm", + streamingAssetsUrl: "streamingassets", + }); + + return ; +} +``` diff --git a/documentation/versioned_docs/version-9.x.x/api/tab-index.md b/documentation/versioned_docs/version-9.x.x/api/tab-index.md new file mode 100644 index 00000000..fdba4515 --- /dev/null +++ b/documentation/versioned_docs/version-9.x.x/api/tab-index.md @@ -0,0 +1,68 @@ +import Tabs from "@theme/Tabs"; +import TabItem from "@theme/TabItem"; + +# Tab Index and Input Keyboard Capturing + +Sets the tab index of the Unity Application's canvas. + +## Type Definition + +```tsx title="Type Definition" + +``` + +## Implementation + +By default, a Unity WebGL Application captures the keyboard as soon as it's loaded. This means that all keyboard input on your React Application is captured by the Unity Application instead. Doing so will result in a focus and blur on all keyboard events when clicking on, or around the Unity Application. Implementing the tab index of the element mitigates this issue and allows for other elements to be selected. + +In order for this to work, Capture All Keyboard Input has to be set to false within your Unity Application. Preferably as soon as the Application is loaded. This property determines whether keyboard inputs are captured by WebGL. If this is enabled (default), all inputs will be received by the WebGL canvas regardless of focus, and other elements in the webpage will not receive keyboard inputs. You need to disable this property if you need inputs to be received by other html input elements. + +```cs showLineNumbers title="Example: Disable Capture All Keyboard Input on load" +WebGLInput.captureAllKeyboardInput = false; +``` + +## Example Usage + +A basic implementation could look something like this. In the following example we'll set the Unity Application's canvas's tab index to a specific value allowing other elements such as HTML Input Elements and HTML TextArea Elements to capture input too. + + + + +```jsx showLineNumbers title="App.jsx" +import React, { Fragment } from "react"; +import { Unity, useUnityContext } from "react-unity-webgl"; + +function App() { + const { unityProvider } = useUnityContext({ + loaderUrl: "build/myunityapp.loader.js", + dataUrl: "build/myunityapp.data", + frameworkUrl: "build/myunityapp.framework.js", + codeUrl: "build/myunityapp.wasm", + }); + + return ( + + + + + ); +} +``` + + + + +```cs showLineNumbers title="Example.cs" +using UnityEngine; + +public class Example : MonoBehaviour { + void Awake () { +#if UNITY_WEBGL == true && UNITY_EDITOR == false + WebGLInput.captureAllKeyboardInput = false; +#endif + } +} +``` + + + diff --git a/documentation/versioned_docs/version-9.x.x/api/take-screenshot.md b/documentation/versioned_docs/version-9.x.x/api/take-screenshot.md new file mode 100644 index 00000000..5ad02192 --- /dev/null +++ b/documentation/versioned_docs/version-9.x.x/api/take-screenshot.md @@ -0,0 +1,80 @@ +# Capturing a Screenshot + +Takes a screenshot of the canvas and returns a data URL containing image data. + +## Type Definition + +```tsx title="Type Definition" +function takeScreenshot( + dataType?: string, + quality?: number +): string | undefined; +``` + +## Implementation + +Takes a screenshot of the canvas and returns a data URL containing image data. An optional data type can be provided, this parameter has to contain a valid image mimetype such as `image/png` or `image/jpg`. If no data type is provided, the default value of `image/png` is used. The quality of the image is optional, if not provided the default value of 0.9 is used. The quality is only used for the `image/jpg` mimetype. + +If an attempt to take a screenshot was made before the Unity Application was initialized, the function will return `undefined` instead of a data URL. + +:::info +In order to take screenshot of the Unity WebGL canvas, you'll need to enable preserve drawing buffer within the WebGL context attributes. Enabling this feature makes sure that the canvas is not cleared before the screenshot is taken. This setting en disabled by default, and can be enabled via the Unity Config's [WebGLRenderingContext](/docs/api/webgl-rendering-context) property. + +```jsx showLineNumbers title="Example: Preserving the Drawing Buffer" +const unityContext = useUnityContext({ + webglContextAttributes: { + preserveDrawingBuffer: true, + }, +}); +``` + +::: + +To get started, destructure the take screenshot function from the Unity Context. + +```jsx showLineNumbers title="Example: Destructuring the take screenshot function" +const { takeScreenshot } = useUnityContext(); +``` + +Next you'll be able to invoke the take screenshot function with the desired image type and quality. + +```jsx showLineNumbers title="Example: Using the take screenshot function" +function handleClick() { + const dataUrl = takeScreenshot("image/jpg", 1.0); +} + +return ; +``` + +## Example Usage + +A basic implementation could look something like this. In the following example we'll display a button which allows the user to take a screenshot of the Unity WebGL canvas. For demonstration purposes, we'll open the image in a new tab. + +```jsx showLineNumbers title="App.jsx" +import React, { Fragment } from "react"; +import { Unity, useUnityContext } from "react-unity-webgl"; + +function App() { + const { unityProvider, takeScreenshot } = useUnityContext({ + loaderUrl: "build/myunityapp.loader.js", + dataUrl: "build/myunityapp.data", + frameworkUrl: "build/myunityapp.framework.js", + codeUrl: "build/myunityapp.wasm", + webglContextAttributes: { + preserveDrawingBuffer: true, + }, + }); + + function handleClickTakeScreenshot() { + const dataUrl = takeScreenshot("image/jpg", 0.5); + window.open(dataUrl, "_blank"); + } + + return ( + + + + + ); +} +``` diff --git a/documentation/versioned_docs/version-9.x.x/api/unload.md b/documentation/versioned_docs/version-9.x.x/api/unload.md new file mode 100644 index 00000000..42b60ce5 --- /dev/null +++ b/documentation/versioned_docs/version-9.x.x/api/unload.md @@ -0,0 +1,71 @@ +# Unloading the Unity Application + +Requests the Unity Application to be unloaded from memory in order to be unmounted from the DOM. + +## Type Definition + +```tsx title="Type Definition" +function unload(): Promise | undefined; +``` + +## Implementation + +:::info +The unload function is only available in Unity Builds created with Unity 2020.1 or later. +::: + +:::danger +In earlier versions of Unity, it was possible to unmount the Unity Application and its containing component immediately after invoking the unload function. However, due to a bug in newer Unity versions, this is no longer feasible when using builds made with Unity 2021.2 or later. While it is still possible to unload the Unity Application, the canvas must remain mounted until the associated promise is resolved. + +As of this writing, the issue has not been resolved. However, it is possible to manually unmount the Unity Application by halting navigation to the next page. A ticket has been submitted, and the Unity team has acknowledged this as a known issue. For more details, refer to the [GitHub issue](https://github.com/jeffreylanters/react-unity-webgl/issues/250). + +Alternatively, you can use the unsafe `detachAndUnloadImmediate` function to immediately unmount the Unity Application. However, this is not recommended unless you are an advanced user. For more information, refer to the [Unsafe Detach and Unload Immediate](/docs/api/unsafe-detach-unmount-immediate) documentation. +::: + +When building a multi-page React Application, it is important to unload the Unity Application in order to completely unmount the component from the DOM to free up the memory taken by the Unity JavaScript heap, and without Unity throwing an error. Invoking the function will request the Unity Application to be unloaded from memory. The function will return a Promise that will be resolved when the Unity Application has been unloaded. + +To get started, destructure the unload function from the Unity Context. + +```jsx showLineNumbers title="Example: Destructuring the unload function" +const { unload } = useUnityContext(); +``` + +Next you'll be able to invoke the awaitable unload function to unload the Unity Application. + +```jsx showLineNumbers title="Example: Using the take screenshot function" +async function handleClick() { + await unload(); +} + +return ; +``` + +## Example Usage + +A basic implementation could look something like this. In the following example we'll display a button which allows the user to navigate to another page, but before this happens, the Unity Application will be unloaded. + +```jsx showLineNumbers title="App.jsx" +import React, { Fragment } from "react"; +import { Unity, useUnityContext } from "react-unity-webgl"; + +function App() { + const { unityProvider, unload } = useUnityContext({ + loaderUrl: "build/myunityapp.loader.js", + dataUrl: "build/myunityapp.data", + frameworkUrl: "build/myunityapp.framework.js", + codeUrl: "build/myunityapp.wasm", + }); + + async function handleClickBack() { + await unload(); + // Ready to navigate to another page. + } + + return ( + + + + + ); +} +``` diff --git a/documentation/docs/api/unsafe-detach-unmount-immediate.md b/documentation/versioned_docs/version-9.x.x/api/unsafe-detach-unmount-immediate.md similarity index 100% rename from documentation/docs/api/unsafe-detach-unmount-immediate.md rename to documentation/versioned_docs/version-9.x.x/api/unsafe-detach-unmount-immediate.md diff --git a/documentation/versioned_docs/version-9.x.x/api/unsafe-unity-instance.md b/documentation/versioned_docs/version-9.x.x/api/unsafe-unity-instance.md new file mode 100644 index 00000000..2b27adb4 --- /dev/null +++ b/documentation/versioned_docs/version-9.x.x/api/unsafe-unity-instance.md @@ -0,0 +1,38 @@ +# Unsafe Unity Instance + +:::warning +**It is not recommended to use this API unless you are an advanced user.** Please make sure that any changes made to, or events bound to the Unity Instance are not reflected inside of the module. This could lead to unexpected behaviour, use with caution. +::: + +In the rare case that you need to access the Unity Instance directly, you can do so by using the `useUnityContext` hook to return a reference to the Unity Instance. + +## Type Definition + +```ts title="Type Definition" +const UNSAFE__unityInstance: UnityInstance | null = null; +``` + +## Example Usage + +A basic implementation could look something like this. In the following example we'll bind the Unity Instance to the window so external scripts can access it. + +```jsx {12-15} showLineNumbers title="App.jsx" +import React, { useEffect } from "react"; +import { Unity, useUnityContext } from "react-unity-webgl"; + +function App() { + const { unityProvider, UNSAFE__unityInstance } = useUnityContext({ + loaderUrl: "build/myunityapp.loader.js", + dataUrl: "build/myunityapp.data", + frameworkUrl: "build/myunityapp.framework.js", + codeUrl: "build/myunityapp.wasm", + }); + + useEffect( + () => (window.unityInstance = UNSAFE__unityInstance), + [UNSAFE__unityInstance] + ); + + return ; +} +``` diff --git a/documentation/versioned_docs/version-9.x.x/api/web-worker.md b/documentation/versioned_docs/version-9.x.x/api/web-worker.md new file mode 100644 index 00000000..92a2ffca --- /dev/null +++ b/documentation/versioned_docs/version-9.x.x/api/web-worker.md @@ -0,0 +1,33 @@ +# Using a Web Worker + +When using a web worker, you can provide the URL to the Unity Web Worker file. +Web Workers are particularly useful when your Unity application performs heavy computations or processing that could potentially block the main thread. By moving these operations to a separate thread, your application remains responsive to user interactions. + +## Type Definition + +```ts title="Type Definition" +type UnityConfig = { + readonly workerUrl?: string; +}; +``` + +## Example Usage + +Here's a basic implementation showing how to configure the web worker. In this example, we'll set the worker URL to point to the Unity worker file in the build directory. + +```jsx showLineNumbers title="App.jsx" +import React from "react"; +import { Unity, useUnityContext } from "react-unity-webgl"; + +function App() { + const { unityProvider } = useUnityContext({ + loaderUrl: "build/myunityapp.loader.js", + dataUrl: "build/myunityapp.data", + frameworkUrl: "build/myunityapp.framework.js", + codeUrl: "build/myunityapp.wasm", + workerUrl: "build/myunityapp.worker.js", + }); + + return ; +} +``` diff --git a/documentation/versioned_docs/version-9.x.x/api/webgl-rendering-context.md b/documentation/versioned_docs/version-9.x.x/api/webgl-rendering-context.md new file mode 100644 index 00000000..d4af2cf7 --- /dev/null +++ b/documentation/versioned_docs/version-9.x.x/api/webgl-rendering-context.md @@ -0,0 +1,104 @@ +# WebGL Rendering Context + +The WebGLContexAttributes allow you to configure WebGLRenderingContext creation options when passed as an additional context attributes parameter to the UnityContext. An object can be used as the WebGLContextAttributes and if the properties below are specified on it, they will be used instead of the default values. Only the options passed to the first call will apply, subsequent calls will ignore the attributes. + +## Type Definition + +```ts title="Type Definition" +type WebGLContextAttributes = { + readonly alpha?: boolean; + readonly antialias?: boolean; + readonly depth?: boolean; + readonly failIfMajorPerformanceCaveat?: boolean; + readonly powerPreference?: 0 | 1 | 2; + readonly premultipliedAlpha?: boolean; + readonly preserveDrawingBuffer?: boolean; + readonly stencil?: boolean; + readonly desynchronized?: boolean; + readonly xrCompatible?: boolean; +}; +``` + +## Implementation + +Provide any of the following properties to the WebGLContextAttributes object to override the default values. + +#### Alpha + +If set to true, the context will have an alpha (transparency) channel. + +#### Antialias + +If set to true, the context will attempt to perform antialiased rendering if possible. + +#### Depth + +If set to true, the context will have a 16 bit depth buffer. Defaults to true. Use gl.enable(DEPTH_TEST) to enable the depth test and gl.depthFunc(), gl.depthMask(), and gl.depthRange() to configure the depth test. + +#### Fail if major performance caveat + +If the value is true, context creation will fail if the implementation determines that the performance of the created WebGL context would be dramatically lower than that of a native application making equivalent OpenGL calls. This could happen for a number of reasons, including an implementation might switch to a software rasterizer if the user's GPU driver is known to be unstable. And an implementation might require reading back the framebuffer from GPU memory to system memory before compositing it with the rest of the page, significantly reducing performance. + +#### Power preference + +Provides a hint to the user agent indicating what configuration of GPU is suitable for this WebGL context. This may influence which GPU is used in a system with multiple GPUs. For example, a dual-GPU system might have one GPU that consumes less power at the expense of rendering performance. Note that this property is only a hint and a WebGL implementation may choose to ignore it. WebGL implementations use context lost and restored events to regulate power and memory consumption, regardless of the value of this attribute. + +The value expected to be `0` for `default`, `1` for `low-power` or `2` for `high-performance`. See the following enum: + +``` +0: Default +1: Low Power +2: High Performance +``` + +#### Premultiplied alpha + +If set to true, the color channels in the framebuffer will be stored premultipled by the alpha channel to improve performance. + +#### Preserve drawing buffer + +If set to false, the buffer will be cleared after rendering. If you wish to use canvas.toDataURL(), you will either need to draw to the canvas immediately before calling toDataURL(), or set preserveDrawingBuffer to true to keep the buffer available after the browser has displayed the buffer (at the cost of increased memory use). + +#### Stencil + +Stenciling enables and disables drawing on a per-pixel basis. It is typically used in multipass rendering to achieve special effects. + +#### Desynchronized + +If set to true, the context will have an 8 bit stencil buffer. Defaults to false. Use gl.enable(STENCIL_TEST) to enable depth test and gl.stencilFunc(), gl.stencilFuncSeparate(), gl.stencilMask(), gl.stencilMaskSeparate(), gl.stencilOp(), and gl.stencilOpSeparate() to configure the stencil test. + +#### xrCompatible + +xrCompatible is a boolean that indicates whether the context is compatible. + +## Example Usage + +A basic implementation could look something like this. + +```jsx {10-21} showLineNumbers title="App.jsx" +import React from "react"; +import { Unity, useUnityContext } from "react-unity-webgl"; + +function App() { + const { unityProvider } = useUnityContext({ + loaderUrl: "build/myunityapp.loader.js", + dataUrl: "build/myunityapp.data", + frameworkUrl: "build/myunityapp.framework.js", + codeUrl: "build/myunityapp.wasm", + webglContextAttributes: { + alpha: true, + antialias: true, + depth: true, + failIfMajorPerformanceCaveat: true, + powerPreference: "high-performance", + premultipliedAlpha: true, + preserveDrawingBuffer: true, + stencil: true, + desynchronized: true, + xrCompatible: true, + }, + }); + + return ; +} +``` diff --git a/documentation/versioned_docs/version-9.x.x/contributing.md b/documentation/versioned_docs/version-9.x.x/contributing.md new file mode 100644 index 00000000..fe4446b2 --- /dev/null +++ b/documentation/versioned_docs/version-9.x.x/contributing.md @@ -0,0 +1,28 @@ +# Contributing + +You're looking into contributing? Awesome! When contributing to this mono-repository, please first discuss the change you wish to make via the [discussion board](https://github.com/jeffreylanters/react-unity-webgl/discussions) with me before making a change. Before submitting a pull request, please make sure the following is done: + +- Create a public fork the React Unity WebGL mono-repository and commit your changes to a new branch which is based from the original repository's main branch. +- Make sure both the module as well as the documentation installs using `npm install`, your code lints using `ts lint`, is formatted using [prettier](https://github.com/prettier/prettier) and compiles using `npm run build`. +- Typecheck all of your changes and make sure the documentation in both the source code as well as the official website is up to date and reflects the changes you've made. +- Make sure your changes passes and are compatibly with Unity WebGL builds using the [testing suite](https://github.com/jeffreylanters/react-unity-webgl/tree/main/testing). + +## Development and Test-Cycle + +> When building this module, do not use a symlink-based technique (e.g. with the "npm link" command) [because npm link breaks libraries that are based on React](https://dev.to/vcarl/testing-npm-packages-before-publishing-h7o). + +> When installing, make sure the module does not install React due to it being listed in the peer dependencies. This module must not have a dependency on React, only a dev dependency on @types/react. Otherwise, the users of this module might install two different versions of React which will lead to problems. + +If you want to modify the module and iteratively test it in inside your React Application, use one the following techniques while you're inside the directory of the testing suite. + +The `npm pack` command creates a .tgz file exactly the way it would if you were going to publish the module to npm. You can use that .tgz file to install it in your app. That way you can be sure that everything works exactly as it will do when you publish the module, later. + +It is also possible to install the module locally using a relative path rather than using a package name. This can be very useful if you want to test the module in your own React Application while being able to keep using live editing features such as hot module reloading and fast refreshing. + +## Documentation Contribution + +English is my second language and I suffer from dyslexia. I try to document everything as clearly and correctly as possible. Contributions to spelling and grammar errors are more than welcome and much appreciated. + +Thanks for your contribution! + +Happy coding! diff --git a/documentation/versioned_docs/version-9.x.x/getting-started/hello-world.md b/documentation/versioned_docs/version-9.x.x/getting-started/hello-world.md new file mode 100644 index 00000000..166ebe8a --- /dev/null +++ b/documentation/versioned_docs/version-9.x.x/getting-started/hello-world.md @@ -0,0 +1,23 @@ +# Hello World + +It's easy and simple to get your first React Unity WebGL project up-and-running. Just make sure you have your Unity WebGL build ready, and have your React project all set up. If it's your first time working with React, I recommend checking out [Vite React template](https://vitejs.dev/guide/). + +Get started by importing the Unity Component and Unity Context hook from the module. A basic implementation of the Unity Context Hook only requires some basic configuration. While it is taking care of everything complicated such as communication, event listeners and references internally, all we're interested in is the Unity Provider spit out by the hook. We're going to pass down this object in order to render the configured Unity Application. + +A basic implementation should look something like this: + +```jsx showLineNumbers title="App.jsx" +import React from "react"; +import { Unity, useUnityContext } from "react-unity-webgl"; + +function App() { + const { unityProvider } = useUnityContext({ + loaderUrl: "build/myunityapp.loader.js", + dataUrl: "build/myunityapp.data", + frameworkUrl: "build/myunityapp.framework.js", + codeUrl: "build/myunityapp.wasm", + }); + + return ; +} +``` diff --git a/documentation/versioned_docs/version-9.x.x/getting-started/installation.md b/documentation/versioned_docs/version-9.x.x/getting-started/installation.md new file mode 100644 index 00000000..b85da3d3 --- /dev/null +++ b/documentation/versioned_docs/version-9.x.x/getting-started/installation.md @@ -0,0 +1,23 @@ +# Installation + +Get started by installing React Unity WebGL using the Node Package Manager or Yarn in your JavaScript or TypeScript React project. If you don't have a React project yet, I recommend using [Vite React template](https://vitejs.dev/guide/) to get you started right away. + +:::tip +Before installing the module, make sure you're installing a version which is compatible with your build's Unity version. When a new Unity version releases, I'll update the module as soon as possible in order to keep the compatibility. If you are running into any issues, please open an issue on the [React Unity WebGL Github page](https://github.com/jeffreylanters/react-unity-webgl/issues). +::: + +```sh +% npm install react-unity-webgl +``` + +## Requirements + +- [React](https://reactjs.org) version >= 16.8.0 or above +- [Unity](https://unity.com) version >= 2020.1.0 or above + - If you are using an older version of Unity which does not support Web Assemly, using a module version prior to version 9 is required. To find out more, read the Unity Version Compatibility section below. + +## Unity Version Compatibility + +The web and Unity are evolving fast, to keep up with these changes the React Unity WebGL module has to adapt too while also keeping the module fast, lightweight and compatible. Starting at version 9 of the module, support for builds made with Unity versions prior to 2020 are no longer supported. If you're using an older version of Unity, or you'll have to maintain a project built with an older version of the module, you can use one of the legacy versions of React Unity WebGL. It however is recommended to update your project to a newer version of Unity in order to use all the latest features of React Unity WebGL. + +Select another version tag in the top right corner of this website to view the documentation and API reference of older versions of React Unity WebGL. diff --git a/documentation/versioned_docs/version-9.x.x/introduction.md b/documentation/versioned_docs/version-9.x.x/introduction.md new file mode 100644 index 00000000..c57c3adb --- /dev/null +++ b/documentation/versioned_docs/version-9.x.x/introduction.md @@ -0,0 +1,7 @@ +# Introduction + +Welcome to the React Unity WebGL documentation! My name is [Jeffrey Lanters](https://twitter.com/jeffreylanters), and I'm here to help you bring your awesome games to the web! Everything you'll need to know from get started to creating complex interactive systems can be found in this documentation. If you'll need help, feel free to open a new [discussion](https://github.com/jeffreylanters/react-unity-webgl/discussions), when you want to contribute or think you've found a problem, feel free to open a new [issue](https://github.com/jeffreylanters/react-unity-webgl/issues). And if you like what you see, please consider [starring this repository](https://github.com/jeffreylanters/react-unity-webgl/stargazers) or by [suporting the project](https://react-unity-webgl.dev/support)! + +If you're stuck or need professional assistance and are looking for personal help over a video call, feel free to reach out to me on [Twitter](https://twitter.com/jeffreylanters) or send me an email to [support@jeffreylanters.me](mailto:support@jeffreylanters.me). + +Happy coding! 🚀 diff --git a/documentation/versioned_docs/version-9.x.x/main-concepts/data-conversion.md b/documentation/versioned_docs/version-9.x.x/main-concepts/data-conversion.md new file mode 100644 index 00000000..966fba5a --- /dev/null +++ b/documentation/versioned_docs/version-9.x.x/main-concepts/data-conversion.md @@ -0,0 +1,32 @@ +# Data Conversion + +Simple numeric types can be passed to JavaScript in function parameters without requiring any conversion. Other data types will be passed as a pointer in the emscripten heap (which is really just a big array in JavaScript). For strings, you can use the Pointerstringify helper function to convert to a JavaScript string. + +To return a string value you need to call \_malloc to allocate some memory and the writeStringToMemory helper function to write a JavaScript string to it. If the string is a return value, then the il2cpp runtime will take care of freeing the memory for you. + +For arrays of primitive types, emscripten provides different ArrayBufferViews into it’s heap for different sizes of integer, unsigned integer or floating point representations of memory: HEAP8, HEAPU8, HEAP16, HEAPU16, HEAP32, HEAPU32, HEAPF32, HEAPF64. To access a texture in WebGL, emscripten provides the GL.textures array which maps native texture IDs from Unity to WebGL texture objects. WebGL functions can be called on emscripten’s WebGL context, GLctx. + +A basic implementation could look something like this. In this example a series of methods is merged into the Unity library making this methods availble in CSharp. Each of these methods contain an example on how to handle specific types of data. No worries, the methods used for the conversion such as "UTF8ToString" and "HEAPF32" are available natively. + +```js showLineNumbers title="Example: Converting Data Types" +mergeInto(LibraryManager.library, { + GameOver: function () { + window.UnityEvent("GameOver"); + }, + NextWave: function (waveNumberValue) { + window.dispatchReactUnityEvent("NextWave", waveNumberValue); + }, + ShowPopup: function (textStringPointer) { + window.dispatchReactUnityEvent( + "ShowPopup", + UTF8ToString(textStringPointer) + ); + }, + SubmitScores: function (scoresFloatArrayPointer, arraySize) { + var scores = []; + for (var i = 0; i < arraySize; i++) + scores.push(HEAPF32[(scoresFloatArrayPointer >> 2) + i]); + window.dispatchReactUnityEvent("SubmitScores", scores); + }, +}); +``` diff --git a/documentation/versioned_docs/version-9.x.x/main-concepts/project-structure.md b/documentation/versioned_docs/version-9.x.x/main-concepts/project-structure.md new file mode 100644 index 00000000..fd45dc9b --- /dev/null +++ b/documentation/versioned_docs/version-9.x.x/main-concepts/project-structure.md @@ -0,0 +1,7 @@ +# Project Structure + +:::info +This page is still under construction. +::: + + diff --git a/documentation/versioned_docs/version-9.x.x/main-concepts/unity-config.md b/documentation/versioned_docs/version-9.x.x/main-concepts/unity-config.md new file mode 100644 index 00000000..a5e79ea3 --- /dev/null +++ b/documentation/versioned_docs/version-9.x.x/main-concepts/unity-config.md @@ -0,0 +1,18 @@ +# Unity Config + +When rendering your Unity Application within a React Application, you'll have to pass along the Unity Provider to the Unity Component. When the Unity Component is being mounted, it will take the Unity Context's configuration and initialises the required resources in order to render your Unity Application. During this process, the Unity Context's state will be updated to reflect the Unity Application's. + +When using the Unity Context hook, you'll need to provide a Unity Config object. A most basic Unity Config consists the four following properties. These four properties are all URLs which are required to initialise the Unity Application. + +- The **`LoaderUrl`**, this is a JavaScript file which contains the Unity Engine bootstrapping code. This file is required to load the Unity Engine and start the initialization process. +- The **`FrameworkUrl`**, this is a JavaScript file which contains the Runtime and Plugin code. This file is responsible for running the actual Unity Application. +- The **`DataUrl`**, this is a JSON file which contains the initial Unity Application state including your Assets and Scenes. This file can get big really fast so try to optimize your game's assets as much as possible. Try using both building and runtime compression techniques and usefull packages such as sprite atlasses. +- The **`CodeUrl`**, this is a Web Assembly binary file containg native code. + +:::caution +All of the URLs which can be provided to the Unity Config, including the ones mentioned above, are due to their enormous size **not included into your bundle**. You should place these files in a public directory within your project or use a CDN. This means the files behind these URLs are loaded during runtime and should be accessible by the browser via a public URL. +::: + +There are many more properties you can pass to the Unity Config object. These properties are all optional and can be found in the documentation. + +Sounds complicated? No worries, you don't need to remember any of the meanings behind these files. The module will take care of all of this for you. Just add the paths to the files to the Unity Context, sit back and enjoy! diff --git a/documentation/versioned_docs/version-9.x.x/miscellaneous-instructions/browser-compatibility.md b/documentation/versioned_docs/version-9.x.x/miscellaneous-instructions/browser-compatibility.md new file mode 100644 index 00000000..961420b1 --- /dev/null +++ b/documentation/versioned_docs/version-9.x.x/miscellaneous-instructions/browser-compatibility.md @@ -0,0 +1,18 @@ +# WebGL Browser Compatibility + +Unity’s WebGL +support for desktop browsers differs depending on the browser. It supports browsers providing the following conditions are true: + +- The browser is WebGL 1 or WebGL 2 capable. Note: Unity has marked WebGL 1 support for deprecation and will remove it in a future release. +- The browser is HTML 5 standards-compliant. +- The browser is 64-bit and supports WebAssembly. + +Unity WebGL doesn’t support mobile devices. It might work on high-end devices, but current devices are often not powerful enough and don’t have enough memory to support Unity WebGL content. To make the end user aware of this, the default template for Unity WebGL displays a warning message when the end user attempts to load a Unity WebGL application on a mobile browser. To remove this warning from your application, add your own WebGL template. For information on how to do this, see Add a WebGL template. + +## WebGL 1 deprecation + +In version 2021.2, Unity marked support for the WebGL 1 Graphics API as deprecated. Currently, there are no changes in behavior and Unity still includes the WebGL 1 Graphics API if you enable the Auto Graphics API Player Setting. However, Unity will remove support for WebGL 1 In a future release. + +:::info +For more information, visit the Unity Manual on [WebGL Browser Compatibility](https://docs.unity3d.com/Manual/webgl-browsercompatibility.html). +::: diff --git a/documentation/versioned_docs/version-9.x.x/miscellaneous-instructions/building-unity-for-webgl.md b/documentation/versioned_docs/version-9.x.x/miscellaneous-instructions/building-unity-for-webgl.md new file mode 100644 index 00000000..2c53794f --- /dev/null +++ b/documentation/versioned_docs/version-9.x.x/miscellaneous-instructions/building-unity-for-webgl.md @@ -0,0 +1,32 @@ +# Building Unity For WebGL + +To get started with React Unity WebGL, you'll first need a Unity WebGL build. Nowadays with Unity 2020 and new, creating WebGL builds is easier then ever before. The following sections runs you though the basic steps of creating your very first WebGL build, and covers some frequently asked questions. + +#### Setting the Target Build Platform + +Start of by switching to the WebGL build platform, the target build platform can be changes from within the Build Settings window. This window can be found under the menu "File > Build Settings", or by pressing \[CMD+Shift+B\] on MacOS or \[CTRL+Shift+B\] on Windows respectively. When you've selected the WebGL build platform, proceed by clicking "Switch Platform". This process might take a while and will reimport your Assets. + +#### Generated Files, Templates and Presentation Settings + +When creating your WebGL build, Unity will by default generate a lot of files including HTML, CSS and a series of images. The reason these files are generated alongside your actual build is a selected Template from within your projects Player Settings. The same goes for the Height and Width settings. Unity allows for Templates to be added to your Asset directory and generate builds while bundeling them with these templates. + +Since your React project is something entirely different, we're not going to need all these files, and we'll be focussing on the actual build instead. These files include the four files required by the Unity Context object. You can either use the Minimal template to reduse the number of unused file to be generated, or just ignore these files and only copy the files you'll need. + +#### Builds Compression and Server Configuration + +By default Unity compresses the generated files using the Brotli compression algorithm based on your Unity Version. Support for compressed files has nothing to do with this module but requires you to set up your server correctly. If you don't want to configure your server, you can disable compression from within the Player Setting's Publish section. + +When chosing to use compressed builds, you might need to adjust your server configuration to match your specific build setup. In particular, there might be issues if you already have another server-side configuration to compress hosted files, which could interfere with this setup. To make the browser perform decompression natively while it downloads your application, append a Content-Encoding header to the server response. This header must correspond to the type of compression Unity uses at build time. For code samples, see Server Configuration Code Samples. + +#### Runtime Debugging and Development Builds + +When taking a look at the generated files, you'll find a lot of minified and mangled JavaScript. This might make debugging runtime issues quite challenging. Enable "Development Build" from the Player Settings window to prevent your build from becomming unreadable. This helps your debugging process, but these builds are not meant to be published since their buildsizes are hudge compaired to regular builds. + +If you're having more questions about creating WebGL builds, feel free to take a look and open a new question on the [Discussion Board](https://github.com/jeffreylanters/react-unity-webgl/discussions). + + diff --git "a/documentation/versioned_docs/version-9.x.x/miscellaneous-instructions/compressed-builds-and\342\200\223server-configuration.md" "b/documentation/versioned_docs/version-9.x.x/miscellaneous-instructions/compressed-builds-and\342\200\223server-configuration.md" new file mode 100644 index 00000000..9b1bed87 --- /dev/null +++ "b/documentation/versioned_docs/version-9.x.x/miscellaneous-instructions/compressed-builds-and\342\200\223server-configuration.md" @@ -0,0 +1,54 @@ +# Compressed Builds and Server Configuration + +To deploy a WebGL build, you must configure your server and make sure you’re using the correct response headers, so that the browser can receive the proper response and process the response correctly. There are two main settings in Unity that affect how you set up the server: + +- [Compression Format](#compression-format): Determines how Unity compresses files during the build step. +- [Decompression Fallback](#decompression-fallback): Determines how Unity processes downloaded files when the build runs in the browser. + +## Compression Format + +Choose the compression type from the WebGL Player Settings window. + +- GZip: This is the default option. Gzip files are bigger than Brotli files, but faster to build, and natively supported by all browsers over both HTTP and HTTPS. +- Brotli: Brotli compression offers the best compression ratios. Brotli compressed files are smaller than gzip, but take a longer time to compress, which increases your iteration times on release builds. Chrome and Firefox only natively support Brotli compression over HTTPS. +- None: Disables compression. Use this option if you want to implement your own compression in post-processing scripts. You should also use it if you plan to use static compression on the hosting server. + +## Web Server Configuration + +You might need to adjust your server configuration to match your specific build setup. In particular, there might be issues if you already have another server-side configuration to compress hosted files, which could interfere with this setup. To make the browser perform decompression natively while it downloads your application, append a Content-Encoding header to the server response. This header must correspond to the type of compression Unity uses at build time. For code samples, see Server Configuration Code Samples. + +## Decompression Fallback + +The decompression fallback option enables Unity to automatically embed a JavaScript decompressor into your build. This decompressor corresponds to your selected compression method, and decompresses your content if the browser fails to do so. + +### Enabling Decompression Fallback + +Enable decompression fallback from the Player Settings window. When you enable decompression fallback, Unity adds a .unityweb extension to the build files. You should consider using Decompression Fallback if you have less experience with server configuration, or if server configuration is unavailable to you. + +:::info +Using this option results in a larger loader size and a less efficient loading scheme for the build files. +::: + +### Disabling Decompression Fallback + +The Decompression Fallback option is disabled by default. Therefore, by default, build files have an extension that corresponds to the compression method you select. To enable browsers to natively decompress Unity build files while they’re downloading, you need to configure your web server to serve the compressed files with the appropriate HTTP headers. This is called native browser decompression. It has the advantage of being faster than the JavaScript decompression fallback, which can reduce your application’s startup time. + +## Content-Encoding Headers + +A Content-Encoding header tells the browser which type of compression Unity has used for the compressed files. This allows the browser to decompress the files natively. Set the Content-Encoding response header to the compression method selected in the Player Settings. + +### WebAssembly Streaming + +WebAssembly streaming allows the browser to compile the WebAssembly code while it is still downloading the code. This significantly improves loading times. For WebAssembly streaming compilation to work, the server needs to return WebAssembly files with an application/wasm MIME type. To use WebAssembly streaming, you need to serve WebAssembly files with the Content-Type: application/wasm response header. A Content-Type header tells the server which media type the content is. This value should be set to application/wasm for WebAssembly files. + +:::info +WebAssembly streaming does not work together with JavaScript decompression (when the Decompression Fallback option is enabled). In such cases, the downloaded WebAssembly file must first go through the JavaScript decompressor and therefore the browser cannot stream it during download. +::: + +### Additional Headers + +If your file contains JavaScript, you should add the application/javascript Content-Type header. Some servers might include this automatically, while others do not. + +:::info +For more information, visit the Unity Manual on [WebGL Deploying](https://docs.unity3d.com/Manual/webgl-deploying.html). +::: diff --git a/documentation/versioned_docs/version-9.x.x/quick-start/simple-example.md b/documentation/versioned_docs/version-9.x.x/quick-start/simple-example.md new file mode 100644 index 00000000..c8700c24 --- /dev/null +++ b/documentation/versioned_docs/version-9.x.x/quick-start/simple-example.md @@ -0,0 +1,21 @@ +# Simple Example + +In the following example, we'll be rendering a Unity Application in our React Application. A fixed height and width is provided to the canvas in order to keep the aspect ratio of the Unity Application. + +```jsx showLineNumbers title="App.jsx" +import React from "react"; +import { Unity, useUnityContext } from "react-unity-webgl"; + +function App() { + const { unityProvider } = useUnityContext({ + loaderUrl: "build/myunityapp.loader.js", + dataUrl: "build/myunityapp.data", + frameworkUrl: "build/myunityapp.framework.js", + codeUrl: "build/myunityapp.wasm", + }); + + return ( + + ); +} +``` diff --git a/documentation/versioned_docs/version-9.x.x/upgrading-from-version-8.md b/documentation/versioned_docs/version-9.x.x/upgrading-from-version-8.md new file mode 100644 index 00000000..10c9a76e --- /dev/null +++ b/documentation/versioned_docs/version-9.x.x/upgrading-from-version-8.md @@ -0,0 +1,7 @@ +# Upgrading from version 8 + +:::info +This page is still under construction. +::: + + diff --git a/documentation/versioned_sidebars/version-9.x.x-sidebars.json b/documentation/versioned_sidebars/version-9.x.x-sidebars.json new file mode 100644 index 00000000..829f71ea --- /dev/null +++ b/documentation/versioned_sidebars/version-9.x.x-sidebars.json @@ -0,0 +1,213 @@ +{ + "docs": [ + { + "type": "doc", + "id": "introduction" + }, + { + "type": "category", + "label": "Getting Started", + "items": [ + { + "type": "doc", + "id": "getting-started/installation" + }, + { + "type": "doc", + "id": "getting-started/hello-world" + } + ] + }, + { + "type": "category", + "label": "Main Concepts", + "items": [ + { + "type": "doc", + "id": "main-concepts/unity-config" + }, + { + "type": "doc", + "id": "main-concepts/data-conversion" + } + ] + }, + { + "type": "category", + "label": "Quick Start", + "items": [ + { + "type": "doc", + "id": "quick-start/simple-example" + } + ] + }, + { + "type": "category", + "label": "Advanced Examples", + "items": [ + { + "type": "doc", + "id": "advanced-examples/loading-overlay" + }, + { + "type": "doc", + "id": "advanced-examples/dynamic-device-pixel-ratio" + } + ] + }, + { + "type": "category", + "label": "Miscellaneous Instructions", + "items": [ + { + "type": "doc", + "id": "miscellaneous-instructions/building-unity-for-webgl" + }, + { + "type": "doc", + "id": "miscellaneous-instructions/compressed-builds-and–server-configuration", + "label": "Compression and Server Configuration" + }, + { + "type": "doc", + "id": "miscellaneous-instructions/browser-compatibility" + } + ] + }, + { + "type": "doc", + "id": "contributing" + } + ], + "api": [ + { + "type": "doc", + "id": "api/introduction" + }, + { + "type": "category", + "label": "Application State", + "items": [ + { + "type": "doc", + "id": "api/is-loaded" + }, + { + "type": "doc", + "id": "api/loading-progression" + }, + { + "type": "doc", + "id": "api/unload" + } + ] + }, + { + "type": "category", + "label": "Canvas Interaction", + "items": [ + { + "type": "doc", + "id": "api/request-fullscreen" + }, + { + "type": "doc", + "id": "api/request-pointer-lock" + }, + { + "type": "doc", + "id": "api/canvas-classname" + }, + { + "type": "doc", + "id": "api/canvas-styles" + }, + { + "type": "doc", + "id": "api/canvas-ref" + }, + { + "type": "doc", + "id": "api/canvas-device-pixel-ratio" + }, + { + "type": "doc", + "id": "api/tab-index" + }, + { + "type": "doc", + "id": "api/take-screenshot" + } + ] + }, + { + "type": "category", + "label": "Communication", + "items": [ + { + "type": "doc", + "id": "api/send-message", + "label": "From React to Unity" + }, + { + "type": "doc", + "id": "api/event-system", + "label": "From Unity to React" + } + ] + }, + { + "type": "category", + "label": "Miscellaneous", + "items": [ + { + "type": "doc", + "id": "api/streaming-assets" + }, + { + "type": "doc", + "id": "api/webgl-rendering-context" + }, + { + "type": "doc", + "id": "api/disabled-canvas-events" + }, + { + "type": "doc", + "id": "api/meta-data" + }, + { + "type": "doc", + "id": "api/unsafe-unity-instance", + "label": "Access the Unity Instance" + }, + { + "type": "doc", + "id": "api/unsafe-detach-unmount-immediate", + "label": "Detach and Unmount Immediate" + }, + { + "type": "doc", + "id": "api/cache-control", + "label": "Custom Cache Control" + }, + { + "type": "doc", + "id": "api/canvas-id", + "label": "Custom Canvas ID" + }, + { + "type": "doc", + "id": "api/auto-sync-persistent-data-path", + "label": "Auto Sync Persistent Data Path" + }, + { + "type": "doc", + "id": "api/web-worker", + "label": "Using a Web Worker" + } + ] + } + ] +} diff --git a/documentation/versions.json b/documentation/versions.json index ee1973e8..657112e3 100644 --- a/documentation/versions.json +++ b/documentation/versions.json @@ -1 +1 @@ -["8.x.x", "7.x.x", "6.x.x", "5.x.x"] +["9.x.x", "8.x.x", "7.x.x", "6.x.x", "5.x.x"] From 20bbf9041881e7767aee3b33b341b40c2c94dfbf Mon Sep 17 00:00:00 2001 From: Jeffrey Lanters Date: Wed, 16 Jul 2025 13:31:50 +0200 Subject: [PATCH 115/194] chore: update dependencies and version to 1.0.5 --- documentation/package-lock.json | 2091 ++++++++++++------------------- documentation/package.json | 12 +- 2 files changed, 834 insertions(+), 1269 deletions(-) diff --git a/documentation/package-lock.json b/documentation/package-lock.json index 2c4cbada..613cf4c1 100644 --- a/documentation/package-lock.json +++ b/documentation/package-lock.json @@ -1,17 +1,17 @@ { "name": "react-unity-webgl-documentation", - "version": "1.0.4", + "version": "1.0.5", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "react-unity-webgl-documentation", - "version": "1.0.4", + "version": "1.0.5", "dependencies": { - "@docusaurus/core": "^3.7.0", - "@docusaurus/plugin-google-analytics": "^3.7.0", - "@docusaurus/plugin-sitemap": "^3.7.0", - "@docusaurus/preset-classic": "^3.7.0", + "@docusaurus/core": "^3.8.1", + "@docusaurus/plugin-google-analytics": "^3.8.1", + "@docusaurus/plugin-sitemap": "^3.8.1", + "@docusaurus/preset-classic": "^3.8.1", "@mdx-js/react": "^3.1.0", "clsx": "^2.1.1", "prism-react-renderer": "^2.4.1", @@ -19,7 +19,7 @@ "react-dom": "^19.0.0" }, "devDependencies": { - "@docusaurus/module-type-aliases": "^3.7.0", + "@docusaurus/module-type-aliases": "^3.8.1", "@tsconfig/docusaurus": "^2.0.3", "typescript": "^5.7.3" }, @@ -69,92 +69,92 @@ } }, "node_modules/@algolia/client-abtesting": { - "version": "5.20.3", - "resolved": "https://registry.npmjs.org/@algolia/client-abtesting/-/client-abtesting-5.20.3.tgz", - "integrity": "sha512-wPOzHYSsW+H97JkBLmnlOdJSpbb9mIiuNPycUCV5DgzSkJFaI/OFxXfZXAh1gqxK+hf0miKue1C9bltjWljrNA==", + "version": "5.33.0", + "resolved": "https://registry.npmjs.org/@algolia/client-abtesting/-/client-abtesting-5.33.0.tgz", + "integrity": "sha512-Pyv+iHkkq7BJWFKzdrXm/JSbcTGvrGqJnIMwHYYlKDjuEBWhYt/z4WDLP9MbFZ9cTKb4qe8OvzEmS/0ERW3ibg==", "dependencies": { - "@algolia/client-common": "5.20.3", - "@algolia/requester-browser-xhr": "5.20.3", - "@algolia/requester-fetch": "5.20.3", - "@algolia/requester-node-http": "5.20.3" + "@algolia/client-common": "5.33.0", + "@algolia/requester-browser-xhr": "5.33.0", + "@algolia/requester-fetch": "5.33.0", + "@algolia/requester-node-http": "5.33.0" }, "engines": { "node": ">= 14.0.0" } }, "node_modules/@algolia/client-analytics": { - "version": "5.20.3", - "resolved": "https://registry.npmjs.org/@algolia/client-analytics/-/client-analytics-5.20.3.tgz", - "integrity": "sha512-XE3iduH9lA7iTQacDGofBQyIyIgaX8qbTRRdj1bOCmfzc9b98CoiMwhNwdTifmmMewmN0EhVF3hP8KjKWwX7Yw==", + "version": "5.33.0", + "resolved": "https://registry.npmjs.org/@algolia/client-analytics/-/client-analytics-5.33.0.tgz", + "integrity": "sha512-qkRc7ovjWQQJng6U1yM5esLPNDB0leGCaOh3FEfeWRyLB0xnjLsBEUkKanYq9GrewPvi17l78nDhkqB2SYzTCw==", "dependencies": { - "@algolia/client-common": "5.20.3", - "@algolia/requester-browser-xhr": "5.20.3", - "@algolia/requester-fetch": "5.20.3", - "@algolia/requester-node-http": "5.20.3" + "@algolia/client-common": "5.33.0", + "@algolia/requester-browser-xhr": "5.33.0", + "@algolia/requester-fetch": "5.33.0", + "@algolia/requester-node-http": "5.33.0" }, "engines": { "node": ">= 14.0.0" } }, "node_modules/@algolia/client-common": { - "version": "5.20.3", - "resolved": "https://registry.npmjs.org/@algolia/client-common/-/client-common-5.20.3.tgz", - "integrity": "sha512-IYRd/A/R3BXeaQVT2805lZEdWo54v39Lqa7ABOxIYnUvX2vvOMW1AyzCuT0U7Q+uPdD4UW48zksUKRixShcWxA==", + "version": "5.33.0", + "resolved": "https://registry.npmjs.org/@algolia/client-common/-/client-common-5.33.0.tgz", + "integrity": "sha512-Gq8Z4Fv0DkqDkf/bZl7ZwIF7PSCnRFwpyQoNDnUg+s4SwerXx6VwZJlIx/t5b9+l7vwWsjnKVivCfM4Ab5gw+g==", "engines": { "node": ">= 14.0.0" } }, "node_modules/@algolia/client-insights": { - "version": "5.20.3", - "resolved": "https://registry.npmjs.org/@algolia/client-insights/-/client-insights-5.20.3.tgz", - "integrity": "sha512-QGc/bmDUBgzB71rDL6kihI2e1Mx6G6PxYO5Ks84iL3tDcIel1aFuxtRF14P8saGgdIe1B6I6QkpkeIddZ6vWQw==", + "version": "5.33.0", + "resolved": "https://registry.npmjs.org/@algolia/client-insights/-/client-insights-5.33.0.tgz", + "integrity": "sha512-/tp1oWD3lpSXhAC4n8j0GMDbmN6pd+pATeO1GeURAFP5TVF+2Jz+NbQ1et0uCTzdazOfjEjSIv0fQSLo7bqSgA==", "dependencies": { - "@algolia/client-common": "5.20.3", - "@algolia/requester-browser-xhr": "5.20.3", - "@algolia/requester-fetch": "5.20.3", - "@algolia/requester-node-http": "5.20.3" + "@algolia/client-common": "5.33.0", + "@algolia/requester-browser-xhr": "5.33.0", + "@algolia/requester-fetch": "5.33.0", + "@algolia/requester-node-http": "5.33.0" }, "engines": { "node": ">= 14.0.0" } }, "node_modules/@algolia/client-personalization": { - "version": "5.20.3", - "resolved": "https://registry.npmjs.org/@algolia/client-personalization/-/client-personalization-5.20.3.tgz", - "integrity": "sha512-zuM31VNPDJ1LBIwKbYGz/7+CSm+M8EhlljDamTg8AnDilnCpKjBebWZR5Tftv/FdWSro4tnYGOIz1AURQgZ+tQ==", + "version": "5.33.0", + "resolved": "https://registry.npmjs.org/@algolia/client-personalization/-/client-personalization-5.33.0.tgz", + "integrity": "sha512-hZNSqe2BXkrBQ04t5NSlqsNl4u0QrFfhXHbjO5iZ14TWt5jyOdtFMBxF3Qc0o0sqTVYnFIp0xtUbEi+/HkGeyQ==", "dependencies": { - "@algolia/client-common": "5.20.3", - "@algolia/requester-browser-xhr": "5.20.3", - "@algolia/requester-fetch": "5.20.3", - "@algolia/requester-node-http": "5.20.3" + "@algolia/client-common": "5.33.0", + "@algolia/requester-browser-xhr": "5.33.0", + "@algolia/requester-fetch": "5.33.0", + "@algolia/requester-node-http": "5.33.0" }, "engines": { "node": ">= 14.0.0" } }, "node_modules/@algolia/client-query-suggestions": { - "version": "5.20.3", - "resolved": "https://registry.npmjs.org/@algolia/client-query-suggestions/-/client-query-suggestions-5.20.3.tgz", - "integrity": "sha512-Nn872PuOI8qzi1bxMMhJ0t2AzVBqN01jbymBQOkypvZHrrjZPso3iTpuuLLo9gi3yc/08vaaWTAwJfPhxPwJUw==", + "version": "5.33.0", + "resolved": "https://registry.npmjs.org/@algolia/client-query-suggestions/-/client-query-suggestions-5.33.0.tgz", + "integrity": "sha512-kpu2hCIR+848T0lcf3W1GCMe+HQp/LcHceIglA6Dyw6i+y9wH3w8kmXqIV2Svv6JQ9ojEqIL8Knk7NEvD3xIBg==", "dependencies": { - "@algolia/client-common": "5.20.3", - "@algolia/requester-browser-xhr": "5.20.3", - "@algolia/requester-fetch": "5.20.3", - "@algolia/requester-node-http": "5.20.3" + "@algolia/client-common": "5.33.0", + "@algolia/requester-browser-xhr": "5.33.0", + "@algolia/requester-fetch": "5.33.0", + "@algolia/requester-node-http": "5.33.0" }, "engines": { "node": ">= 14.0.0" } }, "node_modules/@algolia/client-search": { - "version": "5.20.3", - "resolved": "https://registry.npmjs.org/@algolia/client-search/-/client-search-5.20.3.tgz", - "integrity": "sha512-9+Fm1ahV8/2goSIPIqZnVitV5yHW5E5xTdKy33xnqGd45A9yVv5tTkudWzEXsbfBB47j9Xb3uYPZjAvV5RHbKA==", + "version": "5.33.0", + "resolved": "https://registry.npmjs.org/@algolia/client-search/-/client-search-5.33.0.tgz", + "integrity": "sha512-Z5SAqPLxF8KyE9YPO4tAdHrXyb87DUJ0lXhFrcrG+dl/AQT9nqycQhtqDqdcQnfZrj02PImSWZQpxQj34nGZKw==", "dependencies": { - "@algolia/client-common": "5.20.3", - "@algolia/requester-browser-xhr": "5.20.3", - "@algolia/requester-fetch": "5.20.3", - "@algolia/requester-node-http": "5.20.3" + "@algolia/client-common": "5.33.0", + "@algolia/requester-browser-xhr": "5.33.0", + "@algolia/requester-fetch": "5.33.0", + "@algolia/requester-node-http": "5.33.0" }, "engines": { "node": ">= 14.0.0" @@ -166,75 +166,75 @@ "integrity": "sha512-FQzvOCgoFXAbf5Y6mYozw2aj5KCJoA3m4heImceldzPSMbdyS4atVjJzXKMsfX3wnZTFYwkkt8/z8UesLHlSBQ==" }, "node_modules/@algolia/ingestion": { - "version": "1.20.3", - "resolved": "https://registry.npmjs.org/@algolia/ingestion/-/ingestion-1.20.3.tgz", - "integrity": "sha512-5GHNTiZ3saLjTNyr6WkP5hzDg2eFFAYWomvPcm9eHWskjzXt8R0IOiW9kkTS6I6hXBwN5H9Zna5mZDSqqJdg+g==", + "version": "1.33.0", + "resolved": "https://registry.npmjs.org/@algolia/ingestion/-/ingestion-1.33.0.tgz", + "integrity": "sha512-KNJI60N+twnDLiIY+oGO2Q+syS+yBNOmNdhsB5vCzzrhi3CYs+bufnJ67/BUUfnt+T5+3VlnkvUgDkGBmmZXmA==", "dependencies": { - "@algolia/client-common": "5.20.3", - "@algolia/requester-browser-xhr": "5.20.3", - "@algolia/requester-fetch": "5.20.3", - "@algolia/requester-node-http": "5.20.3" + "@algolia/client-common": "5.33.0", + "@algolia/requester-browser-xhr": "5.33.0", + "@algolia/requester-fetch": "5.33.0", + "@algolia/requester-node-http": "5.33.0" }, "engines": { "node": ">= 14.0.0" } }, "node_modules/@algolia/monitoring": { - "version": "1.20.3", - "resolved": "https://registry.npmjs.org/@algolia/monitoring/-/monitoring-1.20.3.tgz", - "integrity": "sha512-KUWQbTPoRjP37ivXSQ1+lWMfaifCCMzTnEcEnXwAmherS5Tp7us6BAqQDMGOD4E7xyaS2I8pto6WlOzxH+CxmA==", + "version": "1.33.0", + "resolved": "https://registry.npmjs.org/@algolia/monitoring/-/monitoring-1.33.0.tgz", + "integrity": "sha512-47R0kMDTSj8Q7rCUgIRv5Xc518tCBBS0KIZ5oRKg+hspQaJmEO+fxwGLrIIwp5JiaK6y+5sbS7bhtaajelJhpg==", "dependencies": { - "@algolia/client-common": "5.20.3", - "@algolia/requester-browser-xhr": "5.20.3", - "@algolia/requester-fetch": "5.20.3", - "@algolia/requester-node-http": "5.20.3" + "@algolia/client-common": "5.33.0", + "@algolia/requester-browser-xhr": "5.33.0", + "@algolia/requester-fetch": "5.33.0", + "@algolia/requester-node-http": "5.33.0" }, "engines": { "node": ">= 14.0.0" } }, "node_modules/@algolia/recommend": { - "version": "5.20.3", - "resolved": "https://registry.npmjs.org/@algolia/recommend/-/recommend-5.20.3.tgz", - "integrity": "sha512-oo/gG77xTTTclkrdFem0Kmx5+iSRFiwuRRdxZETDjwzCI7svutdbwBgV/Vy4D4QpYaX4nhY/P43k84uEowCE4Q==", + "version": "5.33.0", + "resolved": "https://registry.npmjs.org/@algolia/recommend/-/recommend-5.33.0.tgz", + "integrity": "sha512-HpeLoVQuv5kW9xL0RSq1exa8ueNwyx+9B02dzFonlQzKTaSedM0jiWo6m3nWpi1hChAKqjzkL40FkxrgyrWTSg==", "dependencies": { - "@algolia/client-common": "5.20.3", - "@algolia/requester-browser-xhr": "5.20.3", - "@algolia/requester-fetch": "5.20.3", - "@algolia/requester-node-http": "5.20.3" + "@algolia/client-common": "5.33.0", + "@algolia/requester-browser-xhr": "5.33.0", + "@algolia/requester-fetch": "5.33.0", + "@algolia/requester-node-http": "5.33.0" }, "engines": { "node": ">= 14.0.0" } }, "node_modules/@algolia/requester-browser-xhr": { - "version": "5.20.3", - "resolved": "https://registry.npmjs.org/@algolia/requester-browser-xhr/-/requester-browser-xhr-5.20.3.tgz", - "integrity": "sha512-BkkW7otbiI/Er1AiEPZs1h7lxbtSO9p09jFhv3/iT8/0Yz0CY79VJ9iq+Wv1+dq/l0OxnMpBy8mozrieGA3mXQ==", + "version": "5.33.0", + "resolved": "https://registry.npmjs.org/@algolia/requester-browser-xhr/-/requester-browser-xhr-5.33.0.tgz", + "integrity": "sha512-uOqDkvY7s9c9rkaZ4+n69LkTmZ5ax3el+8u6ipvODfj1P3HzrGvMUVFy/nGSXxw+XITKcIRphPQcyqn15b02dA==", "dependencies": { - "@algolia/client-common": "5.20.3" + "@algolia/client-common": "5.33.0" }, "engines": { "node": ">= 14.0.0" } }, "node_modules/@algolia/requester-fetch": { - "version": "5.20.3", - "resolved": "https://registry.npmjs.org/@algolia/requester-fetch/-/requester-fetch-5.20.3.tgz", - "integrity": "sha512-eAVlXz7UNzTsA1EDr+p0nlIH7WFxo7k3NMxYe8p38DH8YVWLgm2MgOVFUMNg9HCi6ZNOi/A2w/id2ZZ4sKgUOw==", + "version": "5.33.0", + "resolved": "https://registry.npmjs.org/@algolia/requester-fetch/-/requester-fetch-5.33.0.tgz", + "integrity": "sha512-NzTEGjwjPhUXPsrjj9nXM43+jtBVeL6UgGNBTQKsxjpqJ3EEAQ2Kq5g7DRK6mVDTQiTBWvBLKChJpn4qxwtLsg==", "dependencies": { - "@algolia/client-common": "5.20.3" + "@algolia/client-common": "5.33.0" }, "engines": { "node": ">= 14.0.0" } }, "node_modules/@algolia/requester-node-http": { - "version": "5.20.3", - "resolved": "https://registry.npmjs.org/@algolia/requester-node-http/-/requester-node-http-5.20.3.tgz", - "integrity": "sha512-FqR3pQPfHfQyX1wgcdK6iyqu86yP76MZd4Pzj1y/YLMj9rRmRCY0E0AffKr//nrOFEwv6uY8BQY4fd9/6b0ZCg==", + "version": "5.33.0", + "resolved": "https://registry.npmjs.org/@algolia/requester-node-http/-/requester-node-http-5.33.0.tgz", + "integrity": "sha512-FhEE19ScAYuXL3VLj2I3KhL7683gZwZoa+BQZUEnA05vSbVBhCAqUBQgiVu7j2RF3VceqLX3+GEeY0bHs4y7eA==", "dependencies": { - "@algolia/client-common": "5.20.3" + "@algolia/client-common": "5.33.0" }, "engines": { "node": ">= 14.0.0" @@ -253,22 +253,22 @@ } }, "node_modules/@babel/code-frame": { - "version": "7.26.2", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.26.2.tgz", - "integrity": "sha512-RJlIHRueQgwWitWgF8OdFYGZX328Ax5BCemNGlqHfplnRT9ESi8JkFlvaVYbS+UubVY6dpv87Fs2u5M29iNFVQ==", + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.27.1.tgz", + "integrity": "sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg==", "dependencies": { - "@babel/helper-validator-identifier": "^7.25.9", + "@babel/helper-validator-identifier": "^7.27.1", "js-tokens": "^4.0.0", - "picocolors": "^1.0.0" + "picocolors": "^1.1.1" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/compat-data": { - "version": "7.26.8", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.26.8.tgz", - "integrity": "sha512-oH5UPLMWR3L2wEFLnFJ1TZXqHufiTKAiLfqw5zkhS4dKXLJ10yVztfil/twG8EDTA4F/tvVNw9nOl4ZMslB8rQ==", + "version": "7.28.0", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.28.0.tgz", + "integrity": "sha512-60X7qkglvrap8mn1lh2ebxXdZYtUcpd7gsmy9kLaBJ4i/WdY8PqTSdxyA8qraikqKQK5C1KRBKXqznrVapyNaw==", "engines": { "node": ">=6.9.0" } @@ -311,14 +311,14 @@ } }, "node_modules/@babel/generator": { - "version": "7.26.9", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.26.9.tgz", - "integrity": "sha512-kEWdzjOAUMW4hAyrzJ0ZaTOu9OmpyDIQicIh0zg0EEcEkYXZb2TjtBhnHi2ViX7PKwZqF4xwqfAm299/QMP3lg==", - "dependencies": { - "@babel/parser": "^7.26.9", - "@babel/types": "^7.26.9", - "@jridgewell/gen-mapping": "^0.3.5", - "@jridgewell/trace-mapping": "^0.3.25", + "version": "7.28.0", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.28.0.tgz", + "integrity": "sha512-lJjzvrbEeWrhB4P3QBsH7tey117PjLZnDbLiQEKjQ/fNJTjuq4HSqgFA+UNSwZT8D7dxxbnuSBMsa1lrWzKlQg==", + "dependencies": { + "@babel/parser": "^7.28.0", + "@babel/types": "^7.28.0", + "@jridgewell/gen-mapping": "^0.3.12", + "@jridgewell/trace-mapping": "^0.3.28", "jsesc": "^3.0.2" }, "engines": { @@ -337,12 +337,12 @@ } }, "node_modules/@babel/helper-compilation-targets": { - "version": "7.26.5", - "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.26.5.tgz", - "integrity": "sha512-IXuyn5EkouFJscIDuFF5EsiSolseme1s0CZB+QxVugqJLYmKdxI1VfIBOst0SUu4rnk2Z7kqTwmoO1lp3HIfnA==", + "version": "7.27.2", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.27.2.tgz", + "integrity": "sha512-2+1thGUUWWjLTYTHZWK1n8Yga0ijBz1XAhUXcKy81rd5g6yh7hGqMp45v7cadSbEHc9G3OTv45SyneRN3ps4DQ==", "dependencies": { - "@babel/compat-data": "^7.26.5", - "@babel/helper-validator-option": "^7.25.9", + "@babel/compat-data": "^7.27.2", + "@babel/helper-validator-option": "^7.27.1", "browserslist": "^4.24.0", "lru-cache": "^5.1.1", "semver": "^6.3.1" @@ -412,20 +412,28 @@ } }, "node_modules/@babel/helper-define-polyfill-provider": { - "version": "0.6.3", - "resolved": "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.6.3.tgz", - "integrity": "sha512-HK7Bi+Hj6H+VTHA3ZvBis7V/6hu9QuTrnMXNybfUf2iiuU/N97I8VjB+KbhFF8Rld/Lx5MzoCwPCpPjfK+n8Cg==", + "version": "0.6.5", + "resolved": "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.6.5.tgz", + "integrity": "sha512-uJnGFcPsWQK8fvjgGP5LZUZZsYGIoPeRjSF5PGwrelYgq7Q15/Ft9NGFp1zglwgIv//W0uG4BevRuSJRyylZPg==", "dependencies": { - "@babel/helper-compilation-targets": "^7.22.6", - "@babel/helper-plugin-utils": "^7.22.5", - "debug": "^4.1.1", + "@babel/helper-compilation-targets": "^7.27.2", + "@babel/helper-plugin-utils": "^7.27.1", + "debug": "^4.4.1", "lodash.debounce": "^4.0.8", - "resolve": "^1.14.2" + "resolve": "^1.22.10" }, "peerDependencies": { "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" } }, + "node_modules/@babel/helper-globals": { + "version": "7.28.0", + "resolved": "https://registry.npmjs.org/@babel/helper-globals/-/helper-globals-7.28.0.tgz", + "integrity": "sha512-+W6cISkXFa1jXsDEdYA8HeevQT/FULhxzR99pxphltZcVaugps53THCeiWA8SguxxpSp3gKPiuYfSWopkLQ4hw==", + "engines": { + "node": ">=6.9.0" + } + }, "node_modules/@babel/helper-member-expression-to-functions": { "version": "7.25.9", "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.25.9.tgz", @@ -439,12 +447,12 @@ } }, "node_modules/@babel/helper-module-imports": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.25.9.tgz", - "integrity": "sha512-tnUA4RsrmflIM6W6RFTLFSXITtl0wKjgpnLgXyowocVPrbYrLUXSBXDgTs8BlbmIzIdlBySRQjINYs2BAkiLtw==", + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.27.1.tgz", + "integrity": "sha512-0gSFWUPNXNopqtIPQvlD5WgXYI5GY2kP2cCvoT8kczjbfcfuIljTbcWrulD1CIPIX2gt1wghbDy08yE1p+/r3w==", "dependencies": { - "@babel/traverse": "^7.25.9", - "@babel/types": "^7.25.9" + "@babel/traverse": "^7.27.1", + "@babel/types": "^7.27.1" }, "engines": { "node": ">=6.9.0" @@ -478,9 +486,9 @@ } }, "node_modules/@babel/helper-plugin-utils": { - "version": "7.26.5", - "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.26.5.tgz", - "integrity": "sha512-RS+jZcRdZdRFzMyr+wcsaqOmld1/EqTghfaBGQQd/WnRdzdlvSZ//kF7U8VQTxf1ynZ4cjUcYgjVGx13ewNPMg==", + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.27.1.tgz", + "integrity": "sha512-1gn1Up5YXka3YYAHGKpbideQ5Yjf1tDa9qYcgysz+cNCXukyLl6DjPXhD3VRwSb8c0J9tA4b2+rHEZtc6R0tlw==", "engines": { "node": ">=6.9.0" } @@ -530,25 +538,25 @@ } }, "node_modules/@babel/helper-string-parser": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.25.9.tgz", - "integrity": "sha512-4A/SCr/2KLd5jrtOMFzaKjVtAei3+2r/NChoBNoZ3EyP/+GlhoaEGoWOZUmFmoITP7zOJyHIMm+DYRd8o3PvHA==", + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.27.1.tgz", + "integrity": "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==", "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-validator-identifier": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.25.9.tgz", - "integrity": "sha512-Ed61U6XJc3CVRfkERJWDz4dJwKe7iLmmJsbOGu9wSloNSFttHV0I8g6UAgb7qnK5ly5bGLPd4oXZlxCdANBOWQ==", + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.27.1.tgz", + "integrity": "sha512-D2hP9eA+Sqx1kBZgzxZh0y1trbuU+JoDkiEwqhQ36nodYqJwyEIhPSdMNd7lOm/4io72luTPWH20Yda0xOuUow==", "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-validator-option": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.25.9.tgz", - "integrity": "sha512-e/zv1co8pp55dNdEcCynfj9X7nyUKUXoUEwfXqaZt0omVOmDe9oOTdKStH4GmAw6zxMFs50ZayuMfHDKlO7Tfw==", + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.27.1.tgz", + "integrity": "sha512-YvjJow9FxbhFFKDSuFnVCe2WxXk1zWc22fFePVNEaWJEu8IrZVlda6N0uHwzZrUM1il7NC9Mlp4MaJYbYd9JSg==", "engines": { "node": ">=6.9.0" } @@ -579,11 +587,11 @@ } }, "node_modules/@babel/parser": { - "version": "7.26.9", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.26.9.tgz", - "integrity": "sha512-81NWa1njQblgZbQHxWHpxxCzNsa3ZwvFqpUg7P+NNUU6f3UU2jBEg4OlF/J6rl8+PQGh1q6/zWScd001YwcA5A==", + "version": "7.28.0", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.28.0.tgz", + "integrity": "sha512-jVZGvOxOuNSsuQuLRTh13nU0AogFlw32w/MT+LV6D3sP5WdbW61E77RnkbaO2dUvmPAYrBDJXGn5gGS6tH4j8g==", "dependencies": { - "@babel/types": "^7.26.9" + "@babel/types": "^7.28.0" }, "bin": { "parser": "bin/babel-parser.js" @@ -1323,11 +1331,11 @@ } }, "node_modules/@babel/plugin-transform-react-constant-elements": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-constant-elements/-/plugin-transform-react-constant-elements-7.25.9.tgz", - "integrity": "sha512-Ncw2JFsJVuvfRsa2lSHiC55kETQVLSnsYGQ1JDDwkUeWGTL/8Tom8aLTnlqgoeuopWrbbGndrc9AlLYrIosrow==", + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-constant-elements/-/plugin-transform-react-constant-elements-7.27.1.tgz", + "integrity": "sha512-edoidOjl/ZxvYo4lSBOQGDSyToYVkTAwyVoa2tkuYTSmjrB1+uAedoL5iROVLXkxH+vRgA7uP4tMg2pUJpZ3Ug==", "dependencies": { - "@babel/helper-plugin-utils": "^7.25.9" + "@babel/helper-plugin-utils": "^7.27.1" }, "engines": { "node": ">=6.9.0" @@ -1442,15 +1450,15 @@ } }, "node_modules/@babel/plugin-transform-runtime": { - "version": "7.26.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.26.9.tgz", - "integrity": "sha512-Jf+8y9wXQbbxvVYTM8gO5oEF2POdNji0NMltEkG7FtmzD9PVz7/lxpqSdTvwsjTMU5HIHuDVNf2SOxLkWi+wPQ==", - "dependencies": { - "@babel/helper-module-imports": "^7.25.9", - "@babel/helper-plugin-utils": "^7.26.5", - "babel-plugin-polyfill-corejs2": "^0.4.10", - "babel-plugin-polyfill-corejs3": "^0.10.6", - "babel-plugin-polyfill-regenerator": "^0.6.1", + "version": "7.28.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.28.0.tgz", + "integrity": "sha512-dGopk9nZrtCs2+nfIem25UuHyt5moSJamArzIoh9/vezUQPmYDOzjaHDCkAzuGJibCIkPup8rMT2+wYB6S73cA==", + "dependencies": { + "@babel/helper-module-imports": "^7.27.1", + "@babel/helper-plugin-utils": "^7.27.1", + "babel-plugin-polyfill-corejs2": "^0.4.14", + "babel-plugin-polyfill-corejs3": "^0.13.0", + "babel-plugin-polyfill-regenerator": "^0.6.5", "semver": "^6.3.1" }, "engines": { @@ -1780,54 +1788,53 @@ } }, "node_modules/@babel/runtime-corejs3": { - "version": "7.26.9", - "resolved": "https://registry.npmjs.org/@babel/runtime-corejs3/-/runtime-corejs3-7.26.9.tgz", - "integrity": "sha512-5EVjbTegqN7RSJle6hMWYxO4voo4rI+9krITk+DWR+diJgGrjZjrIBnJhjrHYYQsFgI7j1w1QnrvV7YSKBfYGg==", + "version": "7.28.0", + "resolved": "https://registry.npmjs.org/@babel/runtime-corejs3/-/runtime-corejs3-7.28.0.tgz", + "integrity": "sha512-nlIXnSqLcBij8K8TtkxbBJgfzfvi75V1pAKSM7dUXejGw12vJAqez74jZrHTsJ3Z+Aczc5Q/6JgNjKRMsVU44g==", "dependencies": { - "core-js-pure": "^3.30.2", - "regenerator-runtime": "^0.14.0" + "core-js-pure": "^3.43.0" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/template": { - "version": "7.26.9", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.26.9.tgz", - "integrity": "sha512-qyRplbeIpNZhmzOysF/wFMuP9sctmh2cFzRAZOn1YapxBsE1i9bJIY586R/WBLfLcmcBlM8ROBiQURnnNy+zfA==", + "version": "7.27.2", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.27.2.tgz", + "integrity": "sha512-LPDZ85aEJyYSd18/DkjNh4/y1ntkE5KwUHWTiqgRxruuZL2F1yuHligVHLvcHY2vMHXttKFpJn6LwfI7cw7ODw==", "dependencies": { - "@babel/code-frame": "^7.26.2", - "@babel/parser": "^7.26.9", - "@babel/types": "^7.26.9" + "@babel/code-frame": "^7.27.1", + "@babel/parser": "^7.27.2", + "@babel/types": "^7.27.1" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/traverse": { - "version": "7.26.9", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.26.9.tgz", - "integrity": "sha512-ZYW7L+pL8ahU5fXmNbPF+iZFHCv5scFak7MZ9bwaRPLUhHh7QQEMjZUg0HevihoqCM5iSYHN61EyCoZvqC+bxg==", + "version": "7.28.0", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.28.0.tgz", + "integrity": "sha512-mGe7UK5wWyh0bKRfupsUchrQGqvDbZDbKJw+kcRGSmdHVYrv+ltd0pnpDTVpiTqnaBru9iEvA8pz8W46v0Amwg==", "dependencies": { - "@babel/code-frame": "^7.26.2", - "@babel/generator": "^7.26.9", - "@babel/parser": "^7.26.9", - "@babel/template": "^7.26.9", - "@babel/types": "^7.26.9", - "debug": "^4.3.1", - "globals": "^11.1.0" + "@babel/code-frame": "^7.27.1", + "@babel/generator": "^7.28.0", + "@babel/helper-globals": "^7.28.0", + "@babel/parser": "^7.28.0", + "@babel/template": "^7.27.2", + "@babel/types": "^7.28.0", + "debug": "^4.3.1" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/types": { - "version": "7.26.9", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.26.9.tgz", - "integrity": "sha512-Y3IR1cRnOxOCDvMmNiym7XpXQ93iGDDPHx+Zj+NM+rg0fBaShfQLkg+hKPaZCEvg5N/LeCo4+Rj/i3FuJsIQaw==", + "version": "7.28.1", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.28.1.tgz", + "integrity": "sha512-x0LvFTekgSX+83TI28Y9wYPUfzrnl2aT5+5QLnO6v7mSJYtEEevuDRN0F0uSHRk1G1IWZC43o00Y0xDDrpBGPQ==", "dependencies": { - "@babel/helper-string-parser": "^7.25.9", - "@babel/helper-validator-identifier": "^7.25.9" + "@babel/helper-string-parser": "^7.27.1", + "@babel/helper-validator-identifier": "^7.27.1" }, "engines": { "node": ">=6.9.0" @@ -1843,9 +1850,9 @@ } }, "node_modules/@csstools/cascade-layer-name-parser": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/@csstools/cascade-layer-name-parser/-/cascade-layer-name-parser-2.0.4.tgz", - "integrity": "sha512-7DFHlPuIxviKYZrOiwVU/PiHLm3lLUR23OMuEEtfEOQTOp9hzQ2JjdY6X5H18RVuUPJqSCI+qNnD5iOLMVE0bA==", + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@csstools/cascade-layer-name-parser/-/cascade-layer-name-parser-2.0.5.tgz", + "integrity": "sha512-p1ko5eHgV+MgXFVa4STPKpvPxr6ReS8oS2jzTukjR74i5zJNyWO1ZM1m8YKBXnzDKWfBN1ztLYlHxbVemDD88A==", "funding": [ { "type": "github", @@ -1860,14 +1867,14 @@ "node": ">=18" }, "peerDependencies": { - "@csstools/css-parser-algorithms": "^3.0.4", - "@csstools/css-tokenizer": "^3.0.3" + "@csstools/css-parser-algorithms": "^3.0.5", + "@csstools/css-tokenizer": "^3.0.4" } }, "node_modules/@csstools/color-helpers": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/@csstools/color-helpers/-/color-helpers-5.0.1.tgz", - "integrity": "sha512-MKtmkA0BX87PKaO1NFRTFH+UnkgnmySQOvNxJubsadusqPEC2aJ9MOQiMceZJJ6oitUl/i0L6u0M1IrmAOmgBA==", + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/@csstools/color-helpers/-/color-helpers-5.0.2.tgz", + "integrity": "sha512-JqWH1vsgdGcw2RR6VliXXdA0/59LttzlU8UlRT/iUUsEeWfYq8I+K0yhihEUTTHLRm1EXvpsCx3083EU15ecsA==", "funding": [ { "type": "github", @@ -1883,9 +1890,9 @@ } }, "node_modules/@csstools/css-calc": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/@csstools/css-calc/-/css-calc-2.1.1.tgz", - "integrity": "sha512-rL7kaUnTkL9K+Cvo2pnCieqNpTKgQzy5f+N+5Iuko9HAoasP+xgprVh7KN/MaJVvVL1l0EzQq2MoqBHKSrDrag==", + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/@csstools/css-calc/-/css-calc-2.1.4.tgz", + "integrity": "sha512-3N8oaj+0juUw/1H3YwmDDJXCgTB1gKU6Hc/bB502u9zR0q2vd786XJH9QfrKIEgFlZmhZiq6epXl4rHqhzsIgQ==", "funding": [ { "type": "github", @@ -1900,14 +1907,14 @@ "node": ">=18" }, "peerDependencies": { - "@csstools/css-parser-algorithms": "^3.0.4", - "@csstools/css-tokenizer": "^3.0.3" + "@csstools/css-parser-algorithms": "^3.0.5", + "@csstools/css-tokenizer": "^3.0.4" } }, "node_modules/@csstools/css-color-parser": { - "version": "3.0.7", - "resolved": "https://registry.npmjs.org/@csstools/css-color-parser/-/css-color-parser-3.0.7.tgz", - "integrity": "sha512-nkMp2mTICw32uE5NN+EsJ4f5N+IGFeCFu4bGpiKgb2Pq/7J/MpyLBeQ5ry4KKtRFZaYs6sTmcMYrSRIyj5DFKA==", + "version": "3.0.10", + "resolved": "https://registry.npmjs.org/@csstools/css-color-parser/-/css-color-parser-3.0.10.tgz", + "integrity": "sha512-TiJ5Ajr6WRd1r8HSiwJvZBiJOqtH86aHpUjq5aEKWHiII2Qfjqd/HCWKPOW8EP4vcspXbHnXrwIDlu5savQipg==", "funding": [ { "type": "github", @@ -1919,21 +1926,21 @@ } ], "dependencies": { - "@csstools/color-helpers": "^5.0.1", - "@csstools/css-calc": "^2.1.1" + "@csstools/color-helpers": "^5.0.2", + "@csstools/css-calc": "^2.1.4" }, "engines": { "node": ">=18" }, "peerDependencies": { - "@csstools/css-parser-algorithms": "^3.0.4", - "@csstools/css-tokenizer": "^3.0.3" + "@csstools/css-parser-algorithms": "^3.0.5", + "@csstools/css-tokenizer": "^3.0.4" } }, "node_modules/@csstools/css-parser-algorithms": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/@csstools/css-parser-algorithms/-/css-parser-algorithms-3.0.4.tgz", - "integrity": "sha512-Up7rBoV77rv29d3uKHUIVubz1BTcgyUK72IvCQAbfbMv584xHcGKCKbWh7i8hPrRJ7qU4Y8IO3IY9m+iTB7P3A==", + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/@csstools/css-parser-algorithms/-/css-parser-algorithms-3.0.5.tgz", + "integrity": "sha512-DaDeUkXZKjdGhgYaHNJTV9pV7Y9B3b644jCLs9Upc3VeNGg6LWARAT6O+Q+/COo+2gg/bM5rhpMAtf70WqfBdQ==", "funding": [ { "type": "github", @@ -1948,13 +1955,13 @@ "node": ">=18" }, "peerDependencies": { - "@csstools/css-tokenizer": "^3.0.3" + "@csstools/css-tokenizer": "^3.0.4" } }, "node_modules/@csstools/css-tokenizer": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/@csstools/css-tokenizer/-/css-tokenizer-3.0.3.tgz", - "integrity": "sha512-UJnjoFsmxfKUdNYdWgOB0mWUypuLvAfQPH1+pyvRJs6euowbFkFC6P13w1l8mJyi3vxYMxc9kld5jZEGRQs6bw==", + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@csstools/css-tokenizer/-/css-tokenizer-3.0.4.tgz", + "integrity": "sha512-Vd/9EVDiu6PPJt9yAh6roZP6El1xHrdvIVGjyBsHR0RYwNHgL7FJPyIIW4fANJNG6FtyZfvlRPpFI4ZM/lubvw==", "funding": [ { "type": "github", @@ -1970,9 +1977,9 @@ } }, "node_modules/@csstools/media-query-list-parser": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/@csstools/media-query-list-parser/-/media-query-list-parser-4.0.2.tgz", - "integrity": "sha512-EUos465uvVvMJehckATTlNqGj4UJWkTmdWuDMjqvSUkjGpmOyFZBVwb4knxCm/k2GMTXY+c/5RkdndzFYWeX5A==", + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/@csstools/media-query-list-parser/-/media-query-list-parser-4.0.3.tgz", + "integrity": "sha512-HAYH7d3TLRHDOUQK4mZKf9k9Ph/m8Akstg66ywKR4SFAigjs3yBiUeZtFxywiTm5moZMAp/5W/ZuFnNXXYLuuQ==", "funding": [ { "type": "github", @@ -1987,14 +1994,14 @@ "node": ">=18" }, "peerDependencies": { - "@csstools/css-parser-algorithms": "^3.0.4", - "@csstools/css-tokenizer": "^3.0.3" + "@csstools/css-parser-algorithms": "^3.0.5", + "@csstools/css-tokenizer": "^3.0.4" } }, "node_modules/@csstools/postcss-cascade-layers": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/@csstools/postcss-cascade-layers/-/postcss-cascade-layers-5.0.1.tgz", - "integrity": "sha512-XOfhI7GShVcKiKwmPAnWSqd2tBR0uxt+runAxttbSp/LY2U16yAVPmAf7e9q4JJ0d+xMNmpwNDLBXnmRCl3HMQ==", + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/@csstools/postcss-cascade-layers/-/postcss-cascade-layers-5.0.2.tgz", + "integrity": "sha512-nWBE08nhO8uWl6kSAeCx4im7QfVko3zLrtgWZY4/bP87zrSPpSyN/3W3TDqz1jJuH+kbKOHXg5rJnK+ZVYcFFg==", "funding": [ { "type": "github", @@ -2050,9 +2057,9 @@ } }, "node_modules/@csstools/postcss-color-function": { - "version": "4.0.7", - "resolved": "https://registry.npmjs.org/@csstools/postcss-color-function/-/postcss-color-function-4.0.7.tgz", - "integrity": "sha512-aDHYmhNIHR6iLw4ElWhf+tRqqaXwKnMl0YsQ/X105Zc4dQwe6yJpMrTN6BwOoESrkDjOYMOfORviSSLeDTJkdQ==", + "version": "4.0.10", + "resolved": "https://registry.npmjs.org/@csstools/postcss-color-function/-/postcss-color-function-4.0.10.tgz", + "integrity": "sha512-4dY0NBu7NVIpzxZRgh/Q/0GPSz/jLSw0i/u3LTUor0BkQcz/fNhN10mSWBDsL0p9nDb0Ky1PD6/dcGbhACuFTQ==", "funding": [ { "type": "github", @@ -2064,10 +2071,10 @@ } ], "dependencies": { - "@csstools/css-color-parser": "^3.0.7", - "@csstools/css-parser-algorithms": "^3.0.4", - "@csstools/css-tokenizer": "^3.0.3", - "@csstools/postcss-progressive-custom-properties": "^4.0.0", + "@csstools/css-color-parser": "^3.0.10", + "@csstools/css-parser-algorithms": "^3.0.5", + "@csstools/css-tokenizer": "^3.0.4", + "@csstools/postcss-progressive-custom-properties": "^4.1.0", "@csstools/utilities": "^2.0.0" }, "engines": { @@ -2078,9 +2085,37 @@ } }, "node_modules/@csstools/postcss-color-mix-function": { - "version": "3.0.7", - "resolved": "https://registry.npmjs.org/@csstools/postcss-color-mix-function/-/postcss-color-mix-function-3.0.7.tgz", - "integrity": "sha512-e68Nev4CxZYCLcrfWhHH4u/N1YocOfTmw67/kVX5Rb7rnguqqLyxPjhHWjSBX8o4bmyuukmNf3wrUSU3//kT7g==", + "version": "3.0.10", + "resolved": "https://registry.npmjs.org/@csstools/postcss-color-mix-function/-/postcss-color-mix-function-3.0.10.tgz", + "integrity": "sha512-P0lIbQW9I4ShE7uBgZRib/lMTf9XMjJkFl/d6w4EMNHu2qvQ6zljJGEcBkw/NsBtq/6q3WrmgxSS8kHtPMkK4Q==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "dependencies": { + "@csstools/css-color-parser": "^3.0.10", + "@csstools/css-parser-algorithms": "^3.0.5", + "@csstools/css-tokenizer": "^3.0.4", + "@csstools/postcss-progressive-custom-properties": "^4.1.0", + "@csstools/utilities": "^2.0.0" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/@csstools/postcss-color-mix-variadic-function-arguments": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@csstools/postcss-color-mix-variadic-function-arguments/-/postcss-color-mix-variadic-function-arguments-1.0.0.tgz", + "integrity": "sha512-Z5WhouTyD74dPFPrVE7KydgNS9VvnjB8qcdes9ARpCOItb4jTnm7cHp4FhxCRUoyhabD0WVv43wbkJ4p8hLAlQ==", "funding": [ { "type": "github", @@ -2092,10 +2127,10 @@ } ], "dependencies": { - "@csstools/css-color-parser": "^3.0.7", - "@csstools/css-parser-algorithms": "^3.0.4", - "@csstools/css-tokenizer": "^3.0.3", - "@csstools/postcss-progressive-custom-properties": "^4.0.0", + "@csstools/css-color-parser": "^3.0.10", + "@csstools/css-parser-algorithms": "^3.0.5", + "@csstools/css-tokenizer": "^3.0.4", + "@csstools/postcss-progressive-custom-properties": "^4.1.0", "@csstools/utilities": "^2.0.0" }, "engines": { @@ -2106,9 +2141,9 @@ } }, "node_modules/@csstools/postcss-content-alt-text": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/@csstools/postcss-content-alt-text/-/postcss-content-alt-text-2.0.4.tgz", - "integrity": "sha512-YItlZUOuZJCBlRaCf8Aucc1lgN41qYGALMly0qQllrxYJhiyzlI6RxOTMUvtWk+KhS8GphMDsDhKQ7KTPfEMSw==", + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/@csstools/postcss-content-alt-text/-/postcss-content-alt-text-2.0.6.tgz", + "integrity": "sha512-eRjLbOjblXq+byyaedQRSrAejKGNAFued+LcbzT+LCL78fabxHkxYjBbxkroONxHHYu2qxhFK2dBStTLPG3jpQ==", "funding": [ { "type": "github", @@ -2120,9 +2155,9 @@ } ], "dependencies": { - "@csstools/css-parser-algorithms": "^3.0.4", - "@csstools/css-tokenizer": "^3.0.3", - "@csstools/postcss-progressive-custom-properties": "^4.0.0", + "@csstools/css-parser-algorithms": "^3.0.5", + "@csstools/css-tokenizer": "^3.0.4", + "@csstools/postcss-progressive-custom-properties": "^4.1.0", "@csstools/utilities": "^2.0.0" }, "engines": { @@ -2133,9 +2168,9 @@ } }, "node_modules/@csstools/postcss-exponential-functions": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/@csstools/postcss-exponential-functions/-/postcss-exponential-functions-2.0.6.tgz", - "integrity": "sha512-IgJA5DQsQLu/upA3HcdvC6xEMR051ufebBTIXZ5E9/9iiaA7juXWz1ceYj814lnDYP/7eWjZnw0grRJlX4eI6g==", + "version": "2.0.9", + "resolved": "https://registry.npmjs.org/@csstools/postcss-exponential-functions/-/postcss-exponential-functions-2.0.9.tgz", + "integrity": "sha512-abg2W/PI3HXwS/CZshSa79kNWNZHdJPMBXeZNyPQFbbj8sKO3jXxOt/wF7juJVjyDTc6JrvaUZYFcSBZBhaxjw==", "funding": [ { "type": "github", @@ -2147,9 +2182,9 @@ } ], "dependencies": { - "@csstools/css-calc": "^2.1.1", - "@csstools/css-parser-algorithms": "^3.0.4", - "@csstools/css-tokenizer": "^3.0.3" + "@csstools/css-calc": "^2.1.4", + "@csstools/css-parser-algorithms": "^3.0.5", + "@csstools/css-tokenizer": "^3.0.4" }, "engines": { "node": ">=18" @@ -2184,9 +2219,9 @@ } }, "node_modules/@csstools/postcss-gamut-mapping": { - "version": "2.0.7", - "resolved": "https://registry.npmjs.org/@csstools/postcss-gamut-mapping/-/postcss-gamut-mapping-2.0.7.tgz", - "integrity": "sha512-gzFEZPoOkY0HqGdyeBXR3JP218Owr683u7KOZazTK7tQZBE8s2yhg06W1tshOqk7R7SWvw9gkw2TQogKpIW8Xw==", + "version": "2.0.10", + "resolved": "https://registry.npmjs.org/@csstools/postcss-gamut-mapping/-/postcss-gamut-mapping-2.0.10.tgz", + "integrity": "sha512-QDGqhJlvFnDlaPAfCYPsnwVA6ze+8hhrwevYWlnUeSjkkZfBpcCO42SaUD8jiLlq7niouyLgvup5lh+f1qessg==", "funding": [ { "type": "github", @@ -2198,9 +2233,9 @@ } ], "dependencies": { - "@csstools/css-color-parser": "^3.0.7", - "@csstools/css-parser-algorithms": "^3.0.4", - "@csstools/css-tokenizer": "^3.0.3" + "@csstools/css-color-parser": "^3.0.10", + "@csstools/css-parser-algorithms": "^3.0.5", + "@csstools/css-tokenizer": "^3.0.4" }, "engines": { "node": ">=18" @@ -2210,9 +2245,9 @@ } }, "node_modules/@csstools/postcss-gradients-interpolation-method": { - "version": "5.0.7", - "resolved": "https://registry.npmjs.org/@csstools/postcss-gradients-interpolation-method/-/postcss-gradients-interpolation-method-5.0.7.tgz", - "integrity": "sha512-WgEyBeg6glUeTdS2XT7qeTFBthTJuXlS9GFro/DVomj7W7WMTamAwpoP4oQCq/0Ki2gvfRYFi/uZtmRE14/DFA==", + "version": "5.0.10", + "resolved": "https://registry.npmjs.org/@csstools/postcss-gradients-interpolation-method/-/postcss-gradients-interpolation-method-5.0.10.tgz", + "integrity": "sha512-HHPauB2k7Oits02tKFUeVFEU2ox/H3OQVrP3fSOKDxvloOikSal+3dzlyTZmYsb9FlY9p5EUpBtz0//XBmy+aw==", "funding": [ { "type": "github", @@ -2224,10 +2259,10 @@ } ], "dependencies": { - "@csstools/css-color-parser": "^3.0.7", - "@csstools/css-parser-algorithms": "^3.0.4", - "@csstools/css-tokenizer": "^3.0.3", - "@csstools/postcss-progressive-custom-properties": "^4.0.0", + "@csstools/css-color-parser": "^3.0.10", + "@csstools/css-parser-algorithms": "^3.0.5", + "@csstools/css-tokenizer": "^3.0.4", + "@csstools/postcss-progressive-custom-properties": "^4.1.0", "@csstools/utilities": "^2.0.0" }, "engines": { @@ -2238,9 +2273,9 @@ } }, "node_modules/@csstools/postcss-hwb-function": { - "version": "4.0.7", - "resolved": "https://registry.npmjs.org/@csstools/postcss-hwb-function/-/postcss-hwb-function-4.0.7.tgz", - "integrity": "sha512-LKYqjO+wGwDCfNIEllessCBWfR4MS/sS1WXO+j00KKyOjm7jDW2L6jzUmqASEiv/kkJO39GcoIOvTTfB3yeBUA==", + "version": "4.0.10", + "resolved": "https://registry.npmjs.org/@csstools/postcss-hwb-function/-/postcss-hwb-function-4.0.10.tgz", + "integrity": "sha512-nOKKfp14SWcdEQ++S9/4TgRKchooLZL0TUFdun3nI4KPwCjETmhjta1QT4ICQcGVWQTvrsgMM/aLB5We+kMHhQ==", "funding": [ { "type": "github", @@ -2252,10 +2287,10 @@ } ], "dependencies": { - "@csstools/css-color-parser": "^3.0.7", - "@csstools/css-parser-algorithms": "^3.0.4", - "@csstools/css-tokenizer": "^3.0.3", - "@csstools/postcss-progressive-custom-properties": "^4.0.0", + "@csstools/css-color-parser": "^3.0.10", + "@csstools/css-parser-algorithms": "^3.0.5", + "@csstools/css-tokenizer": "^3.0.4", + "@csstools/postcss-progressive-custom-properties": "^4.1.0", "@csstools/utilities": "^2.0.0" }, "engines": { @@ -2266,9 +2301,9 @@ } }, "node_modules/@csstools/postcss-ic-unit": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@csstools/postcss-ic-unit/-/postcss-ic-unit-4.0.0.tgz", - "integrity": "sha512-9QT5TDGgx7wD3EEMN3BSUG6ckb6Eh5gSPT5kZoVtUuAonfPmLDJyPhqR4ntPpMYhUKAMVKAg3I/AgzqHMSeLhA==", + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/@csstools/postcss-ic-unit/-/postcss-ic-unit-4.0.2.tgz", + "integrity": "sha512-lrK2jjyZwh7DbxaNnIUjkeDmU8Y6KyzRBk91ZkI5h8nb1ykEfZrtIVArdIjX4DHMIBGpdHrgP0n4qXDr7OHaKA==", "funding": [ { "type": "github", @@ -2280,7 +2315,7 @@ } ], "dependencies": { - "@csstools/postcss-progressive-custom-properties": "^4.0.0", + "@csstools/postcss-progressive-custom-properties": "^4.1.0", "@csstools/utilities": "^2.0.0", "postcss-value-parser": "^4.2.0" }, @@ -2313,9 +2348,9 @@ } }, "node_modules/@csstools/postcss-is-pseudo-class": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/@csstools/postcss-is-pseudo-class/-/postcss-is-pseudo-class-5.0.1.tgz", - "integrity": "sha512-JLp3POui4S1auhDR0n8wHd/zTOWmMsmK3nQd3hhL6FhWPaox5W7j1se6zXOG/aP07wV2ww0lxbKYGwbBszOtfQ==", + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/@csstools/postcss-is-pseudo-class/-/postcss-is-pseudo-class-5.0.3.tgz", + "integrity": "sha512-jS/TY4SpG4gszAtIg7Qnf3AS2pjcUM5SzxpApOrlndMeGhIbaTzWBzzP/IApXoNWEW7OhcjkRT48jnAUIFXhAQ==", "funding": [ { "type": "github", @@ -2371,9 +2406,9 @@ } }, "node_modules/@csstools/postcss-light-dark-function": { - "version": "2.0.7", - "resolved": "https://registry.npmjs.org/@csstools/postcss-light-dark-function/-/postcss-light-dark-function-2.0.7.tgz", - "integrity": "sha512-ZZ0rwlanYKOHekyIPaU+sVm3BEHCe+Ha0/px+bmHe62n0Uc1lL34vbwrLYn6ote8PHlsqzKeTQdIejQCJ05tfw==", + "version": "2.0.9", + "resolved": "https://registry.npmjs.org/@csstools/postcss-light-dark-function/-/postcss-light-dark-function-2.0.9.tgz", + "integrity": "sha512-1tCZH5bla0EAkFAI2r0H33CDnIBeLUaJh1p+hvvsylJ4svsv2wOmJjJn+OXwUZLXef37GYbRIVKX+X+g6m+3CQ==", "funding": [ { "type": "github", @@ -2385,9 +2420,9 @@ } ], "dependencies": { - "@csstools/css-parser-algorithms": "^3.0.4", - "@csstools/css-tokenizer": "^3.0.3", - "@csstools/postcss-progressive-custom-properties": "^4.0.0", + "@csstools/css-parser-algorithms": "^3.0.5", + "@csstools/css-tokenizer": "^3.0.4", + "@csstools/postcss-progressive-custom-properties": "^4.1.0", "@csstools/utilities": "^2.0.0" }, "engines": { @@ -2485,9 +2520,9 @@ } }, "node_modules/@csstools/postcss-logical-viewport-units": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/@csstools/postcss-logical-viewport-units/-/postcss-logical-viewport-units-3.0.3.tgz", - "integrity": "sha512-OC1IlG/yoGJdi0Y+7duz/kU/beCwO+Gua01sD6GtOtLi7ByQUpcIqs7UE/xuRPay4cHgOMatWdnDdsIDjnWpPw==", + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@csstools/postcss-logical-viewport-units/-/postcss-logical-viewport-units-3.0.4.tgz", + "integrity": "sha512-q+eHV1haXA4w9xBwZLKjVKAWn3W2CMqmpNpZUk5kRprvSiBEGMgrNH3/sJZ8UA3JgyHaOt3jwT9uFa4wLX4EqQ==", "funding": [ { "type": "github", @@ -2499,7 +2534,7 @@ } ], "dependencies": { - "@csstools/css-tokenizer": "^3.0.3", + "@csstools/css-tokenizer": "^3.0.4", "@csstools/utilities": "^2.0.0" }, "engines": { @@ -2510,9 +2545,9 @@ } }, "node_modules/@csstools/postcss-media-minmax": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/@csstools/postcss-media-minmax/-/postcss-media-minmax-2.0.6.tgz", - "integrity": "sha512-J1+4Fr2W3pLZsfxkFazK+9kr96LhEYqoeBszLmFjb6AjYs+g9oDAw3J5oQignLKk3rC9XHW+ebPTZ9FaW5u5pg==", + "version": "2.0.9", + "resolved": "https://registry.npmjs.org/@csstools/postcss-media-minmax/-/postcss-media-minmax-2.0.9.tgz", + "integrity": "sha512-af9Qw3uS3JhYLnCbqtZ9crTvvkR+0Se+bBqSr7ykAnl9yKhk6895z9rf+2F4dClIDJWxgn0iZZ1PSdkhrbs2ig==", "funding": [ { "type": "github", @@ -2524,10 +2559,10 @@ } ], "dependencies": { - "@csstools/css-calc": "^2.1.1", - "@csstools/css-parser-algorithms": "^3.0.4", - "@csstools/css-tokenizer": "^3.0.3", - "@csstools/media-query-list-parser": "^4.0.2" + "@csstools/css-calc": "^2.1.4", + "@csstools/css-parser-algorithms": "^3.0.5", + "@csstools/css-tokenizer": "^3.0.4", + "@csstools/media-query-list-parser": "^4.0.3" }, "engines": { "node": ">=18" @@ -2537,9 +2572,9 @@ } }, "node_modules/@csstools/postcss-media-queries-aspect-ratio-number-values": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/@csstools/postcss-media-queries-aspect-ratio-number-values/-/postcss-media-queries-aspect-ratio-number-values-3.0.4.tgz", - "integrity": "sha512-AnGjVslHMm5xw9keusQYvjVWvuS7KWK+OJagaG0+m9QnIjZsrysD2kJP/tr/UJIyYtMCtu8OkUd+Rajb4DqtIQ==", + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/@csstools/postcss-media-queries-aspect-ratio-number-values/-/postcss-media-queries-aspect-ratio-number-values-3.0.5.tgz", + "integrity": "sha512-zhAe31xaaXOY2Px8IYfoVTB3wglbJUVigGphFLj6exb7cjZRH9A6adyE22XfFK3P2PzwRk0VDeTJmaxpluyrDg==", "funding": [ { "type": "github", @@ -2551,9 +2586,9 @@ } ], "dependencies": { - "@csstools/css-parser-algorithms": "^3.0.4", - "@csstools/css-tokenizer": "^3.0.3", - "@csstools/media-query-list-parser": "^4.0.2" + "@csstools/css-parser-algorithms": "^3.0.5", + "@csstools/css-tokenizer": "^3.0.4", + "@csstools/media-query-list-parser": "^4.0.3" }, "engines": { "node": ">=18" @@ -2612,9 +2647,9 @@ } }, "node_modules/@csstools/postcss-oklab-function": { - "version": "4.0.7", - "resolved": "https://registry.npmjs.org/@csstools/postcss-oklab-function/-/postcss-oklab-function-4.0.7.tgz", - "integrity": "sha512-I6WFQIbEKG2IO3vhaMGZDkucbCaUSXMxvHNzDdnfsTCF5tc0UlV3Oe2AhamatQoKFjBi75dSEMrgWq3+RegsOQ==", + "version": "4.0.10", + "resolved": "https://registry.npmjs.org/@csstools/postcss-oklab-function/-/postcss-oklab-function-4.0.10.tgz", + "integrity": "sha512-ZzZUTDd0fgNdhv8UUjGCtObPD8LYxMH+MJsW9xlZaWTV8Ppr4PtxlHYNMmF4vVWGl0T6f8tyWAKjoI6vePSgAg==", "funding": [ { "type": "github", @@ -2626,10 +2661,10 @@ } ], "dependencies": { - "@csstools/css-color-parser": "^3.0.7", - "@csstools/css-parser-algorithms": "^3.0.4", - "@csstools/css-tokenizer": "^3.0.3", - "@csstools/postcss-progressive-custom-properties": "^4.0.0", + "@csstools/css-color-parser": "^3.0.10", + "@csstools/css-parser-algorithms": "^3.0.5", + "@csstools/css-tokenizer": "^3.0.4", + "@csstools/postcss-progressive-custom-properties": "^4.1.0", "@csstools/utilities": "^2.0.0" }, "engines": { @@ -2640,9 +2675,9 @@ } }, "node_modules/@csstools/postcss-progressive-custom-properties": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@csstools/postcss-progressive-custom-properties/-/postcss-progressive-custom-properties-4.0.0.tgz", - "integrity": "sha512-XQPtROaQjomnvLUSy/bALTR5VCtTVUFwYs1SblvYgLSeTo2a/bMNwUwo2piXw5rTv/FEYiy5yPSXBqg9OKUx7Q==", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/@csstools/postcss-progressive-custom-properties/-/postcss-progressive-custom-properties-4.1.0.tgz", + "integrity": "sha512-YrkI9dx8U4R8Sz2EJaoeD9fI7s7kmeEBfmO+UURNeL6lQI7VxF6sBE+rSqdCBn4onwqmxFdBU3lTwyYb/lCmxA==", "funding": [ { "type": "github", @@ -2664,9 +2699,9 @@ } }, "node_modules/@csstools/postcss-random-function": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@csstools/postcss-random-function/-/postcss-random-function-1.0.2.tgz", - "integrity": "sha512-vBCT6JvgdEkvRc91NFoNrLjgGtkLWt47GKT6E2UDn3nd8ZkMBiziQ1Md1OiKoSsgzxsSnGKG3RVdhlbdZEkHjA==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@csstools/postcss-random-function/-/postcss-random-function-2.0.1.tgz", + "integrity": "sha512-q+FQaNiRBhnoSNo+GzqGOIBKoHQ43lYz0ICrV+UudfWnEF6ksS6DsBIJSISKQT2Bvu3g4k6r7t0zYrk5pDlo8w==", "funding": [ { "type": "github", @@ -2678,9 +2713,9 @@ } ], "dependencies": { - "@csstools/css-calc": "^2.1.1", - "@csstools/css-parser-algorithms": "^3.0.4", - "@csstools/css-tokenizer": "^3.0.3" + "@csstools/css-calc": "^2.1.4", + "@csstools/css-parser-algorithms": "^3.0.5", + "@csstools/css-tokenizer": "^3.0.4" }, "engines": { "node": ">=18" @@ -2690,9 +2725,9 @@ } }, "node_modules/@csstools/postcss-relative-color-syntax": { - "version": "3.0.7", - "resolved": "https://registry.npmjs.org/@csstools/postcss-relative-color-syntax/-/postcss-relative-color-syntax-3.0.7.tgz", - "integrity": "sha512-apbT31vsJVd18MabfPOnE977xgct5B1I+Jpf+Munw3n6kKb1MMuUmGGH+PT9Hm/fFs6fe61Q/EWnkrb4bNoNQw==", + "version": "3.0.10", + "resolved": "https://registry.npmjs.org/@csstools/postcss-relative-color-syntax/-/postcss-relative-color-syntax-3.0.10.tgz", + "integrity": "sha512-8+0kQbQGg9yYG8hv0dtEpOMLwB9M+P7PhacgIzVzJpixxV4Eq9AUQtQw8adMmAJU1RBBmIlpmtmm3XTRd/T00g==", "funding": [ { "type": "github", @@ -2704,10 +2739,10 @@ } ], "dependencies": { - "@csstools/css-color-parser": "^3.0.7", - "@csstools/css-parser-algorithms": "^3.0.4", - "@csstools/css-tokenizer": "^3.0.3", - "@csstools/postcss-progressive-custom-properties": "^4.0.0", + "@csstools/css-color-parser": "^3.0.10", + "@csstools/css-parser-algorithms": "^3.0.5", + "@csstools/css-tokenizer": "^3.0.4", + "@csstools/postcss-progressive-custom-properties": "^4.1.0", "@csstools/utilities": "^2.0.0" }, "engines": { @@ -2754,9 +2789,9 @@ } }, "node_modules/@csstools/postcss-sign-functions": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@csstools/postcss-sign-functions/-/postcss-sign-functions-1.1.1.tgz", - "integrity": "sha512-MslYkZCeMQDxetNkfmmQYgKCy4c+w9pPDfgOBCJOo/RI1RveEUdZQYtOfrC6cIZB7sD7/PHr2VGOcMXlZawrnA==", + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/@csstools/postcss-sign-functions/-/postcss-sign-functions-1.1.4.tgz", + "integrity": "sha512-P97h1XqRPcfcJndFdG95Gv/6ZzxUBBISem0IDqPZ7WMvc/wlO+yU0c5D/OCpZ5TJoTt63Ok3knGk64N+o6L2Pg==", "funding": [ { "type": "github", @@ -2768,9 +2803,9 @@ } ], "dependencies": { - "@csstools/css-calc": "^2.1.1", - "@csstools/css-parser-algorithms": "^3.0.4", - "@csstools/css-tokenizer": "^3.0.3" + "@csstools/css-calc": "^2.1.4", + "@csstools/css-parser-algorithms": "^3.0.5", + "@csstools/css-tokenizer": "^3.0.4" }, "engines": { "node": ">=18" @@ -2780,9 +2815,9 @@ } }, "node_modules/@csstools/postcss-stepped-value-functions": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/@csstools/postcss-stepped-value-functions/-/postcss-stepped-value-functions-4.0.6.tgz", - "integrity": "sha512-/dwlO9w8vfKgiADxpxUbZOWlL5zKoRIsCymYoh1IPuBsXODKanKnfuZRr32DEqT0//3Av1VjfNZU9yhxtEfIeA==", + "version": "4.0.9", + "resolved": "https://registry.npmjs.org/@csstools/postcss-stepped-value-functions/-/postcss-stepped-value-functions-4.0.9.tgz", + "integrity": "sha512-h9btycWrsex4dNLeQfyU3y3w40LMQooJWFMm/SK9lrKguHDcFl4VMkncKKoXi2z5rM9YGWbUQABI8BT2UydIcA==", "funding": [ { "type": "github", @@ -2794,9 +2829,9 @@ } ], "dependencies": { - "@csstools/css-calc": "^2.1.1", - "@csstools/css-parser-algorithms": "^3.0.4", - "@csstools/css-tokenizer": "^3.0.3" + "@csstools/css-calc": "^2.1.4", + "@csstools/css-parser-algorithms": "^3.0.5", + "@csstools/css-tokenizer": "^3.0.4" }, "engines": { "node": ">=18" @@ -2806,9 +2841,9 @@ } }, "node_modules/@csstools/postcss-text-decoration-shorthand": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/@csstools/postcss-text-decoration-shorthand/-/postcss-text-decoration-shorthand-4.0.1.tgz", - "integrity": "sha512-xPZIikbx6jyzWvhms27uugIc0I4ykH4keRvoa3rxX5K7lEhkbd54rjj/dv60qOCTisoS+3bmwJTeyV1VNBrXaw==", + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/@csstools/postcss-text-decoration-shorthand/-/postcss-text-decoration-shorthand-4.0.2.tgz", + "integrity": "sha512-8XvCRrFNseBSAGxeaVTaNijAu+FzUvjwFXtcrynmazGb/9WUdsPCpBX+mHEHShVRq47Gy4peYAoxYs8ltUnmzA==", "funding": [ { "type": "github", @@ -2820,7 +2855,7 @@ } ], "dependencies": { - "@csstools/color-helpers": "^5.0.1", + "@csstools/color-helpers": "^5.0.2", "postcss-value-parser": "^4.2.0" }, "engines": { @@ -2831,9 +2866,9 @@ } }, "node_modules/@csstools/postcss-trigonometric-functions": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/@csstools/postcss-trigonometric-functions/-/postcss-trigonometric-functions-4.0.6.tgz", - "integrity": "sha512-c4Y1D2Why/PeccaSouXnTt6WcNHJkoJRidV2VW9s5gJ97cNxnLgQ4Qj8qOqkIR9VmTQKJyNcbF4hy79ZQnWD7A==", + "version": "4.0.9", + "resolved": "https://registry.npmjs.org/@csstools/postcss-trigonometric-functions/-/postcss-trigonometric-functions-4.0.9.tgz", + "integrity": "sha512-Hnh5zJUdpNrJqK9v1/E3BbrQhaDTj5YiX7P61TOvUhoDHnUmsNNxcDAgkQ32RrcWx9GVUvfUNPcUkn8R3vIX6A==", "funding": [ { "type": "github", @@ -2845,9 +2880,9 @@ } ], "dependencies": { - "@csstools/css-calc": "^2.1.1", - "@csstools/css-parser-algorithms": "^3.0.4", - "@csstools/css-tokenizer": "^3.0.3" + "@csstools/css-calc": "^2.1.4", + "@csstools/css-parser-algorithms": "^3.0.5", + "@csstools/css-tokenizer": "^3.0.4" }, "engines": { "node": ">=18" @@ -2943,9 +2978,9 @@ } }, "node_modules/@docusaurus/babel": { - "version": "3.7.0", - "resolved": "https://registry.npmjs.org/@docusaurus/babel/-/babel-3.7.0.tgz", - "integrity": "sha512-0H5uoJLm14S/oKV3Keihxvh8RV+vrid+6Gv+2qhuzbqHanawga8tYnsdpjEyt36ucJjqlby2/Md2ObWjA02UXQ==", + "version": "3.8.1", + "resolved": "https://registry.npmjs.org/@docusaurus/babel/-/babel-3.8.1.tgz", + "integrity": "sha512-3brkJrml8vUbn9aeoZUlJfsI/GqyFcDgQJwQkmBtclJgWDEQBKKeagZfOgx0WfUQhagL1sQLNW0iBdxnI863Uw==", "dependencies": { "@babel/core": "^7.25.9", "@babel/generator": "^7.25.9", @@ -2957,8 +2992,8 @@ "@babel/runtime": "^7.25.9", "@babel/runtime-corejs3": "^7.25.9", "@babel/traverse": "^7.25.9", - "@docusaurus/logger": "3.7.0", - "@docusaurus/utils": "3.7.0", + "@docusaurus/logger": "3.8.1", + "@docusaurus/utils": "3.8.1", "babel-plugin-dynamic-import-node": "^2.3.3", "fs-extra": "^11.1.1", "tslib": "^2.6.0" @@ -2968,30 +3003,29 @@ } }, "node_modules/@docusaurus/bundler": { - "version": "3.7.0", - "resolved": "https://registry.npmjs.org/@docusaurus/bundler/-/bundler-3.7.0.tgz", - "integrity": "sha512-CUUT9VlSGukrCU5ctZucykvgCISivct+cby28wJwCC/fkQFgAHRp/GKv2tx38ZmXb7nacrKzFTcp++f9txUYGg==", + "version": "3.8.1", + "resolved": "https://registry.npmjs.org/@docusaurus/bundler/-/bundler-3.8.1.tgz", + "integrity": "sha512-/z4V0FRoQ0GuSLToNjOSGsk6m2lQUG4FRn8goOVoZSRsTrU8YR2aJacX5K3RG18EaX9b+52pN4m1sL3MQZVsQA==", "dependencies": { "@babel/core": "^7.25.9", - "@docusaurus/babel": "3.7.0", - "@docusaurus/cssnano-preset": "3.7.0", - "@docusaurus/logger": "3.7.0", - "@docusaurus/types": "3.7.0", - "@docusaurus/utils": "3.7.0", + "@docusaurus/babel": "3.8.1", + "@docusaurus/cssnano-preset": "3.8.1", + "@docusaurus/logger": "3.8.1", + "@docusaurus/types": "3.8.1", + "@docusaurus/utils": "3.8.1", "babel-loader": "^9.2.1", - "clean-css": "^5.3.2", + "clean-css": "^5.3.3", "copy-webpack-plugin": "^11.0.0", - "css-loader": "^6.8.1", + "css-loader": "^6.11.0", "css-minimizer-webpack-plugin": "^5.0.1", "cssnano": "^6.1.2", "file-loader": "^6.2.0", "html-minifier-terser": "^7.2.0", - "mini-css-extract-plugin": "^2.9.1", + "mini-css-extract-plugin": "^2.9.2", "null-loader": "^4.0.1", - "postcss": "^8.4.26", - "postcss-loader": "^7.3.3", - "postcss-preset-env": "^10.1.0", - "react-dev-utils": "^12.0.1", + "postcss": "^8.5.4", + "postcss-loader": "^7.3.4", + "postcss-preset-env": "^10.2.1", "terser-webpack-plugin": "^5.3.9", "tslib": "^2.6.0", "url-loader": "^4.1.1", @@ -3011,17 +3045,17 @@ } }, "node_modules/@docusaurus/core": { - "version": "3.7.0", - "resolved": "https://registry.npmjs.org/@docusaurus/core/-/core-3.7.0.tgz", - "integrity": "sha512-b0fUmaL+JbzDIQaamzpAFpTviiaU4cX3Qz8cuo14+HGBCwa0evEK0UYCBFY3n4cLzL8Op1BueeroUD2LYAIHbQ==", - "dependencies": { - "@docusaurus/babel": "3.7.0", - "@docusaurus/bundler": "3.7.0", - "@docusaurus/logger": "3.7.0", - "@docusaurus/mdx-loader": "3.7.0", - "@docusaurus/utils": "3.7.0", - "@docusaurus/utils-common": "3.7.0", - "@docusaurus/utils-validation": "3.7.0", + "version": "3.8.1", + "resolved": "https://registry.npmjs.org/@docusaurus/core/-/core-3.8.1.tgz", + "integrity": "sha512-ENB01IyQSqI2FLtOzqSI3qxG2B/jP4gQPahl2C3XReiLebcVh5B5cB9KYFvdoOqOWPyr5gXK4sjgTKv7peXCrA==", + "dependencies": { + "@docusaurus/babel": "3.8.1", + "@docusaurus/bundler": "3.8.1", + "@docusaurus/logger": "3.8.1", + "@docusaurus/mdx-loader": "3.8.1", + "@docusaurus/utils": "3.8.1", + "@docusaurus/utils-common": "3.8.1", + "@docusaurus/utils-validation": "3.8.1", "boxen": "^6.2.1", "chalk": "^4.1.2", "chokidar": "^3.5.3", @@ -3029,19 +3063,19 @@ "combine-promises": "^1.1.0", "commander": "^5.1.0", "core-js": "^3.31.1", - "del": "^6.1.1", "detect-port": "^1.5.1", "escape-html": "^1.0.3", "eta": "^2.2.0", "eval": "^0.1.8", + "execa": "5.1.1", "fs-extra": "^11.1.1", "html-tags": "^3.3.1", "html-webpack-plugin": "^5.6.0", "leven": "^3.1.0", "lodash": "^4.17.21", + "open": "^8.4.0", "p-map": "^4.0.0", "prompts": "^2.4.2", - "react-dev-utils": "^12.0.1", "react-helmet-async": "npm:@slorber/react-helmet-async@1.3.0", "react-loadable": "npm:@docusaurus/react-loadable@6.0.0", "react-loadable-ssr-addon-v5-slorber": "^1.0.1", @@ -3050,7 +3084,7 @@ "react-router-dom": "^5.3.4", "semver": "^7.5.4", "serve-handler": "^6.1.6", - "shelljs": "^0.8.5", + "tinypool": "^1.0.2", "tslib": "^2.6.0", "update-notifier": "^6.0.2", "webpack": "^5.95.0", @@ -3071,12 +3105,12 @@ } }, "node_modules/@docusaurus/cssnano-preset": { - "version": "3.7.0", - "resolved": "https://registry.npmjs.org/@docusaurus/cssnano-preset/-/cssnano-preset-3.7.0.tgz", - "integrity": "sha512-X9GYgruZBSOozg4w4dzv9uOz8oK/EpPVQXkp0MM6Tsgp/nRIU9hJzJ0Pxg1aRa3xCeEQTOimZHcocQFlLwYajQ==", + "version": "3.8.1", + "resolved": "https://registry.npmjs.org/@docusaurus/cssnano-preset/-/cssnano-preset-3.8.1.tgz", + "integrity": "sha512-G7WyR2N6SpyUotqhGznERBK+x84uyhfMQM2MmDLs88bw4Flom6TY46HzkRkSEzaP9j80MbTN8naiL1fR17WQug==", "dependencies": { "cssnano-preset-advanced": "^6.1.2", - "postcss": "^8.4.38", + "postcss": "^8.5.4", "postcss-sort-media-queries": "^5.2.0", "tslib": "^2.6.0" }, @@ -3085,9 +3119,9 @@ } }, "node_modules/@docusaurus/logger": { - "version": "3.7.0", - "resolved": "https://registry.npmjs.org/@docusaurus/logger/-/logger-3.7.0.tgz", - "integrity": "sha512-z7g62X7bYxCYmeNNuO9jmzxLQG95q9QxINCwpboVcNff3SJiHJbGrarxxOVMVmAh1MsrSfxWkVGv4P41ktnFsA==", + "version": "3.8.1", + "resolved": "https://registry.npmjs.org/@docusaurus/logger/-/logger-3.8.1.tgz", + "integrity": "sha512-2wjeGDhKcExEmjX8k1N/MRDiPKXGF2Pg+df/bDDPnnJWHXnVEZxXj80d6jcxp1Gpnksl0hF8t/ZQw9elqj2+ww==", "dependencies": { "chalk": "^4.1.2", "tslib": "^2.6.0" @@ -3097,20 +3131,20 @@ } }, "node_modules/@docusaurus/mdx-loader": { - "version": "3.7.0", - "resolved": "https://registry.npmjs.org/@docusaurus/mdx-loader/-/mdx-loader-3.7.0.tgz", - "integrity": "sha512-OFBG6oMjZzc78/U3WNPSHs2W9ZJ723ewAcvVJaqS0VgyeUfmzUV8f1sv+iUHA0DtwiR5T5FjOxj6nzEE8LY6VA==", + "version": "3.8.1", + "resolved": "https://registry.npmjs.org/@docusaurus/mdx-loader/-/mdx-loader-3.8.1.tgz", + "integrity": "sha512-DZRhagSFRcEq1cUtBMo4TKxSNo/W6/s44yhr8X+eoXqCLycFQUylebOMPseHi5tc4fkGJqwqpWJLz6JStU9L4w==", "dependencies": { - "@docusaurus/logger": "3.7.0", - "@docusaurus/utils": "3.7.0", - "@docusaurus/utils-validation": "3.7.0", + "@docusaurus/logger": "3.8.1", + "@docusaurus/utils": "3.8.1", + "@docusaurus/utils-validation": "3.8.1", "@mdx-js/mdx": "^3.0.0", "@slorber/remark-comment": "^1.0.0", "escape-html": "^1.0.3", "estree-util-value-to-estree": "^3.0.1", "file-loader": "^6.2.0", "fs-extra": "^11.1.1", - "image-size": "^1.0.2", + "image-size": "^2.0.2", "mdast-util-mdx": "^3.0.0", "mdast-util-to-string": "^4.0.0", "rehype-raw": "^7.0.0", @@ -3135,16 +3169,16 @@ } }, "node_modules/@docusaurus/module-type-aliases": { - "version": "3.7.0", - "resolved": "https://registry.npmjs.org/@docusaurus/module-type-aliases/-/module-type-aliases-3.7.0.tgz", - "integrity": "sha512-g7WdPqDNaqA60CmBrr0cORTrsOit77hbsTj7xE2l71YhBn79sxdm7WMK7wfhcaafkbpIh7jv5ef5TOpf1Xv9Lg==", + "version": "3.8.1", + "resolved": "https://registry.npmjs.org/@docusaurus/module-type-aliases/-/module-type-aliases-3.8.1.tgz", + "integrity": "sha512-6xhvAJiXzsaq3JdosS7wbRt/PwEPWHr9eM4YNYqVlbgG1hSK3uQDXTVvQktasp3VO6BmfYWPozueLWuj4gB+vg==", "dependencies": { - "@docusaurus/types": "3.7.0", + "@docusaurus/types": "3.8.1", "@types/history": "^4.7.11", "@types/react": "*", "@types/react-router-config": "*", "@types/react-router-dom": "*", - "react-helmet-async": "npm:@slorber/react-helmet-async@*", + "react-helmet-async": "npm:@slorber/react-helmet-async@1.3.0", "react-loadable": "npm:@docusaurus/react-loadable@6.0.0" }, "peerDependencies": { @@ -3153,23 +3187,23 @@ } }, "node_modules/@docusaurus/plugin-content-blog": { - "version": "3.7.0", - "resolved": "https://registry.npmjs.org/@docusaurus/plugin-content-blog/-/plugin-content-blog-3.7.0.tgz", - "integrity": "sha512-EFLgEz6tGHYWdPU0rK8tSscZwx+AsyuBW/r+tNig2kbccHYGUJmZtYN38GjAa3Fda4NU+6wqUO5kTXQSRBQD3g==", - "dependencies": { - "@docusaurus/core": "3.7.0", - "@docusaurus/logger": "3.7.0", - "@docusaurus/mdx-loader": "3.7.0", - "@docusaurus/theme-common": "3.7.0", - "@docusaurus/types": "3.7.0", - "@docusaurus/utils": "3.7.0", - "@docusaurus/utils-common": "3.7.0", - "@docusaurus/utils-validation": "3.7.0", + "version": "3.8.1", + "resolved": "https://registry.npmjs.org/@docusaurus/plugin-content-blog/-/plugin-content-blog-3.8.1.tgz", + "integrity": "sha512-vNTpMmlvNP9n3hGEcgPaXyvTljanAKIUkuG9URQ1DeuDup0OR7Ltvoc8yrmH+iMZJbcQGhUJF+WjHLwuk8HSdw==", + "dependencies": { + "@docusaurus/core": "3.8.1", + "@docusaurus/logger": "3.8.1", + "@docusaurus/mdx-loader": "3.8.1", + "@docusaurus/theme-common": "3.8.1", + "@docusaurus/types": "3.8.1", + "@docusaurus/utils": "3.8.1", + "@docusaurus/utils-common": "3.8.1", + "@docusaurus/utils-validation": "3.8.1", "cheerio": "1.0.0-rc.12", "feed": "^4.2.2", "fs-extra": "^11.1.1", "lodash": "^4.17.21", - "reading-time": "^1.5.0", + "schema-dts": "^1.1.2", "srcset": "^4.0.0", "tslib": "^2.6.0", "unist-util-visit": "^5.0.0", @@ -3186,24 +3220,25 @@ } }, "node_modules/@docusaurus/plugin-content-docs": { - "version": "3.7.0", - "resolved": "https://registry.npmjs.org/@docusaurus/plugin-content-docs/-/plugin-content-docs-3.7.0.tgz", - "integrity": "sha512-GXg5V7kC9FZE4FkUZA8oo/NrlRb06UwuICzI6tcbzj0+TVgjq/mpUXXzSgKzMS82YByi4dY2Q808njcBCyy6tQ==", - "dependencies": { - "@docusaurus/core": "3.7.0", - "@docusaurus/logger": "3.7.0", - "@docusaurus/mdx-loader": "3.7.0", - "@docusaurus/module-type-aliases": "3.7.0", - "@docusaurus/theme-common": "3.7.0", - "@docusaurus/types": "3.7.0", - "@docusaurus/utils": "3.7.0", - "@docusaurus/utils-common": "3.7.0", - "@docusaurus/utils-validation": "3.7.0", + "version": "3.8.1", + "resolved": "https://registry.npmjs.org/@docusaurus/plugin-content-docs/-/plugin-content-docs-3.8.1.tgz", + "integrity": "sha512-oByRkSZzeGNQByCMaX+kif5Nl2vmtj2IHQI2fWjCfCootsdKZDPFLonhIp5s3IGJO7PLUfe0POyw0Xh/RrGXJA==", + "dependencies": { + "@docusaurus/core": "3.8.1", + "@docusaurus/logger": "3.8.1", + "@docusaurus/mdx-loader": "3.8.1", + "@docusaurus/module-type-aliases": "3.8.1", + "@docusaurus/theme-common": "3.8.1", + "@docusaurus/types": "3.8.1", + "@docusaurus/utils": "3.8.1", + "@docusaurus/utils-common": "3.8.1", + "@docusaurus/utils-validation": "3.8.1", "@types/react-router-config": "^5.0.7", "combine-promises": "^1.1.0", "fs-extra": "^11.1.1", "js-yaml": "^4.1.0", "lodash": "^4.17.21", + "schema-dts": "^1.1.2", "tslib": "^2.6.0", "utility-types": "^3.10.0", "webpack": "^5.88.1" @@ -3217,15 +3252,15 @@ } }, "node_modules/@docusaurus/plugin-content-pages": { - "version": "3.7.0", - "resolved": "https://registry.npmjs.org/@docusaurus/plugin-content-pages/-/plugin-content-pages-3.7.0.tgz", - "integrity": "sha512-YJSU3tjIJf032/Aeao8SZjFOrXJbz/FACMveSMjLyMH4itQyZ2XgUIzt4y+1ISvvk5zrW4DABVT2awTCqBkx0Q==", - "dependencies": { - "@docusaurus/core": "3.7.0", - "@docusaurus/mdx-loader": "3.7.0", - "@docusaurus/types": "3.7.0", - "@docusaurus/utils": "3.7.0", - "@docusaurus/utils-validation": "3.7.0", + "version": "3.8.1", + "resolved": "https://registry.npmjs.org/@docusaurus/plugin-content-pages/-/plugin-content-pages-3.8.1.tgz", + "integrity": "sha512-a+V6MS2cIu37E/m7nDJn3dcxpvXb6TvgdNI22vJX8iUTp8eoMoPa0VArEbWvCxMY/xdC26WzNv4wZ6y0iIni/w==", + "dependencies": { + "@docusaurus/core": "3.8.1", + "@docusaurus/mdx-loader": "3.8.1", + "@docusaurus/types": "3.8.1", + "@docusaurus/utils": "3.8.1", + "@docusaurus/utils-validation": "3.8.1", "fs-extra": "^11.1.1", "tslib": "^2.6.0", "webpack": "^5.88.1" @@ -3238,16 +3273,31 @@ "react-dom": "^18.0.0 || ^19.0.0" } }, + "node_modules/@docusaurus/plugin-css-cascade-layers": { + "version": "3.8.1", + "resolved": "https://registry.npmjs.org/@docusaurus/plugin-css-cascade-layers/-/plugin-css-cascade-layers-3.8.1.tgz", + "integrity": "sha512-VQ47xRxfNKjHS5ItzaVXpxeTm7/wJLFMOPo1BkmoMG4Cuz4nuI+Hs62+RMk1OqVog68Swz66xVPK8g9XTrBKRw==", + "dependencies": { + "@docusaurus/core": "3.8.1", + "@docusaurus/types": "3.8.1", + "@docusaurus/utils": "3.8.1", + "@docusaurus/utils-validation": "3.8.1", + "tslib": "^2.6.0" + }, + "engines": { + "node": ">=18.0" + } + }, "node_modules/@docusaurus/plugin-debug": { - "version": "3.7.0", - "resolved": "https://registry.npmjs.org/@docusaurus/plugin-debug/-/plugin-debug-3.7.0.tgz", - "integrity": "sha512-Qgg+IjG/z4svtbCNyTocjIwvNTNEwgRjSXXSJkKVG0oWoH0eX/HAPiu+TS1HBwRPQV+tTYPWLrUypYFepfujZA==", + "version": "3.8.1", + "resolved": "https://registry.npmjs.org/@docusaurus/plugin-debug/-/plugin-debug-3.8.1.tgz", + "integrity": "sha512-nT3lN7TV5bi5hKMB7FK8gCffFTBSsBsAfV84/v293qAmnHOyg1nr9okEw8AiwcO3bl9vije5nsUvP0aRl2lpaw==", "dependencies": { - "@docusaurus/core": "3.7.0", - "@docusaurus/types": "3.7.0", - "@docusaurus/utils": "3.7.0", + "@docusaurus/core": "3.8.1", + "@docusaurus/types": "3.8.1", + "@docusaurus/utils": "3.8.1", "fs-extra": "^11.1.1", - "react-json-view-lite": "^1.2.0", + "react-json-view-lite": "^2.3.0", "tslib": "^2.6.0" }, "engines": { @@ -3258,25 +3308,14 @@ "react-dom": "^18.0.0 || ^19.0.0" } }, - "node_modules/@docusaurus/plugin-debug/node_modules/react-json-view-lite": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/react-json-view-lite/-/react-json-view-lite-1.5.0.tgz", - "integrity": "sha512-nWqA1E4jKPklL2jvHWs6s+7Na0qNgw9HCP6xehdQJeg6nPBTFZgGwyko9Q0oj+jQWKTTVRS30u0toM5wiuL3iw==", - "engines": { - "node": ">=14" - }, - "peerDependencies": { - "react": "^16.13.1 || ^17.0.0 || ^18.0.0" - } - }, "node_modules/@docusaurus/plugin-google-analytics": { - "version": "3.7.0", - "resolved": "https://registry.npmjs.org/@docusaurus/plugin-google-analytics/-/plugin-google-analytics-3.7.0.tgz", - "integrity": "sha512-otIqiRV/jka6Snjf+AqB360XCeSv7lQC+DKYW+EUZf6XbuE8utz5PeUQ8VuOcD8Bk5zvT1MC4JKcd5zPfDuMWA==", + "version": "3.8.1", + "resolved": "https://registry.npmjs.org/@docusaurus/plugin-google-analytics/-/plugin-google-analytics-3.8.1.tgz", + "integrity": "sha512-Hrb/PurOJsmwHAsfMDH6oVpahkEGsx7F8CWMjyP/dw1qjqmdS9rcV1nYCGlM8nOtD3Wk/eaThzUB5TSZsGz+7Q==", "dependencies": { - "@docusaurus/core": "3.7.0", - "@docusaurus/types": "3.7.0", - "@docusaurus/utils-validation": "3.7.0", + "@docusaurus/core": "3.8.1", + "@docusaurus/types": "3.8.1", + "@docusaurus/utils-validation": "3.8.1", "tslib": "^2.6.0" }, "engines": { @@ -3288,13 +3327,13 @@ } }, "node_modules/@docusaurus/plugin-google-gtag": { - "version": "3.7.0", - "resolved": "https://registry.npmjs.org/@docusaurus/plugin-google-gtag/-/plugin-google-gtag-3.7.0.tgz", - "integrity": "sha512-M3vrMct1tY65ModbyeDaMoA+fNJTSPe5qmchhAbtqhDD/iALri0g9LrEpIOwNaoLmm6lO88sfBUADQrSRSGSWA==", + "version": "3.8.1", + "resolved": "https://registry.npmjs.org/@docusaurus/plugin-google-gtag/-/plugin-google-gtag-3.8.1.tgz", + "integrity": "sha512-tKE8j1cEZCh8KZa4aa80zpSTxsC2/ZYqjx6AAfd8uA8VHZVw79+7OTEP2PoWi0uL5/1Is0LF5Vwxd+1fz5HlKg==", "dependencies": { - "@docusaurus/core": "3.7.0", - "@docusaurus/types": "3.7.0", - "@docusaurus/utils-validation": "3.7.0", + "@docusaurus/core": "3.8.1", + "@docusaurus/types": "3.8.1", + "@docusaurus/utils-validation": "3.8.1", "@types/gtag.js": "^0.0.12", "tslib": "^2.6.0" }, @@ -3307,13 +3346,13 @@ } }, "node_modules/@docusaurus/plugin-google-tag-manager": { - "version": "3.7.0", - "resolved": "https://registry.npmjs.org/@docusaurus/plugin-google-tag-manager/-/plugin-google-tag-manager-3.7.0.tgz", - "integrity": "sha512-X8U78nb8eiMiPNg3jb9zDIVuuo/rE1LjGDGu+5m5CX4UBZzjMy+klOY2fNya6x8ACyE/L3K2erO1ErheP55W/w==", + "version": "3.8.1", + "resolved": "https://registry.npmjs.org/@docusaurus/plugin-google-tag-manager/-/plugin-google-tag-manager-3.8.1.tgz", + "integrity": "sha512-iqe3XKITBquZq+6UAXdb1vI0fPY5iIOitVjPQ581R1ZKpHr0qe+V6gVOrrcOHixPDD/BUKdYwkxFjpNiEN+vBw==", "dependencies": { - "@docusaurus/core": "3.7.0", - "@docusaurus/types": "3.7.0", - "@docusaurus/utils-validation": "3.7.0", + "@docusaurus/core": "3.8.1", + "@docusaurus/types": "3.8.1", + "@docusaurus/utils-validation": "3.8.1", "tslib": "^2.6.0" }, "engines": { @@ -3325,16 +3364,16 @@ } }, "node_modules/@docusaurus/plugin-sitemap": { - "version": "3.7.0", - "resolved": "https://registry.npmjs.org/@docusaurus/plugin-sitemap/-/plugin-sitemap-3.7.0.tgz", - "integrity": "sha512-bTRT9YLZ/8I/wYWKMQke18+PF9MV8Qub34Sku6aw/vlZ/U+kuEuRpQ8bTcNOjaTSfYsWkK4tTwDMHK2p5S86cA==", - "dependencies": { - "@docusaurus/core": "3.7.0", - "@docusaurus/logger": "3.7.0", - "@docusaurus/types": "3.7.0", - "@docusaurus/utils": "3.7.0", - "@docusaurus/utils-common": "3.7.0", - "@docusaurus/utils-validation": "3.7.0", + "version": "3.8.1", + "resolved": "https://registry.npmjs.org/@docusaurus/plugin-sitemap/-/plugin-sitemap-3.8.1.tgz", + "integrity": "sha512-+9YV/7VLbGTq8qNkjiugIelmfUEVkTyLe6X8bWq7K5qPvGXAjno27QAfFq63mYfFFbJc7z+pudL63acprbqGzw==", + "dependencies": { + "@docusaurus/core": "3.8.1", + "@docusaurus/logger": "3.8.1", + "@docusaurus/types": "3.8.1", + "@docusaurus/utils": "3.8.1", + "@docusaurus/utils-common": "3.8.1", + "@docusaurus/utils-validation": "3.8.1", "fs-extra": "^11.1.1", "sitemap": "^7.1.1", "tslib": "^2.6.0" @@ -3348,14 +3387,14 @@ } }, "node_modules/@docusaurus/plugin-svgr": { - "version": "3.7.0", - "resolved": "https://registry.npmjs.org/@docusaurus/plugin-svgr/-/plugin-svgr-3.7.0.tgz", - "integrity": "sha512-HByXIZTbc4GV5VAUkZ2DXtXv1Qdlnpk3IpuImwSnEzCDBkUMYcec5282hPjn6skZqB25M1TYCmWS91UbhBGxQg==", - "dependencies": { - "@docusaurus/core": "3.7.0", - "@docusaurus/types": "3.7.0", - "@docusaurus/utils": "3.7.0", - "@docusaurus/utils-validation": "3.7.0", + "version": "3.8.1", + "resolved": "https://registry.npmjs.org/@docusaurus/plugin-svgr/-/plugin-svgr-3.8.1.tgz", + "integrity": "sha512-rW0LWMDsdlsgowVwqiMb/7tANDodpy1wWPwCcamvhY7OECReN3feoFwLjd/U4tKjNY3encj0AJSTxJA+Fpe+Gw==", + "dependencies": { + "@docusaurus/core": "3.8.1", + "@docusaurus/types": "3.8.1", + "@docusaurus/utils": "3.8.1", + "@docusaurus/utils-validation": "3.8.1", "@svgr/core": "8.1.0", "@svgr/webpack": "^8.1.0", "tslib": "^2.6.0", @@ -3370,24 +3409,25 @@ } }, "node_modules/@docusaurus/preset-classic": { - "version": "3.7.0", - "resolved": "https://registry.npmjs.org/@docusaurus/preset-classic/-/preset-classic-3.7.0.tgz", - "integrity": "sha512-nPHj8AxDLAaQXs+O6+BwILFuhiWbjfQWrdw2tifOClQoNfuXDjfjogee6zfx6NGHWqshR23LrcN115DmkHC91Q==", - "dependencies": { - "@docusaurus/core": "3.7.0", - "@docusaurus/plugin-content-blog": "3.7.0", - "@docusaurus/plugin-content-docs": "3.7.0", - "@docusaurus/plugin-content-pages": "3.7.0", - "@docusaurus/plugin-debug": "3.7.0", - "@docusaurus/plugin-google-analytics": "3.7.0", - "@docusaurus/plugin-google-gtag": "3.7.0", - "@docusaurus/plugin-google-tag-manager": "3.7.0", - "@docusaurus/plugin-sitemap": "3.7.0", - "@docusaurus/plugin-svgr": "3.7.0", - "@docusaurus/theme-classic": "3.7.0", - "@docusaurus/theme-common": "3.7.0", - "@docusaurus/theme-search-algolia": "3.7.0", - "@docusaurus/types": "3.7.0" + "version": "3.8.1", + "resolved": "https://registry.npmjs.org/@docusaurus/preset-classic/-/preset-classic-3.8.1.tgz", + "integrity": "sha512-yJSjYNHXD8POMGc2mKQuj3ApPrN+eG0rO1UPgSx7jySpYU+n4WjBikbrA2ue5ad9A7aouEtMWUoiSRXTH/g7KQ==", + "dependencies": { + "@docusaurus/core": "3.8.1", + "@docusaurus/plugin-content-blog": "3.8.1", + "@docusaurus/plugin-content-docs": "3.8.1", + "@docusaurus/plugin-content-pages": "3.8.1", + "@docusaurus/plugin-css-cascade-layers": "3.8.1", + "@docusaurus/plugin-debug": "3.8.1", + "@docusaurus/plugin-google-analytics": "3.8.1", + "@docusaurus/plugin-google-gtag": "3.8.1", + "@docusaurus/plugin-google-tag-manager": "3.8.1", + "@docusaurus/plugin-sitemap": "3.8.1", + "@docusaurus/plugin-svgr": "3.8.1", + "@docusaurus/theme-classic": "3.8.1", + "@docusaurus/theme-common": "3.8.1", + "@docusaurus/theme-search-algolia": "3.8.1", + "@docusaurus/types": "3.8.1" }, "engines": { "node": ">=18.0" @@ -3398,30 +3438,30 @@ } }, "node_modules/@docusaurus/theme-classic": { - "version": "3.7.0", - "resolved": "https://registry.npmjs.org/@docusaurus/theme-classic/-/theme-classic-3.7.0.tgz", - "integrity": "sha512-MnLxG39WcvLCl4eUzHr0gNcpHQfWoGqzADCly54aqCofQX6UozOS9Th4RK3ARbM9m7zIRv3qbhggI53dQtx/hQ==", - "dependencies": { - "@docusaurus/core": "3.7.0", - "@docusaurus/logger": "3.7.0", - "@docusaurus/mdx-loader": "3.7.0", - "@docusaurus/module-type-aliases": "3.7.0", - "@docusaurus/plugin-content-blog": "3.7.0", - "@docusaurus/plugin-content-docs": "3.7.0", - "@docusaurus/plugin-content-pages": "3.7.0", - "@docusaurus/theme-common": "3.7.0", - "@docusaurus/theme-translations": "3.7.0", - "@docusaurus/types": "3.7.0", - "@docusaurus/utils": "3.7.0", - "@docusaurus/utils-common": "3.7.0", - "@docusaurus/utils-validation": "3.7.0", + "version": "3.8.1", + "resolved": "https://registry.npmjs.org/@docusaurus/theme-classic/-/theme-classic-3.8.1.tgz", + "integrity": "sha512-bqDUCNqXeYypMCsE1VcTXSI1QuO4KXfx8Cvl6rYfY0bhhqN6d2WZlRkyLg/p6pm+DzvanqHOyYlqdPyP0iz+iw==", + "dependencies": { + "@docusaurus/core": "3.8.1", + "@docusaurus/logger": "3.8.1", + "@docusaurus/mdx-loader": "3.8.1", + "@docusaurus/module-type-aliases": "3.8.1", + "@docusaurus/plugin-content-blog": "3.8.1", + "@docusaurus/plugin-content-docs": "3.8.1", + "@docusaurus/plugin-content-pages": "3.8.1", + "@docusaurus/theme-common": "3.8.1", + "@docusaurus/theme-translations": "3.8.1", + "@docusaurus/types": "3.8.1", + "@docusaurus/utils": "3.8.1", + "@docusaurus/utils-common": "3.8.1", + "@docusaurus/utils-validation": "3.8.1", "@mdx-js/react": "^3.0.0", "clsx": "^2.0.0", "copy-text-to-clipboard": "^3.2.0", "infima": "0.2.0-alpha.45", "lodash": "^4.17.21", "nprogress": "^0.2.0", - "postcss": "^8.4.26", + "postcss": "^8.5.4", "prism-react-renderer": "^2.3.0", "prismjs": "^1.29.0", "react-router-dom": "^5.3.4", @@ -3438,14 +3478,14 @@ } }, "node_modules/@docusaurus/theme-common": { - "version": "3.7.0", - "resolved": "https://registry.npmjs.org/@docusaurus/theme-common/-/theme-common-3.7.0.tgz", - "integrity": "sha512-8eJ5X0y+gWDsURZnBfH0WabdNm8XMCXHv8ENy/3Z/oQKwaB/EHt5lP9VsTDTf36lKEp0V6DjzjFyFIB+CetL0A==", - "dependencies": { - "@docusaurus/mdx-loader": "3.7.0", - "@docusaurus/module-type-aliases": "3.7.0", - "@docusaurus/utils": "3.7.0", - "@docusaurus/utils-common": "3.7.0", + "version": "3.8.1", + "resolved": "https://registry.npmjs.org/@docusaurus/theme-common/-/theme-common-3.8.1.tgz", + "integrity": "sha512-UswMOyTnPEVRvN5Qzbo+l8k4xrd5fTFu2VPPfD6FcW/6qUtVLmJTQCktbAL3KJ0BVXGm5aJXz/ZrzqFuZERGPw==", + "dependencies": { + "@docusaurus/mdx-loader": "3.8.1", + "@docusaurus/module-type-aliases": "3.8.1", + "@docusaurus/utils": "3.8.1", + "@docusaurus/utils-common": "3.8.1", "@types/history": "^4.7.11", "@types/react": "*", "@types/react-router-config": "*", @@ -3465,18 +3505,18 @@ } }, "node_modules/@docusaurus/theme-search-algolia": { - "version": "3.7.0", - "resolved": "https://registry.npmjs.org/@docusaurus/theme-search-algolia/-/theme-search-algolia-3.7.0.tgz", - "integrity": "sha512-Al/j5OdzwRU1m3falm+sYy9AaB93S1XF1Lgk9Yc6amp80dNxJVplQdQTR4cYdzkGtuQqbzUA8+kaoYYO0RbK6g==", - "dependencies": { - "@docsearch/react": "^3.8.1", - "@docusaurus/core": "3.7.0", - "@docusaurus/logger": "3.7.0", - "@docusaurus/plugin-content-docs": "3.7.0", - "@docusaurus/theme-common": "3.7.0", - "@docusaurus/theme-translations": "3.7.0", - "@docusaurus/utils": "3.7.0", - "@docusaurus/utils-validation": "3.7.0", + "version": "3.8.1", + "resolved": "https://registry.npmjs.org/@docusaurus/theme-search-algolia/-/theme-search-algolia-3.8.1.tgz", + "integrity": "sha512-NBFH5rZVQRAQM087aYSRKQ9yGEK9eHd+xOxQjqNpxMiV85OhJDD4ZGz6YJIod26Fbooy54UWVdzNU0TFeUUUzQ==", + "dependencies": { + "@docsearch/react": "^3.9.0", + "@docusaurus/core": "3.8.1", + "@docusaurus/logger": "3.8.1", + "@docusaurus/plugin-content-docs": "3.8.1", + "@docusaurus/theme-common": "3.8.1", + "@docusaurus/theme-translations": "3.8.1", + "@docusaurus/utils": "3.8.1", + "@docusaurus/utils-validation": "3.8.1", "algoliasearch": "^5.17.1", "algoliasearch-helper": "^3.22.6", "clsx": "^2.0.0", @@ -3495,9 +3535,9 @@ } }, "node_modules/@docusaurus/theme-translations": { - "version": "3.7.0", - "resolved": "https://registry.npmjs.org/@docusaurus/theme-translations/-/theme-translations-3.7.0.tgz", - "integrity": "sha512-Ewq3bEraWDmienM6eaNK7fx+/lHMtGDHQyd1O+4+3EsDxxUmrzPkV7Ct3nBWTuE0MsoZr3yNwQVKjllzCMuU3g==", + "version": "3.8.1", + "resolved": "https://registry.npmjs.org/@docusaurus/theme-translations/-/theme-translations-3.8.1.tgz", + "integrity": "sha512-OTp6eebuMcf2rJt4bqnvuwmm3NVXfzfYejL+u/Y1qwKhZPrjPoKWfk1CbOP5xH5ZOPkiAsx4dHdQBRJszK3z2g==", "dependencies": { "fs-extra": "^11.1.1", "tslib": "^2.6.0" @@ -3507,9 +3547,9 @@ } }, "node_modules/@docusaurus/types": { - "version": "3.7.0", - "resolved": "https://registry.npmjs.org/@docusaurus/types/-/types-3.7.0.tgz", - "integrity": "sha512-kOmZg5RRqJfH31m+6ZpnwVbkqMJrPOG5t0IOl4i/+3ruXyNfWzZ0lVtVrD0u4ONc/0NOsS9sWYaxxWNkH1LdLQ==", + "version": "3.8.1", + "resolved": "https://registry.npmjs.org/@docusaurus/types/-/types-3.8.1.tgz", + "integrity": "sha512-ZPdW5AB+pBjiVrcLuw3dOS6BFlrG0XkS2lDGsj8TizcnREQg3J8cjsgfDviszOk4CweNfwo1AEELJkYaMUuOPg==", "dependencies": { "@mdx-js/mdx": "^3.0.0", "@types/history": "^4.7.11", @@ -3540,14 +3580,15 @@ } }, "node_modules/@docusaurus/utils": { - "version": "3.7.0", - "resolved": "https://registry.npmjs.org/@docusaurus/utils/-/utils-3.7.0.tgz", - "integrity": "sha512-e7zcB6TPnVzyUaHMJyLSArKa2AG3h9+4CfvKXKKWNx6hRs+p0a+u7HHTJBgo6KW2m+vqDnuIHK4X+bhmoghAFA==", + "version": "3.8.1", + "resolved": "https://registry.npmjs.org/@docusaurus/utils/-/utils-3.8.1.tgz", + "integrity": "sha512-P1ml0nvOmEFdmu0smSXOqTS1sxU5tqvnc0dA4MTKV39kye+bhQnjkIKEE18fNOvxjyB86k8esoCIFM3x4RykOQ==", "dependencies": { - "@docusaurus/logger": "3.7.0", - "@docusaurus/types": "3.7.0", - "@docusaurus/utils-common": "3.7.0", + "@docusaurus/logger": "3.8.1", + "@docusaurus/types": "3.8.1", + "@docusaurus/utils-common": "3.8.1", "escape-string-regexp": "^4.0.0", + "execa": "5.1.1", "file-loader": "^6.2.0", "fs-extra": "^11.1.1", "github-slugger": "^1.5.0", @@ -3557,9 +3598,9 @@ "js-yaml": "^4.1.0", "lodash": "^4.17.21", "micromatch": "^4.0.5", + "p-queue": "^6.6.2", "prompts": "^2.4.2", "resolve-pathname": "^3.0.0", - "shelljs": "^0.8.5", "tslib": "^2.6.0", "url-loader": "^4.1.1", "utility-types": "^3.10.0", @@ -3570,11 +3611,11 @@ } }, "node_modules/@docusaurus/utils-common": { - "version": "3.7.0", - "resolved": "https://registry.npmjs.org/@docusaurus/utils-common/-/utils-common-3.7.0.tgz", - "integrity": "sha512-IZeyIfCfXy0Mevj6bWNg7DG7B8G+S6o6JVpddikZtWyxJguiQ7JYr0SIZ0qWd8pGNuMyVwriWmbWqMnK7Y5PwA==", + "version": "3.8.1", + "resolved": "https://registry.npmjs.org/@docusaurus/utils-common/-/utils-common-3.8.1.tgz", + "integrity": "sha512-zTZiDlvpvoJIrQEEd71c154DkcriBecm4z94OzEE9kz7ikS3J+iSlABhFXM45mZ0eN5pVqqr7cs60+ZlYLewtg==", "dependencies": { - "@docusaurus/types": "3.7.0", + "@docusaurus/types": "3.8.1", "tslib": "^2.6.0" }, "engines": { @@ -3582,13 +3623,13 @@ } }, "node_modules/@docusaurus/utils-validation": { - "version": "3.7.0", - "resolved": "https://registry.npmjs.org/@docusaurus/utils-validation/-/utils-validation-3.7.0.tgz", - "integrity": "sha512-w8eiKk8mRdN+bNfeZqC4nyFoxNyI1/VExMKAzD9tqpJfLLbsa46Wfn5wcKH761g9WkKh36RtFV49iL9lh1DYBA==", + "version": "3.8.1", + "resolved": "https://registry.npmjs.org/@docusaurus/utils-validation/-/utils-validation-3.8.1.tgz", + "integrity": "sha512-gs5bXIccxzEbyVecvxg6upTwaUbfa0KMmTj7HhHzc016AGyxH2o73k1/aOD0IFrdCsfJNt37MqNI47s2MgRZMA==", "dependencies": { - "@docusaurus/logger": "3.7.0", - "@docusaurus/utils": "3.7.0", - "@docusaurus/utils-common": "3.7.0", + "@docusaurus/logger": "3.8.1", + "@docusaurus/utils": "3.8.1", + "@docusaurus/utils-common": "3.8.1", "fs-extra": "^11.2.0", "joi": "^17.9.2", "js-yaml": "^4.1.0", @@ -3640,16 +3681,12 @@ } }, "node_modules/@jridgewell/gen-mapping": { - "version": "0.3.8", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.8.tgz", - "integrity": "sha512-imAbBGkb+ebQyxKgzv5Hu2nmROxoDOXHh80evxdoXNOrvAnVx7zimzc1Oo5h9RlfV4vPXaE2iM5pOFbvOCClWA==", + "version": "0.3.12", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.12.tgz", + "integrity": "sha512-OuLGC46TjB5BbN1dH8JULVVZY4WTdkF7tV9Ys6wLL1rubZnCMstOhNHueU5bLCrnRuDhKPDM4g6sw4Bel5Gzqg==", "dependencies": { - "@jridgewell/set-array": "^1.2.1", - "@jridgewell/sourcemap-codec": "^1.4.10", + "@jridgewell/sourcemap-codec": "^1.5.0", "@jridgewell/trace-mapping": "^0.3.24" - }, - "engines": { - "node": ">=6.0.0" } }, "node_modules/@jridgewell/resolve-uri": { @@ -3660,14 +3697,6 @@ "node": ">=6.0.0" } }, - "node_modules/@jridgewell/set-array": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.2.1.tgz", - "integrity": "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==", - "engines": { - "node": ">=6.0.0" - } - }, "node_modules/@jridgewell/source-map": { "version": "0.3.6", "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.6.tgz", @@ -3683,9 +3712,9 @@ "integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==" }, "node_modules/@jridgewell/trace-mapping": { - "version": "0.3.25", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", - "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", + "version": "0.3.29", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.29.tgz", + "integrity": "sha512-uw6guiW/gcAGPDhLmd77/6lW8QLeiV5RUTsAX46Db6oLhGaVj4lhnPwb184s1bkc8kdVg/+h988dro8GRDpmYQ==", "dependencies": { "@jridgewell/resolve-uri": "^3.1.0", "@jridgewell/sourcemap-codec": "^1.4.14" @@ -4353,11 +4382,6 @@ "@types/node": "*" } }, - "node_modules/@types/parse-json": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/@types/parse-json/-/parse-json-4.0.2.tgz", - "integrity": "sha512-dISoDXWWQwUquiKsyZ4Ng+HX2KsPL7LyHKHQwgGFEA3IaKac4Obd+h2a/a6waisAoepJlBcx9paWqjA8/HVjCw==" - }, "node_modules/@types/prismjs": { "version": "1.26.5", "resolved": "https://registry.npmjs.org/@types/prismjs/-/prismjs-1.26.5.tgz", @@ -4762,32 +4786,32 @@ } }, "node_modules/algoliasearch": { - "version": "5.20.3", - "resolved": "https://registry.npmjs.org/algoliasearch/-/algoliasearch-5.20.3.tgz", - "integrity": "sha512-iNC6BGvipaalFfDfDnXUje8GUlW5asj0cTMsZJwO/0rhsyLx1L7GZFAY8wW+eQ6AM4Yge2p5GSE5hrBlfSD90Q==", - "dependencies": { - "@algolia/client-abtesting": "5.20.3", - "@algolia/client-analytics": "5.20.3", - "@algolia/client-common": "5.20.3", - "@algolia/client-insights": "5.20.3", - "@algolia/client-personalization": "5.20.3", - "@algolia/client-query-suggestions": "5.20.3", - "@algolia/client-search": "5.20.3", - "@algolia/ingestion": "1.20.3", - "@algolia/monitoring": "1.20.3", - "@algolia/recommend": "5.20.3", - "@algolia/requester-browser-xhr": "5.20.3", - "@algolia/requester-fetch": "5.20.3", - "@algolia/requester-node-http": "5.20.3" + "version": "5.33.0", + "resolved": "https://registry.npmjs.org/algoliasearch/-/algoliasearch-5.33.0.tgz", + "integrity": "sha512-WdgSkmyTec5n2W2FA2/7Q7TCSajCV0X6w57u3H5GHnw0UCp/G5xb33/Jx1FX3uMtz17P3wGEzMCP82d0LJqMow==", + "dependencies": { + "@algolia/client-abtesting": "5.33.0", + "@algolia/client-analytics": "5.33.0", + "@algolia/client-common": "5.33.0", + "@algolia/client-insights": "5.33.0", + "@algolia/client-personalization": "5.33.0", + "@algolia/client-query-suggestions": "5.33.0", + "@algolia/client-search": "5.33.0", + "@algolia/ingestion": "1.33.0", + "@algolia/monitoring": "1.33.0", + "@algolia/recommend": "5.33.0", + "@algolia/requester-browser-xhr": "5.33.0", + "@algolia/requester-fetch": "5.33.0", + "@algolia/requester-node-http": "5.33.0" }, "engines": { "node": ">= 14.0.0" } }, "node_modules/algoliasearch-helper": { - "version": "3.24.1", - "resolved": "https://registry.npmjs.org/algoliasearch-helper/-/algoliasearch-helper-3.24.1.tgz", - "integrity": "sha512-knYRACqLH9UpeR+WRUrBzBFR2ulGuOjI2b525k4PNeqZxeFMHJE7YcL7s6Jh12Qza0rtHqZdgHMfeuaaAkf4wA==", + "version": "3.26.0", + "resolved": "https://registry.npmjs.org/algoliasearch-helper/-/algoliasearch-helper-3.26.0.tgz", + "integrity": "sha512-Rv2x3GXleQ3ygwhkhJubhhYGsICmShLAiqtUuJTUkr9uOCOXyF2E71LVT4XDnVffbknv8XgScP4U0Oxtgm+hIw==", "dependencies": { "@algolia/events": "^4.0.1" }, @@ -4922,18 +4946,10 @@ "astring": "bin/astring" } }, - "node_modules/at-least-node": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/at-least-node/-/at-least-node-1.0.0.tgz", - "integrity": "sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg==", - "engines": { - "node": ">= 4.0.0" - } - }, "node_modules/autoprefixer": { - "version": "10.4.20", - "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.20.tgz", - "integrity": "sha512-XY25y5xSv/wEoqzDyXXME4AFfkZI0P23z6Fs3YgymDnKJkCGOnkL0iTxCa85UTqaSgfcqyf3UA6+c7wUvx/16g==", + "version": "10.4.21", + "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.21.tgz", + "integrity": "sha512-O+A6LWV5LDHSJD3LjHYoNi4VLsj/Whi7k6zG12xTYaU4cQ8oxQGckXNX8cRHK5yOZ/ppVHe0ZBXGzSV9jXdVbQ==", "funding": [ { "type": "opencollective", @@ -4949,11 +4965,11 @@ } ], "dependencies": { - "browserslist": "^4.23.3", - "caniuse-lite": "^1.0.30001646", + "browserslist": "^4.24.4", + "caniuse-lite": "^1.0.30001702", "fraction.js": "^4.3.7", "normalize-range": "^0.1.2", - "picocolors": "^1.0.1", + "picocolors": "^1.1.1", "postcss-value-parser": "^4.2.0" }, "bin": { @@ -4991,12 +5007,12 @@ } }, "node_modules/babel-plugin-polyfill-corejs2": { - "version": "0.4.12", - "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.4.12.tgz", - "integrity": "sha512-CPWT6BwvhrTO2d8QVorhTCQw9Y43zOu7G9HigcfxvepOU6b8o3tcWad6oVgZIsZCTt42FFv97aA7ZJsbM4+8og==", + "version": "0.4.14", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.4.14.tgz", + "integrity": "sha512-Co2Y9wX854ts6U8gAAPXfn0GmAyctHuK8n0Yhfjd6t30g7yvKjspvvOo9yG+z52PZRgFErt7Ka2pYnXCjLKEpg==", "dependencies": { - "@babel/compat-data": "^7.22.6", - "@babel/helper-define-polyfill-provider": "^0.6.3", + "@babel/compat-data": "^7.27.7", + "@babel/helper-define-polyfill-provider": "^0.6.5", "semver": "^6.3.1" }, "peerDependencies": { @@ -5012,23 +5028,23 @@ } }, "node_modules/babel-plugin-polyfill-corejs3": { - "version": "0.10.6", - "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.10.6.tgz", - "integrity": "sha512-b37+KR2i/khY5sKmWNVQAnitvquQbNdWy6lJdsr0kmquCKEEUgMKK4SboVM3HtfnZilfjr4MMQ7vY58FVWDtIA==", + "version": "0.13.0", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.13.0.tgz", + "integrity": "sha512-U+GNwMdSFgzVmfhNm8GJUX88AadB3uo9KpJqS3FaqNIPKgySuvMb+bHPsOmmuWyIcuqZj/pzt1RUIUZns4y2+A==", "dependencies": { - "@babel/helper-define-polyfill-provider": "^0.6.2", - "core-js-compat": "^3.38.0" + "@babel/helper-define-polyfill-provider": "^0.6.5", + "core-js-compat": "^3.43.0" }, "peerDependencies": { "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" } }, "node_modules/babel-plugin-polyfill-regenerator": { - "version": "0.6.3", - "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.6.3.tgz", - "integrity": "sha512-LiWSbl4CRSIa5x/JAU6jZiG9eit9w6mz+yVMFwDE83LAWvt0AfGBoZ7HS/mkhrKuh2ZlzfVZYKoLjXdqw6Yt7Q==", + "version": "0.6.5", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.6.5.tgz", + "integrity": "sha512-ISqQ2frbiNU9vIJkzg7dlPpznPZ4jOiUQ1uSmB0fEHeowtN3COYRsXr/xexn64NpU13P06jc/L5TgiJXOgrbEg==", "dependencies": { - "@babel/helper-define-polyfill-provider": "^0.6.3" + "@babel/helper-define-polyfill-provider": "^0.6.5" }, "peerDependencies": { "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" @@ -5172,9 +5188,9 @@ } }, "node_modules/browserslist": { - "version": "4.24.4", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.24.4.tgz", - "integrity": "sha512-KDi1Ny1gSePi1vm0q4oxSF8b4DR44GF4BbmS2YdhPLOEqd8pDviZOGH/GsmRwoWJ2+5Lr085X7naowMwKHDG1A==", + "version": "4.25.1", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.25.1.tgz", + "integrity": "sha512-KGj0KoOMXLpSNkkEI6Z6mShmQy0bc1I+T7K9N81k4WWMrfz+6fQ6es80B/YLAeRoKvjYE1YSHHOW1qe9xIVzHw==", "funding": [ { "type": "opencollective", @@ -5190,10 +5206,10 @@ } ], "dependencies": { - "caniuse-lite": "^1.0.30001688", - "electron-to-chromium": "^1.5.73", + "caniuse-lite": "^1.0.30001726", + "electron-to-chromium": "^1.5.173", "node-releases": "^2.0.19", - "update-browserslist-db": "^1.1.1" + "update-browserslist-db": "^1.1.3" }, "bin": { "browserslist": "cli.js" @@ -5324,9 +5340,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001700", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001700.tgz", - "integrity": "sha512-2S6XIXwaE7K7erT8dY+kLQcpa5ms63XlRkMkReXjle+kf6c5g38vyMl+Z5y8dSxOFDhcFe+nxnn261PLxBSQsQ==", + "version": "1.0.30001727", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001727.tgz", + "integrity": "sha512-pB68nIHmbN6L/4C6MH1DokyR3bYqFwjaSs/sWDHGj4CTcFtQUQMuJftVwWkXq7mNWOybD3KhUv3oWHoGxgP14Q==", "funding": [ { "type": "opencollective", @@ -5745,9 +5761,9 @@ } }, "node_modules/consola": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/consola/-/consola-3.4.0.tgz", - "integrity": "sha512-EiPU8G6dQG0GFHNR8ljnZFki/8a+cQwEQ+7wpxdChl02Q8HXlwEZWD5lqAF8vC2sEC3Tehr8hy7vErz88LHyUA==", + "version": "3.4.2", + "resolved": "https://registry.npmjs.org/consola/-/consola-3.4.2.tgz", + "integrity": "sha512-5IKcdX0nnYavi6G7TtOhwkYzyjfJlatbjMjuLSfE2kYT5pMDOilZ4OvMhi637CcDICTmz3wARPoyhqyX1Y+XvA==", "engines": { "node": "^14.18.0 || >=16.10.0" } @@ -5871,11 +5887,11 @@ } }, "node_modules/core-js-compat": { - "version": "3.40.0", - "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.40.0.tgz", - "integrity": "sha512-0XEDpr5y5mijvw8Lbc6E5AkjrHfp7eEoPlu36SWeAbcL8fn1G1ANe8DBlo2XoNN89oVpxWwOjYIPVzR4ZvsKCQ==", + "version": "3.44.0", + "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.44.0.tgz", + "integrity": "sha512-JepmAj2zfl6ogy34qfWtcE7nHKAJnKsQFRn++scjVS2bZFllwptzw61BZcZFYBPpUznLfAvh0LGhxKppk04ClA==", "dependencies": { - "browserslist": "^4.24.3" + "browserslist": "^4.25.1" }, "funding": { "type": "opencollective", @@ -5883,9 +5899,9 @@ } }, "node_modules/core-js-pure": { - "version": "3.40.0", - "resolved": "https://registry.npmjs.org/core-js-pure/-/core-js-pure-3.40.0.tgz", - "integrity": "sha512-AtDzVIgRrmRKQai62yuSIN5vNiQjcJakJb4fbhVw3ehxx7Lohphvw9SGNWKhLFqSxC4ilD0g/L1huAYFQU3Q6A==", + "version": "3.44.0", + "resolved": "https://registry.npmjs.org/core-js-pure/-/core-js-pure-3.44.0.tgz", + "integrity": "sha512-gvMQAGB4dfVUxpYD0k3Fq8J+n5bB6Ytl15lqlZrOIXFzxOhtPaObfkQGHtMRdyjIf7z2IeNULwi1jEwyS+ltKQ==", "hasInstallScript": true, "funding": { "type": "opencollective", @@ -6203,9 +6219,9 @@ } }, "node_modules/cssdb": { - "version": "8.2.3", - "resolved": "https://registry.npmjs.org/cssdb/-/cssdb-8.2.3.tgz", - "integrity": "sha512-9BDG5XmJrJQQnJ51VFxXCAtpZ5ebDlAREmO8sxMOVU0aSxN/gocbctjIG5LMh3WBUq+xTlb/jw2LoljBEqraTA==", + "version": "8.3.1", + "resolved": "https://registry.npmjs.org/cssdb/-/cssdb-8.3.1.tgz", + "integrity": "sha512-XnDRQMXucLueX92yDe0LPKupXetWoFOgawr4O4X41l5TltgK2NVbJJVDnnOywDYfW1sTJ28AcXGKOqdRKwCcmQ==", "funding": [ { "type": "opencollective", @@ -6362,9 +6378,9 @@ "integrity": "sha512-XRRe6Glud4rd/ZGQfiV1ruXSfbvfJedlV9Y6zOlP+2K04vBYiJEte6stfFkCP03aMnY5tsipamumUjL14fofug==" }, "node_modules/debug": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz", - "integrity": "sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==", + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.1.tgz", + "integrity": "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==", "dependencies": { "ms": "^2.1.3" }, @@ -6489,27 +6505,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/del": { - "version": "6.1.1", - "resolved": "https://registry.npmjs.org/del/-/del-6.1.1.tgz", - "integrity": "sha512-ua8BhapfP0JUJKC/zV9yHHDW/rDoDxP4Zhn3AkA6/xT6gY7jYXJiaeyBZznYVujhZZET+UgcbZiQ7sN3WqcImg==", - "dependencies": { - "globby": "^11.0.1", - "graceful-fs": "^4.2.4", - "is-glob": "^4.0.1", - "is-path-cwd": "^2.2.0", - "is-path-inside": "^3.0.2", - "p-map": "^4.0.0", - "rimraf": "^3.0.2", - "slash": "^3.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/depd": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", @@ -6556,35 +6551,6 @@ "node": ">= 4.0.0" } }, - "node_modules/detect-port-alt": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/detect-port-alt/-/detect-port-alt-1.1.6.tgz", - "integrity": "sha512-5tQykt+LqfJFBEYaDITx7S7cR7mJ/zQmLXZ2qt5w04ainYZw6tBf9dBunMjVeVOdYVRUzUOE4HkY5J7+uttb5Q==", - "dependencies": { - "address": "^1.0.1", - "debug": "^2.6.0" - }, - "bin": { - "detect": "bin/detect-port", - "detect-port": "bin/detect-port" - }, - "engines": { - "node": ">= 4.2.1" - } - }, - "node_modules/detect-port-alt/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/detect-port-alt/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" - }, "node_modules/devlop": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/devlop/-/devlop-1.1.0.tgz", @@ -6738,9 +6704,9 @@ "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==" }, "node_modules/electron-to-chromium": { - "version": "1.5.102", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.102.tgz", - "integrity": "sha512-eHhqaja8tE/FNpIiBrvBjFV/SSKpyWHLvxuR9dPTdo+3V9ppdLmFB7ZZQ98qNovcngPLYIz0oOBF9P0FfZef5Q==" + "version": "1.5.185", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.185.tgz", + "integrity": "sha512-dYOZfUk57hSMPePoIQ1fZWl1Fkj+OshhEVuPacNKWzC1efe56OsHY3l/jCfiAgIICOU3VgOIdoq7ahg7r7n6MQ==" }, "node_modules/emoji-regex": { "version": "9.2.2", @@ -7391,14 +7357,6 @@ "url": "https://opencollective.com/webpack" } }, - "node_modules/filesize": { - "version": "8.0.7", - "resolved": "https://registry.npmjs.org/filesize/-/filesize-8.0.7.tgz", - "integrity": "sha512-pjmC+bkIF8XI7fWaH8KxHcZL3DPybs1roSKP4rKDvy20tAWwIObE4+JIseG2byfGKhud5ZnM4YSGKBz7Sh0ndQ==", - "engines": { - "node": ">= 0.4.0" - } - }, "node_modules/fill-range": { "version": "7.1.1", "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", @@ -7497,126 +7455,6 @@ } } }, - "node_modules/fork-ts-checker-webpack-plugin": { - "version": "6.5.3", - "resolved": "https://registry.npmjs.org/fork-ts-checker-webpack-plugin/-/fork-ts-checker-webpack-plugin-6.5.3.tgz", - "integrity": "sha512-SbH/l9ikmMWycd5puHJKTkZJKddF4iRLyW3DeZ08HTI7NGyLS38MXd/KGgeWumQO7YNQbW2u/NtPT2YowbPaGQ==", - "dependencies": { - "@babel/code-frame": "^7.8.3", - "@types/json-schema": "^7.0.5", - "chalk": "^4.1.0", - "chokidar": "^3.4.2", - "cosmiconfig": "^6.0.0", - "deepmerge": "^4.2.2", - "fs-extra": "^9.0.0", - "glob": "^7.1.6", - "memfs": "^3.1.2", - "minimatch": "^3.0.4", - "schema-utils": "2.7.0", - "semver": "^7.3.2", - "tapable": "^1.0.0" - }, - "engines": { - "node": ">=10", - "yarn": ">=1.0.0" - }, - "peerDependencies": { - "eslint": ">= 6", - "typescript": ">= 2.7", - "vue-template-compiler": "*", - "webpack": ">= 4" - }, - "peerDependenciesMeta": { - "eslint": { - "optional": true - }, - "vue-template-compiler": { - "optional": true - } - } - }, - "node_modules/fork-ts-checker-webpack-plugin/node_modules/ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", - "dependencies": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" - } - }, - "node_modules/fork-ts-checker-webpack-plugin/node_modules/ajv-keywords": { - "version": "3.5.2", - "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", - "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", - "peerDependencies": { - "ajv": "^6.9.1" - } - }, - "node_modules/fork-ts-checker-webpack-plugin/node_modules/cosmiconfig": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-6.0.0.tgz", - "integrity": "sha512-xb3ZL6+L8b9JLLCx3ZdoZy4+2ECphCMo2PwqgP1tlfVq6M6YReyzBJtvWWtbDSpNr9hn96pkCiZqUcFEc+54Qg==", - "dependencies": { - "@types/parse-json": "^4.0.0", - "import-fresh": "^3.1.0", - "parse-json": "^5.0.0", - "path-type": "^4.0.0", - "yaml": "^1.7.2" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/fork-ts-checker-webpack-plugin/node_modules/fs-extra": { - "version": "9.1.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", - "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", - "dependencies": { - "at-least-node": "^1.0.0", - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^2.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/fork-ts-checker-webpack-plugin/node_modules/json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==" - }, - "node_modules/fork-ts-checker-webpack-plugin/node_modules/schema-utils": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-2.7.0.tgz", - "integrity": "sha512-0ilKFI6QQF5nxDZLFn2dMjvc4hjg/Wkg7rHd3jK6/A4a1Hl9VFdQWvgB1UMGoU94pad1P/8N7fMcEnLnSiju8A==", - "dependencies": { - "@types/json-schema": "^7.0.4", - "ajv": "^6.12.2", - "ajv-keywords": "^3.4.1" - }, - "engines": { - "node": ">= 8.9.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - } - }, - "node_modules/fork-ts-checker-webpack-plugin/node_modules/tapable": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/tapable/-/tapable-1.1.3.tgz", - "integrity": "sha512-4WK/bYZmj8xLr+HUCODHGF1ZFzsYffasLUgEiMBY4fgtltdO6B4WJtlSbPaDTLpYTcGVwM2qLnFTICEcNxs3kA==", - "engines": { - "node": ">=6" - } - }, "node_modules/form-data-encoder": { "version": "2.1.4", "resolved": "https://registry.npmjs.org/form-data-encoder/-/form-data-encoder-2.1.4.tgz", @@ -7827,41 +7665,6 @@ "node": ">=10" } }, - "node_modules/global-modules": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/global-modules/-/global-modules-2.0.0.tgz", - "integrity": "sha512-NGbfmJBp9x8IxyJSd1P+otYK8vonoJactOogrVfFRIAEY1ukil8RSKDz2Yo7wh1oihl51l/r6W4epkeKJHqL8A==", - "dependencies": { - "global-prefix": "^3.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/global-prefix": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/global-prefix/-/global-prefix-3.0.0.tgz", - "integrity": "sha512-awConJSVCHVGND6x3tmMaKcQvwXLhjdkmomy2W+Goaui8YPgYgXJZewhg3fWC+DlfqqQuWg8AwqjGTD2nAPVWg==", - "dependencies": { - "ini": "^1.3.5", - "kind-of": "^6.0.2", - "which": "^1.3.1" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/global-prefix/node_modules/which": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", - "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", - "dependencies": { - "isexe": "^2.0.0" - }, - "bin": { - "which": "bin/which" - } - }, "node_modules/globals": { "version": "11.12.0", "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", @@ -8553,12 +8356,9 @@ } }, "node_modules/image-size": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/image-size/-/image-size-1.2.0.tgz", - "integrity": "sha512-4S8fwbO6w3GeCVN6OPtA9I5IGKkcDMPcKndtUlpJuCwu7JLjtj7JZpwqLuyY2nrmQT3AWsCJLSKPsc2mPBSl3w==", - "dependencies": { - "queue": "6.0.2" - }, + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/image-size/-/image-size-2.0.2.tgz", + "integrity": "sha512-IRqXKlaXwgSMAMtpNzZa1ZAe8m+Sa1770Dhk8VkSsP9LS+iHD62Zd8FQKs8fbPiagBE7BzoFX23cxFnwshpV6w==", "bin": { "image-size": "bin/image-size.js" }, @@ -8566,15 +8366,6 @@ "node": ">=16.x" } }, - "node_modules/immer": { - "version": "9.0.21", - "resolved": "https://registry.npmjs.org/immer/-/immer-9.0.21.tgz", - "integrity": "sha512-bc4NBHqOqSfRW7POMkHd51LvClaeMXpm8dx0e8oE2GORbq5aRK7Bxl4FyzVLdGtLmvLKL7BTDBG5ACQm4HWjTA==", - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/immer" - } - }, "node_modules/import-fresh": { "version": "3.3.1", "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.1.tgz", @@ -8647,14 +8438,6 @@ "resolved": "https://registry.npmjs.org/inline-style-parser/-/inline-style-parser-0.2.4.tgz", "integrity": "sha512-0aO8FkhNZlj/ZIbNi7Lxxr12obT7cL1moPfE4tg1LkX7LlLfC6DeX4l2ZEud1ukP9jNQyNnfzQVqwbwmAATY4Q==" }, - "node_modules/interpret": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/interpret/-/interpret-1.4.0.tgz", - "integrity": "sha512-agE4QfB2Lkp9uICn7BAqoscw4SZP9kTE2hxiFI3jBPmXJfdqiahTbUuKGsMoN2GtqL9AxhYioAcVvgsb1HvRbA==", - "engines": { - "node": ">= 0.10" - } - }, "node_modules/invariant": { "version": "2.2.4", "resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz", @@ -8843,14 +8626,6 @@ "node": ">=0.10.0" } }, - "node_modules/is-path-cwd": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/is-path-cwd/-/is-path-cwd-2.2.0.tgz", - "integrity": "sha512-w942bTcih8fdJPJmQHFzkS76NEP8Kzzvmw92cXsazb8intwLqPibPPdXf4ANdKV3rYMuuQYGIWtvz9JilB3NFQ==", - "engines": { - "node": ">=6" - } - }, "node_modules/is-path-inside": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", @@ -8889,14 +8664,6 @@ "node": ">=0.10.0" } }, - "node_modules/is-root": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-root/-/is-root-2.1.0.tgz", - "integrity": "sha512-AGOriNp96vNBd3HtU+RzFEc75FfR5ymiYv8E553I71SCeXBiMsVDUtdio1OEFvrPyLIQ9tVR5RxXIFe5PUFjMg==", - "engines": { - "node": ">=6" - } - }, "node_modules/is-stream": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", @@ -11533,9 +11300,9 @@ } }, "node_modules/nanoid": { - "version": "3.3.8", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.8.tgz", - "integrity": "sha512-WNLf5Sd8oZxOm+TzppcYk8gVOgP+l58xNy58D0nbUnOxOWRWvlcCV4kUF7ltmI6PsrLl/BgKEyS4mqsGChFN0w==", + "version": "3.3.11", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz", + "integrity": "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==", "funding": [ { "type": "github", @@ -11840,6 +11607,14 @@ "node": ">=12.20" } }, + "node_modules/p-finally": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz", + "integrity": "sha512-LICb2p9CB7FS+0eR1oqWnHhp0FljGLZCWBE9aix0Uye9W8LTQPwMTYVGWQWIw9RdQiDg4+epXQODwIYJtSJaow==", + "engines": { + "node": ">=4" + } + }, "node_modules/p-limit": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-4.0.0.tgz", @@ -11882,6 +11657,21 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/p-queue": { + "version": "6.6.2", + "resolved": "https://registry.npmjs.org/p-queue/-/p-queue-6.6.2.tgz", + "integrity": "sha512-RwFpb72c/BhQLEXIZ5K2e+AhgNVmIejGlTgiB9MzZ0e93GRvqZ7uSi0dvRF7/XIXDeNkra2fNHBxTyPDGySpjQ==", + "dependencies": { + "eventemitter3": "^4.0.4", + "p-timeout": "^3.2.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/p-retry": { "version": "4.6.2", "resolved": "https://registry.npmjs.org/p-retry/-/p-retry-4.6.2.tgz", @@ -11894,12 +11684,15 @@ "node": ">=8" } }, - "node_modules/p-try": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", - "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", + "node_modules/p-timeout": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/p-timeout/-/p-timeout-3.2.0.tgz", + "integrity": "sha512-rhIwUycgwwKcP9yTOOFK/AKsAopjjCakVqLHePO3CC6Mir1Z99xT+R63jZxAT5lFZLa2inS5h+ZS2GvR99/FBg==", + "dependencies": { + "p-finally": "^1.0.0" + }, "engines": { - "node": ">=6" + "node": ">=8" } }, "node_modules/package-json": { @@ -12104,77 +11897,10 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/pkg-up": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/pkg-up/-/pkg-up-3.1.0.tgz", - "integrity": "sha512-nDywThFk1i4BQK4twPQ6TA4RT8bDY96yeuCVBWL3ePARCiEKDRSrNGbFIgUJpLp+XeIR65v8ra7WuJOFUBtkMA==", - "dependencies": { - "find-up": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/pkg-up/node_modules/find-up": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", - "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", - "dependencies": { - "locate-path": "^3.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/pkg-up/node_modules/locate-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", - "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", - "dependencies": { - "p-locate": "^3.0.0", - "path-exists": "^3.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/pkg-up/node_modules/p-limit": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", - "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", - "dependencies": { - "p-try": "^2.0.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/pkg-up/node_modules/p-locate": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", - "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", - "dependencies": { - "p-limit": "^2.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/pkg-up/node_modules/path-exists": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", - "integrity": "sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ==", - "engines": { - "node": ">=4" - } - }, "node_modules/postcss": { - "version": "8.5.3", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.3.tgz", - "integrity": "sha512-dle9A3yYxlBSrt8Fu+IpjGT8SY8hN0mlaA6GY8t0P5PjIOZemULz/E2Bnm/2dcUOena75OTNkHI76uZBNUUq3A==", + "version": "8.5.6", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.6.tgz", + "integrity": "sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==", "funding": [ { "type": "opencollective", @@ -12190,7 +11916,7 @@ } ], "dependencies": { - "nanoid": "^3.3.8", + "nanoid": "^3.3.11", "picocolors": "^1.1.1", "source-map-js": "^1.2.1" }, @@ -12264,9 +11990,9 @@ } }, "node_modules/postcss-color-functional-notation": { - "version": "7.0.7", - "resolved": "https://registry.npmjs.org/postcss-color-functional-notation/-/postcss-color-functional-notation-7.0.7.tgz", - "integrity": "sha512-EZvAHsvyASX63vXnyXOIynkxhaHRSsdb7z6yiXKIovGXAolW4cMZ3qoh7k3VdTsLBS6VGdksGfIo3r6+waLoOw==", + "version": "7.0.10", + "resolved": "https://registry.npmjs.org/postcss-color-functional-notation/-/postcss-color-functional-notation-7.0.10.tgz", + "integrity": "sha512-k9qX+aXHBiLTRrWoCJuUFI6F1iF6QJQUXNVWJVSbqZgj57jDhBlOvD8gNUGl35tgqDivbGLhZeW3Ongz4feuKA==", "funding": [ { "type": "github", @@ -12278,10 +12004,10 @@ } ], "dependencies": { - "@csstools/css-color-parser": "^3.0.7", - "@csstools/css-parser-algorithms": "^3.0.4", - "@csstools/css-tokenizer": "^3.0.3", - "@csstools/postcss-progressive-custom-properties": "^4.0.0", + "@csstools/css-color-parser": "^3.0.10", + "@csstools/css-parser-algorithms": "^3.0.5", + "@csstools/css-tokenizer": "^3.0.4", + "@csstools/postcss-progressive-custom-properties": "^4.1.0", "@csstools/utilities": "^2.0.0" }, "engines": { @@ -12374,9 +12100,9 @@ } }, "node_modules/postcss-custom-media": { - "version": "11.0.5", - "resolved": "https://registry.npmjs.org/postcss-custom-media/-/postcss-custom-media-11.0.5.tgz", - "integrity": "sha512-SQHhayVNgDvSAdX9NQ/ygcDQGEY+aSF4b/96z7QUX6mqL5yl/JgG/DywcF6fW9XbnCRE+aVYk+9/nqGuzOPWeQ==", + "version": "11.0.6", + "resolved": "https://registry.npmjs.org/postcss-custom-media/-/postcss-custom-media-11.0.6.tgz", + "integrity": "sha512-C4lD4b7mUIw+RZhtY7qUbf4eADmb7Ey8BFA2px9jUbwg7pjTZDl4KY4bvlUV+/vXQvzQRfiGEVJyAbtOsCMInw==", "funding": [ { "type": "github", @@ -12388,10 +12114,10 @@ } ], "dependencies": { - "@csstools/cascade-layer-name-parser": "^2.0.4", - "@csstools/css-parser-algorithms": "^3.0.4", - "@csstools/css-tokenizer": "^3.0.3", - "@csstools/media-query-list-parser": "^4.0.2" + "@csstools/cascade-layer-name-parser": "^2.0.5", + "@csstools/css-parser-algorithms": "^3.0.5", + "@csstools/css-tokenizer": "^3.0.4", + "@csstools/media-query-list-parser": "^4.0.3" }, "engines": { "node": ">=18" @@ -12401,9 +12127,9 @@ } }, "node_modules/postcss-custom-properties": { - "version": "14.0.4", - "resolved": "https://registry.npmjs.org/postcss-custom-properties/-/postcss-custom-properties-14.0.4.tgz", - "integrity": "sha512-QnW8FCCK6q+4ierwjnmXF9Y9KF8q0JkbgVfvQEMa93x1GT8FvOiUevWCN2YLaOWyByeDX8S6VFbZEeWoAoXs2A==", + "version": "14.0.6", + "resolved": "https://registry.npmjs.org/postcss-custom-properties/-/postcss-custom-properties-14.0.6.tgz", + "integrity": "sha512-fTYSp3xuk4BUeVhxCSJdIPhDLpJfNakZKoiTDx7yRGCdlZrSJR7mWKVOBS4sBF+5poPQFMj2YdXx1VHItBGihQ==", "funding": [ { "type": "github", @@ -12415,9 +12141,9 @@ } ], "dependencies": { - "@csstools/cascade-layer-name-parser": "^2.0.4", - "@csstools/css-parser-algorithms": "^3.0.4", - "@csstools/css-tokenizer": "^3.0.3", + "@csstools/cascade-layer-name-parser": "^2.0.5", + "@csstools/css-parser-algorithms": "^3.0.5", + "@csstools/css-tokenizer": "^3.0.4", "@csstools/utilities": "^2.0.0", "postcss-value-parser": "^4.2.0" }, @@ -12429,9 +12155,9 @@ } }, "node_modules/postcss-custom-selectors": { - "version": "8.0.4", - "resolved": "https://registry.npmjs.org/postcss-custom-selectors/-/postcss-custom-selectors-8.0.4.tgz", - "integrity": "sha512-ASOXqNvDCE0dAJ/5qixxPeL1aOVGHGW2JwSy7HyjWNbnWTQCl+fDc968HY1jCmZI0+BaYT5CxsOiUhavpG/7eg==", + "version": "8.0.5", + "resolved": "https://registry.npmjs.org/postcss-custom-selectors/-/postcss-custom-selectors-8.0.5.tgz", + "integrity": "sha512-9PGmckHQswiB2usSO6XMSswO2yFWVoCAuih1yl9FVcwkscLjRKjwsjM3t+NIWpSU2Jx3eOiK2+t4vVTQaoCHHg==", "funding": [ { "type": "github", @@ -12443,9 +12169,9 @@ } ], "dependencies": { - "@csstools/cascade-layer-name-parser": "^2.0.4", - "@csstools/css-parser-algorithms": "^3.0.4", - "@csstools/css-tokenizer": "^3.0.3", + "@csstools/cascade-layer-name-parser": "^2.0.5", + "@csstools/css-parser-algorithms": "^3.0.5", + "@csstools/css-tokenizer": "^3.0.4", "postcss-selector-parser": "^7.0.0" }, "engines": { @@ -12562,9 +12288,9 @@ } }, "node_modules/postcss-double-position-gradients": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/postcss-double-position-gradients/-/postcss-double-position-gradients-6.0.0.tgz", - "integrity": "sha512-JkIGah3RVbdSEIrcobqj4Gzq0h53GG4uqDPsho88SgY84WnpkTpI0k50MFK/sX7XqVisZ6OqUfFnoUO6m1WWdg==", + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/postcss-double-position-gradients/-/postcss-double-position-gradients-6.0.2.tgz", + "integrity": "sha512-7qTqnL7nfLRyJK/AHSVrrXOuvDDzettC+wGoienURV8v2svNbu6zJC52ruZtHaO6mfcagFmuTGFdzRsJKB3k5Q==", "funding": [ { "type": "github", @@ -12576,7 +12302,7 @@ } ], "dependencies": { - "@csstools/postcss-progressive-custom-properties": "^4.0.0", + "@csstools/postcss-progressive-custom-properties": "^4.1.0", "@csstools/utilities": "^2.0.0", "postcss-value-parser": "^4.2.0" }, @@ -12714,9 +12440,9 @@ } }, "node_modules/postcss-lab-function": { - "version": "7.0.7", - "resolved": "https://registry.npmjs.org/postcss-lab-function/-/postcss-lab-function-7.0.7.tgz", - "integrity": "sha512-+ONj2bpOQfsCKZE2T9VGMyVVdGcGUpr7u3SVfvkJlvhTRmDCfY25k4Jc8fubB9DclAPR4+w8uVtDZmdRgdAHig==", + "version": "7.0.10", + "resolved": "https://registry.npmjs.org/postcss-lab-function/-/postcss-lab-function-7.0.10.tgz", + "integrity": "sha512-tqs6TCEv9tC1Riq6fOzHuHcZyhg4k3gIAMB8GGY/zA1ssGdm6puHMVE7t75aOSoFg7UD2wyrFFhbldiCMyyFTQ==", "funding": [ { "type": "github", @@ -12728,10 +12454,10 @@ } ], "dependencies": { - "@csstools/css-color-parser": "^3.0.7", - "@csstools/css-parser-algorithms": "^3.0.4", - "@csstools/css-tokenizer": "^3.0.3", - "@csstools/postcss-progressive-custom-properties": "^4.0.0", + "@csstools/css-color-parser": "^3.0.10", + "@csstools/css-parser-algorithms": "^3.0.5", + "@csstools/css-tokenizer": "^3.0.4", + "@csstools/postcss-progressive-custom-properties": "^4.1.0", "@csstools/utilities": "^2.0.0" }, "engines": { @@ -12763,9 +12489,9 @@ } }, "node_modules/postcss-logical": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/postcss-logical/-/postcss-logical-8.0.0.tgz", - "integrity": "sha512-HpIdsdieClTjXLOyYdUPAX/XQASNIwdKt5hoZW08ZOAiI+tbV0ta1oclkpVkW5ANU+xJvk3KkA0FejkjGLXUkg==", + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/postcss-logical/-/postcss-logical-8.1.0.tgz", + "integrity": "sha512-pL1hXFQ2fEXNKiNiAgtfA005T9FBxky5zkX6s4GZM2D8RkVgRqz3f4g1JUoq925zXv495qk8UNldDwh8uGEDoA==", "funding": [ { "type": "github", @@ -12973,9 +12699,9 @@ } }, "node_modules/postcss-nesting": { - "version": "13.0.1", - "resolved": "https://registry.npmjs.org/postcss-nesting/-/postcss-nesting-13.0.1.tgz", - "integrity": "sha512-VbqqHkOBOt4Uu3G8Dm8n6lU5+9cJFxiuty9+4rcoyRPO9zZS1JIs6td49VIoix3qYqELHlJIn46Oih9SAKo+yQ==", + "version": "13.0.2", + "resolved": "https://registry.npmjs.org/postcss-nesting/-/postcss-nesting-13.0.2.tgz", + "integrity": "sha512-1YCI290TX+VP0U/K/aFxzHzQWHWURL+CtHMSbex1lCdpXD1SoR2sYuxDu5aNI9lPoXpKTCggFZiDJbwylU0LEQ==", "funding": [ { "type": "github", @@ -12987,7 +12713,7 @@ } ], "dependencies": { - "@csstools/selector-resolve-nested": "^3.0.0", + "@csstools/selector-resolve-nested": "^3.1.0", "@csstools/selector-specificity": "^5.0.0", "postcss-selector-parser": "^7.0.0" }, @@ -12999,9 +12725,9 @@ } }, "node_modules/postcss-nesting/node_modules/@csstools/selector-resolve-nested": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@csstools/selector-resolve-nested/-/selector-resolve-nested-3.0.0.tgz", - "integrity": "sha512-ZoK24Yku6VJU1gS79a5PFmC8yn3wIapiKmPgun0hZgEI5AOqgH2kiPRsPz1qkGv4HL+wuDLH83yQyk6inMYrJQ==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@csstools/selector-resolve-nested/-/selector-resolve-nested-3.1.0.tgz", + "integrity": "sha512-mf1LEW0tJLKfWyvn5KdDrhpxHyuxpbNwTIwOYLIvsTffeyOf85j5oIzfG0yosxDgx/sswlqBnESYUcQH0vgZ0g==", "funding": [ { "type": "github", @@ -13269,9 +12995,9 @@ } }, "node_modules/postcss-preset-env": { - "version": "10.1.4", - "resolved": "https://registry.npmjs.org/postcss-preset-env/-/postcss-preset-env-10.1.4.tgz", - "integrity": "sha512-awWKS3CwyY7I4Eb3YSWOZisbj3qXyuQCrylYiu2vSHxnSZAj3LHStN6jOcpCrc6EjYunLwbeNto3M5/JBtXpzg==", + "version": "10.2.4", + "resolved": "https://registry.npmjs.org/postcss-preset-env/-/postcss-preset-env-10.2.4.tgz", + "integrity": "sha512-q+lXgqmTMdB0Ty+EQ31SuodhdfZetUlwCA/F0zRcd/XdxjzI+Rl2JhZNz5US2n/7t9ePsvuhCnEN4Bmu86zXlA==", "funding": [ { "type": "github", @@ -13283,62 +13009,63 @@ } ], "dependencies": { - "@csstools/postcss-cascade-layers": "^5.0.1", - "@csstools/postcss-color-function": "^4.0.7", - "@csstools/postcss-color-mix-function": "^3.0.7", - "@csstools/postcss-content-alt-text": "^2.0.4", - "@csstools/postcss-exponential-functions": "^2.0.6", + "@csstools/postcss-cascade-layers": "^5.0.2", + "@csstools/postcss-color-function": "^4.0.10", + "@csstools/postcss-color-mix-function": "^3.0.10", + "@csstools/postcss-color-mix-variadic-function-arguments": "^1.0.0", + "@csstools/postcss-content-alt-text": "^2.0.6", + "@csstools/postcss-exponential-functions": "^2.0.9", "@csstools/postcss-font-format-keywords": "^4.0.0", - "@csstools/postcss-gamut-mapping": "^2.0.7", - "@csstools/postcss-gradients-interpolation-method": "^5.0.7", - "@csstools/postcss-hwb-function": "^4.0.7", - "@csstools/postcss-ic-unit": "^4.0.0", + "@csstools/postcss-gamut-mapping": "^2.0.10", + "@csstools/postcss-gradients-interpolation-method": "^5.0.10", + "@csstools/postcss-hwb-function": "^4.0.10", + "@csstools/postcss-ic-unit": "^4.0.2", "@csstools/postcss-initial": "^2.0.1", - "@csstools/postcss-is-pseudo-class": "^5.0.1", - "@csstools/postcss-light-dark-function": "^2.0.7", + "@csstools/postcss-is-pseudo-class": "^5.0.3", + "@csstools/postcss-light-dark-function": "^2.0.9", "@csstools/postcss-logical-float-and-clear": "^3.0.0", "@csstools/postcss-logical-overflow": "^2.0.0", "@csstools/postcss-logical-overscroll-behavior": "^2.0.0", "@csstools/postcss-logical-resize": "^3.0.0", - "@csstools/postcss-logical-viewport-units": "^3.0.3", - "@csstools/postcss-media-minmax": "^2.0.6", - "@csstools/postcss-media-queries-aspect-ratio-number-values": "^3.0.4", + "@csstools/postcss-logical-viewport-units": "^3.0.4", + "@csstools/postcss-media-minmax": "^2.0.9", + "@csstools/postcss-media-queries-aspect-ratio-number-values": "^3.0.5", "@csstools/postcss-nested-calc": "^4.0.0", "@csstools/postcss-normalize-display-values": "^4.0.0", - "@csstools/postcss-oklab-function": "^4.0.7", - "@csstools/postcss-progressive-custom-properties": "^4.0.0", - "@csstools/postcss-random-function": "^1.0.2", - "@csstools/postcss-relative-color-syntax": "^3.0.7", + "@csstools/postcss-oklab-function": "^4.0.10", + "@csstools/postcss-progressive-custom-properties": "^4.1.0", + "@csstools/postcss-random-function": "^2.0.1", + "@csstools/postcss-relative-color-syntax": "^3.0.10", "@csstools/postcss-scope-pseudo-class": "^4.0.1", - "@csstools/postcss-sign-functions": "^1.1.1", - "@csstools/postcss-stepped-value-functions": "^4.0.6", - "@csstools/postcss-text-decoration-shorthand": "^4.0.1", - "@csstools/postcss-trigonometric-functions": "^4.0.6", + "@csstools/postcss-sign-functions": "^1.1.4", + "@csstools/postcss-stepped-value-functions": "^4.0.9", + "@csstools/postcss-text-decoration-shorthand": "^4.0.2", + "@csstools/postcss-trigonometric-functions": "^4.0.9", "@csstools/postcss-unset-value": "^4.0.0", - "autoprefixer": "^10.4.19", - "browserslist": "^4.24.4", + "autoprefixer": "^10.4.21", + "browserslist": "^4.25.0", "css-blank-pseudo": "^7.0.1", "css-has-pseudo": "^7.0.2", "css-prefers-color-scheme": "^10.0.0", - "cssdb": "^8.2.3", + "cssdb": "^8.3.0", "postcss-attribute-case-insensitive": "^7.0.1", "postcss-clamp": "^4.1.0", - "postcss-color-functional-notation": "^7.0.7", + "postcss-color-functional-notation": "^7.0.10", "postcss-color-hex-alpha": "^10.0.0", "postcss-color-rebeccapurple": "^10.0.0", - "postcss-custom-media": "^11.0.5", - "postcss-custom-properties": "^14.0.4", - "postcss-custom-selectors": "^8.0.4", + "postcss-custom-media": "^11.0.6", + "postcss-custom-properties": "^14.0.6", + "postcss-custom-selectors": "^8.0.5", "postcss-dir-pseudo-class": "^9.0.1", - "postcss-double-position-gradients": "^6.0.0", + "postcss-double-position-gradients": "^6.0.2", "postcss-focus-visible": "^10.0.1", "postcss-focus-within": "^9.0.1", "postcss-font-variant": "^5.0.0", "postcss-gap-properties": "^6.0.0", "postcss-image-set-function": "^7.0.0", - "postcss-lab-function": "^7.0.7", - "postcss-logical": "^8.0.0", - "postcss-nesting": "^13.0.1", + "postcss-lab-function": "^7.0.10", + "postcss-logical": "^8.1.0", + "postcss-nesting": "^13.0.2", "postcss-opacity-percentage": "^3.0.0", "postcss-overflow-shorthand": "^6.0.0", "postcss-page-break": "^3.0.4", @@ -13578,9 +13305,9 @@ } }, "node_modules/prismjs": { - "version": "1.29.0", - "resolved": "https://registry.npmjs.org/prismjs/-/prismjs-1.29.0.tgz", - "integrity": "sha512-Kx/1w86q/epKcmte75LNrEoT+lX8pBpavuAbvJWRXar7Hz8jrtF+e3vY751p0R8H9HdArwaCTNDDzHg/ScJK1Q==", + "version": "1.30.0", + "resolved": "https://registry.npmjs.org/prismjs/-/prismjs-1.30.0.tgz", + "integrity": "sha512-DEvV2ZF2r2/63V+tK8hQvrR2ZGn10srHbXviTlcv7Kpzw8jWiNTqbVgjO3IY8RxrrOUF8VPMQQFysYYYv0YZxw==", "engines": { "node": ">=6" } @@ -13682,14 +13409,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/queue": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/queue/-/queue-6.0.2.tgz", - "integrity": "sha512-iHZWu+q3IdFZFX36ro/lKBkSvfkztY5Y7HMiPlOUjhupPcG2JMfst2KKEpu5XndviX/3UhFbRngUPNKtgvtZiA==", - "dependencies": { - "inherits": "~2.0.3" - } - }, "node_modules/queue-microtask": { "version": "1.2.3", "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", @@ -13788,124 +13507,6 @@ "node": ">=0.10.0" } }, - "node_modules/react-dev-utils": { - "version": "12.0.1", - "resolved": "https://registry.npmjs.org/react-dev-utils/-/react-dev-utils-12.0.1.tgz", - "integrity": "sha512-84Ivxmr17KjUupyqzFode6xKhjwuEJDROWKJy/BthkL7Wn6NJ8h4WE6k/exAv6ImS+0oZLRRW5j/aINMHyeGeQ==", - "dependencies": { - "@babel/code-frame": "^7.16.0", - "address": "^1.1.2", - "browserslist": "^4.18.1", - "chalk": "^4.1.2", - "cross-spawn": "^7.0.3", - "detect-port-alt": "^1.1.6", - "escape-string-regexp": "^4.0.0", - "filesize": "^8.0.6", - "find-up": "^5.0.0", - "fork-ts-checker-webpack-plugin": "^6.5.0", - "global-modules": "^2.0.0", - "globby": "^11.0.4", - "gzip-size": "^6.0.0", - "immer": "^9.0.7", - "is-root": "^2.1.0", - "loader-utils": "^3.2.0", - "open": "^8.4.0", - "pkg-up": "^3.1.0", - "prompts": "^2.4.2", - "react-error-overlay": "^6.0.11", - "recursive-readdir": "^2.2.2", - "shell-quote": "^1.7.3", - "strip-ansi": "^6.0.1", - "text-table": "^0.2.0" - }, - "engines": { - "node": ">=14" - } - }, - "node_modules/react-dev-utils/node_modules/find-up": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", - "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", - "dependencies": { - "locate-path": "^6.0.0", - "path-exists": "^4.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/react-dev-utils/node_modules/loader-utils": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-3.3.1.tgz", - "integrity": "sha512-FMJTLMXfCLMLfJxcX9PFqX5qD88Z5MRGaZCVzfuqeZSPsyiBzs+pahDQjbIWz2QIzPZz0NX9Zy4FX3lmK6YHIg==", - "engines": { - "node": ">= 12.13.0" - } - }, - "node_modules/react-dev-utils/node_modules/locate-path": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", - "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", - "dependencies": { - "p-locate": "^5.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/react-dev-utils/node_modules/p-limit": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", - "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", - "dependencies": { - "yocto-queue": "^0.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/react-dev-utils/node_modules/p-locate": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", - "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", - "dependencies": { - "p-limit": "^3.0.2" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/react-dev-utils/node_modules/path-exists": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", - "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", - "engines": { - "node": ">=8" - } - }, - "node_modules/react-dev-utils/node_modules/yocto-queue": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", - "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/react-dom": { "version": "19.0.0", "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.0.0.tgz", @@ -13917,11 +13518,6 @@ "react": "^19.0.0" } }, - "node_modules/react-error-overlay": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/react-error-overlay/-/react-error-overlay-6.1.0.tgz", - "integrity": "sha512-SN/U6Ytxf1QGkw/9ve5Y+NxBbZM6Ht95tuXNMKs8EJyFa/Vy/+Co3stop3KBHARfn/giv+Lj1uUnTfOJ3moFEQ==" - }, "node_modules/react-fast-compare": { "version": "3.2.2", "resolved": "https://registry.npmjs.org/react-fast-compare/-/react-fast-compare-3.2.2.tgz", @@ -13949,6 +13545,17 @@ "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==" }, + "node_modules/react-json-view-lite": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/react-json-view-lite/-/react-json-view-lite-2.4.1.tgz", + "integrity": "sha512-fwFYknRIBxjbFm0kBDrzgBy1xa5tDg2LyXXBepC5f1b+MY3BUClMCsvanMPn089JbV1Eg3nZcrp0VCuH43aXnA==", + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "react": "^18.0.0 || ^19.0.0" + } + }, "node_modules/react-loadable": { "name": "@docusaurus/react-loadable", "version": "6.0.0", @@ -14048,22 +13655,6 @@ "node": ">=8.10.0" } }, - "node_modules/reading-time": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/reading-time/-/reading-time-1.5.0.tgz", - "integrity": "sha512-onYyVhBNr4CmAxFsKS7bz+uTLRakypIe4R+5A824vBSkQy/hB3fZepoVEf8OVAxzLvK+H/jm9TzpI3ETSm64Kg==" - }, - "node_modules/rechoir": { - "version": "0.6.2", - "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.6.2.tgz", - "integrity": "sha512-HFM8rkZ+i3zrV+4LQjwQ0W+ez98pApMGM3HUrN04j3CqzPOzl9nmP15Y8YXNm8QHGv/eacOVEjqhmWpkRV0NAw==", - "dependencies": { - "resolve": "^1.1.6" - }, - "engines": { - "node": ">= 0.10" - } - }, "node_modules/recma-build-jsx": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/recma-build-jsx/-/recma-build-jsx-1.0.0.tgz", @@ -14124,17 +13715,6 @@ "url": "https://opencollective.com/unified" } }, - "node_modules/recursive-readdir": { - "version": "2.2.3", - "resolved": "https://registry.npmjs.org/recursive-readdir/-/recursive-readdir-2.2.3.tgz", - "integrity": "sha512-8HrF5ZsXk5FAH9dgsx3BlUer73nIhuj+9OrQwEbLTPOBzGkL1lsFCR01am+v+0m2Cmbs1nP12hLDl5FA7EszKA==", - "dependencies": { - "minimatch": "^3.0.5" - }, - "engines": { - "node": ">=6.0.0" - } - }, "node_modules/regenerate": { "version": "1.4.2", "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.2.tgz", @@ -14666,6 +14246,11 @@ "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.25.0.tgz", "integrity": "sha512-xFVuu11jh+xcO7JOAGJNOXld8/TcEHK/4CituBUeUb5hqxJLj9YuemAEuvm9gQ/+pgXYfbQuqAkiYu+u7YEsNA==" }, + "node_modules/schema-dts": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/schema-dts/-/schema-dts-1.1.5.tgz", + "integrity": "sha512-RJr9EaCmsLzBX2NDiO5Z3ux2BVosNZN5jo0gWgsyKvxKIUL5R3swNvoorulAeL9kLB0iTSX7V6aokhla2m7xbg==" + }, "node_modules/schema-utils": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.3.0.tgz", @@ -14974,22 +14559,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/shelljs": { - "version": "0.8.5", - "resolved": "https://registry.npmjs.org/shelljs/-/shelljs-0.8.5.tgz", - "integrity": "sha512-TiwcRcrkhHvbrZbnRcFYMLl30Dfov3HKqzp5tO5b4pt6G/SezKcYhmDg15zXVBswHmctSAQKznqNW2LO5tTDow==", - "dependencies": { - "glob": "^7.0.0", - "interpret": "^1.0.0", - "rechoir": "^0.6.2" - }, - "bin": { - "shjs": "bin/shjs" - }, - "engines": { - "node": ">=4" - } - }, "node_modules/side-channel": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.0.tgz", @@ -15245,9 +14814,9 @@ } }, "node_modules/std-env": { - "version": "3.8.0", - "resolved": "https://registry.npmjs.org/std-env/-/std-env-3.8.0.tgz", - "integrity": "sha512-Bc3YwwCB+OzldMxOXJIIvC6cPRWr/LxOp48CdQTOkPyk/t4JWWJbrilwBd7RJzKV8QW7tJkcgAmeuLLJugl5/w==" + "version": "3.9.0", + "resolved": "https://registry.npmjs.org/std-env/-/std-env-3.9.0.tgz", + "integrity": "sha512-UGvjygr6F6tpH7o2qyqR6QYpwraIjKSdtzyBdyytFOHmPZY917kwdwLG0RbOjWOnKmnm3PeHjaoLLMie7kPLQw==" }, "node_modules/string_decoder": { "version": "1.3.0", @@ -15534,11 +15103,6 @@ "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==" }, - "node_modules/text-table": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", - "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==" - }, "node_modules/thunky": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/thunky/-/thunky-1.1.0.tgz", @@ -15554,6 +15118,14 @@ "resolved": "https://registry.npmjs.org/tiny-warning/-/tiny-warning-1.0.3.tgz", "integrity": "sha512-lBN9zLN/oAf68o3zNXYrdCt1kP8WsiGW8Oo2ka41b2IM5JL/S1CTyX1rW0mb/zSuJun0ZUrDxx4sqvYS2FWzPA==" }, + "node_modules/tinypool": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/tinypool/-/tinypool-1.1.1.tgz", + "integrity": "sha512-Zba82s87IFq9A9XmjiX5uZA/ARWDrB03OHlq+Vw1fSdt0I+4/Kutwy8BP4Y/y/aORMo61FQ0vIb5j44vSo5Pkg==", + "engines": { + "node": "^18.0.0 || >=20.0.0" + } + }, "node_modules/to-regex-range": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", @@ -15658,6 +15230,7 @@ "version": "5.7.3", "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.7.3.tgz", "integrity": "sha512-84MVSjMEHP+FQRPy3pX9sTVV/INIex71s9TL2Gm5FG/WG1SqXeKyZ0k7/blY/4FdOzI12CBy1vGc4og/eus0fw==", + "devOptional": true, "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" @@ -15839,9 +15412,9 @@ } }, "node_modules/update-browserslist-db": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.2.tgz", - "integrity": "sha512-PPypAm5qvlD7XMZC3BujecnaOxwhrtoFR+Dqkk5Aa/6DssiH0ibKoketaj9w8LP7Bont1rYeoV5plxD7RTEPRg==", + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.3.tgz", + "integrity": "sha512-UxhIZQ+QInVdunkDAaiazvvT/+fXL5Osr0JZlJulepYu6Jd7qJtDZjlur0emRlT71EN3ScPoE7gvsuIKKNavKw==", "funding": [ { "type": "opencollective", @@ -16631,18 +16204,10 @@ "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==" }, - "node_modules/yaml": { - "version": "1.10.2", - "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz", - "integrity": "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==", - "engines": { - "node": ">= 6" - } - }, "node_modules/yocto-queue": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-1.1.1.tgz", - "integrity": "sha512-b4JR1PFR10y1mKjhHY9LaGo6tmrgjit7hxVIeAmyMw3jegXR4dhYqLaQF5zMXZxY7tLpMyJeLjr1C4rLmkVe8g==", + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-1.2.1.tgz", + "integrity": "sha512-AyeEbWOu/TAXdxlV9wmGcR0+yh2j3vYPGOECcIj2S7MkrLyC7ne+oye2BKTItt0ii2PHk4cDy+95+LshzbXnGg==", "engines": { "node": ">=12.20" }, diff --git a/documentation/package.json b/documentation/package.json index ff51550c..7434f560 100644 --- a/documentation/package.json +++ b/documentation/package.json @@ -1,6 +1,6 @@ { "name": "react-unity-webgl-documentation", - "version": "1.0.4", + "version": "1.0.5", "homepage": "https://react-unity-webgl.dev", "author": { "name": "Jeffrey Lanters", @@ -32,10 +32,10 @@ "typecheck": "tsc" }, "dependencies": { - "@docusaurus/core": "^3.7.0", - "@docusaurus/plugin-google-analytics": "^3.7.0", - "@docusaurus/plugin-sitemap": "^3.7.0", - "@docusaurus/preset-classic": "^3.7.0", + "@docusaurus/core": "^3.8.1", + "@docusaurus/plugin-google-analytics": "^3.8.1", + "@docusaurus/plugin-sitemap": "^3.8.1", + "@docusaurus/preset-classic": "^3.8.1", "@mdx-js/react": "^3.1.0", "clsx": "^2.1.1", "prism-react-renderer": "^2.4.1", @@ -43,7 +43,7 @@ "react-dom": "^19.0.0" }, "devDependencies": { - "@docusaurus/module-type-aliases": "^3.7.0", + "@docusaurus/module-type-aliases": "^3.8.1", "@tsconfig/docusaurus": "^2.0.3", "typescript": "^5.7.3" }, From d59cc117706d626c73d345adbb2ea052400af2a4 Mon Sep 17 00:00:00 2001 From: Jeffrey Lanters Date: Wed, 16 Jul 2025 13:31:54 +0200 Subject: [PATCH 116/194] docs: update unload documentation to reflect changes in React Unity WebGL version 10 --- documentation/docs/api/unload.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/documentation/docs/api/unload.md b/documentation/docs/api/unload.md index 8d13461a..0696dc09 100644 --- a/documentation/docs/api/unload.md +++ b/documentation/docs/api/unload.md @@ -2,6 +2,10 @@ Requests the Unity Application to be unloaded from memory in order to be unmounted from the DOM. +:::warning +Since React Unity WebGL version 10, calling the unload function is no longer required to unmount the Unity Application. The Unity Application will automatically be unmounted when the component is removed from the DOM. However, if you want to unload the Unity Application manually, you can still use the unload function. But be aware that this is not necessary in most cases. +::: + ## Type Definition ```tsx title="Type Definition" From 398d9f7cb38c38a8dedbbb4473e8ee26f64b0981 Mon Sep 17 00:00:00 2001 From: Jeffrey Lanters Date: Wed, 16 Jul 2025 13:31:57 +0200 Subject: [PATCH 117/194] fix: restore unload documentation in API sidebar --- documentation/sidebars.json | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/documentation/sidebars.json b/documentation/sidebars.json index 6babebc2..8f96e313 100644 --- a/documentation/sidebars.json +++ b/documentation/sidebars.json @@ -96,10 +96,6 @@ { "type": "doc", "id": "api/loading-progression" - }, - { - "type": "doc", - "id": "api/unload" } ] }, @@ -201,6 +197,10 @@ "type": "doc", "id": "api/web-worker", "label": "Using a Web Worker" + }, + { + "type": "doc", + "id": "api/unload" } ] } From 337f92c54126b1c3fb991e021ed23e5dc285b0af Mon Sep 17 00:00:00 2001 From: Jeffrey Lanters Date: Wed, 16 Jul 2025 13:45:15 +0200 Subject: [PATCH 118/194] docs: update release notes for React Unity WebGL version 10.0.0 --- RELEASE-NOTES.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/RELEASE-NOTES.md b/RELEASE-NOTES.md index 75d15b07..6bf84495 100644 --- a/RELEASE-NOTES.md +++ b/RELEASE-NOTES.md @@ -1 +1 @@ -- Added support for configurating autoSyncPersistentDataPath in the Unity configuration. +- Proud to announce the release of React Unity WebGL version 10.0.0 while celebrating 8 years of React Unity WebGL! This version includes several important updates and fixes, including the removal of the `unload` function, which is no longer necessary to unmount the Unity Application. The Unity Application will automatically be unmounted when the component is removed from the DOM. However, if you want to unload the Unity Application manually, you can still use the `unload` function, but be aware that this is not necessary in most cases. From 3b474a5cdb8f5f83ac6c920f45ab6fc3d991e504 Mon Sep 17 00:00:00 2001 From: Jeffrey Lanters Date: Wed, 16 Jul 2025 13:46:00 +0200 Subject: [PATCH 119/194] Resolved documentation migration links --- .../version-9.x.x/api/canvas-device-pixel-ratio.md | 2 +- .../versioned_docs/version-9.x.x/api/event-system.md | 2 +- documentation/versioned_docs/version-9.x.x/api/is-loaded.md | 2 +- .../versioned_docs/version-9.x.x/api/loading-progression.md | 2 +- .../versioned_docs/version-9.x.x/api/request-fullscreen.md | 2 +- .../versioned_docs/version-9.x.x/api/request-pointer-lock.md | 2 +- .../versioned_docs/version-9.x.x/api/send-message.md | 4 ++-- .../versioned_docs/version-9.x.x/api/take-screenshot.md | 2 +- documentation/versioned_docs/version-9.x.x/api/unload.md | 2 +- 9 files changed, 10 insertions(+), 10 deletions(-) diff --git a/documentation/versioned_docs/version-9.x.x/api/canvas-device-pixel-ratio.md b/documentation/versioned_docs/version-9.x.x/api/canvas-device-pixel-ratio.md index faecdd36..2c97f8ef 100644 --- a/documentation/versioned_docs/version-9.x.x/api/canvas-device-pixel-ratio.md +++ b/documentation/versioned_docs/version-9.x.x/api/canvas-device-pixel-ratio.md @@ -16,7 +16,7 @@ Usage of this feature requires your Unity Application to be built with Unity 202 The Canvas can appear too blurry on retina screens. The device pixel ratio determines how much extra pixel density should be added to allow for a sharper image. Providing this prop will set the device pixel ratio of the Unity Application's canvas by multiplying the default resolution of the canvas by the provided value. -You can use the browser's device pixel ratio to determine the device pixel ratio of the Unity Application's canvas. Head over to the advanced examples to see [how to implement a dynamic device pixel ratio](/docs/advanced-examples/dynamic-device-pixel-ratio). +You can use the browser's device pixel ratio to determine the device pixel ratio of the Unity Application's canvas. Head over to the advanced examples to see [how to implement a dynamic device pixel ratio](/docs/9.x.x/advanced-examples/dynamic-device-pixel-ratio). :::warning The value will be used as a multiplier to the actual canvas scale and will litterally add extra pixels to the canvas. This will have a big impact on the performance of your Unity Application and overall performance of your browser. diff --git a/documentation/versioned_docs/version-9.x.x/api/event-system.md b/documentation/versioned_docs/version-9.x.x/api/event-system.md index 521c813b..477976c7 100644 --- a/documentation/versioned_docs/version-9.x.x/api/event-system.md +++ b/documentation/versioned_docs/version-9.x.x/api/event-system.md @@ -41,7 +41,7 @@ Keep in mind communication from Unity to React is handeld globally, this means e ::: :::info -Simple numeric types can be passed to JavaScript in function parameters without requiring any conversion. Other data types will be passed as a pointer in the emscripten heap (which is really just a big array in JavaScript). For strings, you can use the Pointerstringify helper function to convert to a JavaScript string. You can read more about [parameters and JavaScript to Unityscript types here](/docs/main-concepts/data-conversion). +Simple numeric types can be passed to JavaScript in function parameters without requiring any conversion. Other data types will be passed as a pointer in the emscripten heap (which is really just a big array in JavaScript). For strings, you can use the Pointerstringify helper function to convert to a JavaScript string. You can read more about [parameters and JavaScript to Unityscript types here](/docs/9.x.x/main-concepts/data-conversion). ::: Sending messages from Unity to React consists of two parts, registering an event listener and dispatching an event. diff --git a/documentation/versioned_docs/version-9.x.x/api/is-loaded.md b/documentation/versioned_docs/version-9.x.x/api/is-loaded.md index d353350f..a660abaf 100644 --- a/documentation/versioned_docs/version-9.x.x/api/is-loaded.md +++ b/documentation/versioned_docs/version-9.x.x/api/is-loaded.md @@ -30,7 +30,7 @@ return

Application Loaded!

; ``` :::tip -Display some kind of overlay over your Unity Application while it's loading to prevent the user from interacting with the Unity Application before it's completely ready. And use the [loading progression stateful value](/docs/api/loading-progression) to display a loading bar. +Display some kind of overlay over your Unity Application while it's loading to prevent the user from interacting with the Unity Application before it's completely ready. And use the [loading progression stateful value](/docs/9.x.x/api/loading-progression) to display a loading bar. ::: ## Example Usage diff --git a/documentation/versioned_docs/version-9.x.x/api/loading-progression.md b/documentation/versioned_docs/version-9.x.x/api/loading-progression.md index 08e3f733..89639dd7 100644 --- a/documentation/versioned_docs/version-9.x.x/api/loading-progression.md +++ b/documentation/versioned_docs/version-9.x.x/api/loading-progression.md @@ -31,7 +31,7 @@ You're not limited by just showing the percentage of the loading progression, yo ``` :::tip -If you want to do something based on when the Unity Application has finished loading, you can use the [is loaded stateful value](/docs/api/is-loaded) rather than checking whether the loading progression's value is 1. +If you want to do something based on when the Unity Application has finished loading, you can use the [is loaded stateful value](/docs/9.x.x/api/is-loaded) rather than checking whether the loading progression's value is 1. ::: ## Example Usage diff --git a/documentation/versioned_docs/version-9.x.x/api/request-fullscreen.md b/documentation/versioned_docs/version-9.x.x/api/request-fullscreen.md index 4711d72c..a7c17ca5 100644 --- a/documentation/versioned_docs/version-9.x.x/api/request-fullscreen.md +++ b/documentation/versioned_docs/version-9.x.x/api/request-fullscreen.md @@ -13,7 +13,7 @@ function requestFullscreen(enabled: boolean): void; The exposed request fullscreen function allows you to enable and disable the fullscreen mode of your Unity Application. The parameter `enabled` is a boolean value that indicates if the fullscreen mode should be enabled or disabled. :::info -It is posible to also request locking the pointer within the canvas via the [request pointer lock function](/docs/api/request-pointer-lock) within the Unity Context. Cursor locking and full-screen mode are both supported simultaneously in React Unity WebGL, implemented using their respective HTML5 APIs. +It is posible to also request locking the pointer within the canvas via the [request pointer lock function](/docs/9.x.x/api/request-pointer-lock) within the Unity Context. Cursor locking and full-screen mode are both supported simultaneously in React Unity WebGL, implemented using their respective HTML5 APIs. ::: To get started, destructure the request fullscreen function from the Unity Context. diff --git a/documentation/versioned_docs/version-9.x.x/api/request-pointer-lock.md b/documentation/versioned_docs/version-9.x.x/api/request-pointer-lock.md index 293f363b..a056778f 100644 --- a/documentation/versioned_docs/version-9.x.x/api/request-pointer-lock.md +++ b/documentation/versioned_docs/version-9.x.x/api/request-pointer-lock.md @@ -17,7 +17,7 @@ More than that, the API is useful for any applications that require significant Pointer lock lets you access mouse events even when the cursor goes past the boundary of the browser or screen. For example, your users can continue to rotate or manipulate a 3D model by moving the mouse without end. Without Pointer lock, the rotation or manipulation stops the moment the pointer reaches the edge of the browser or screen. Game players can now click buttons and swipe the mouse cursor back and forth without worrying about leaving the game play area and accidentally clicking another application that would take mouse focus away from the game. :::info -It is posible to also request entering fullscreen within the canvas via the [request fullscreen function](/docs/api/request-fullscreen) within the Unity Context. Cursor locking and full-screen mode are both supported simultaneously in React Unity WebGL, implemented using their respective HTML5 APIs. +It is posible to also request entering fullscreen within the canvas via the [request fullscreen function](/docs/9.x.x/api/request-fullscreen) within the Unity Context. Cursor locking and full-screen mode are both supported simultaneously in React Unity WebGL, implemented using their respective HTML5 APIs. ::: To get started, destructure the request pointer lock function from the Unity Context. diff --git a/documentation/versioned_docs/version-9.x.x/api/send-message.md b/documentation/versioned_docs/version-9.x.x/api/send-message.md index 8f090a7c..8a93ece7 100644 --- a/documentation/versioned_docs/version-9.x.x/api/send-message.md +++ b/documentation/versioned_docs/version-9.x.x/api/send-message.md @@ -32,12 +32,12 @@ When invoking a C-Sharp method by sending a message, the name of the mono behavi ::: :::warning -Make sure the parameter matches the actual existence and type of the C-Sharp method you're trying to invoke. Not +Make sure the parameter matches the actual existence and type of the C-Sharp method you're trying to invoke. Not doing so may cause unintended behaviour or even a crash of the Unity Application. ::: :::info -Simple numeric types can be passed to JavaScript in function parameters without requiring any conversion. Other data types will be passed as a pointer in the emscripten heap (which is really just a big array in JavaScript). For strings, you can use the Pointerstringify helper function to convert to a JavaScript string. You can read more about [parameters and JavaScript to Unityscript types here](/docs/main-concepts/data-conversion). +Simple numeric types can be passed to JavaScript in function parameters without requiring any conversion. Other data types will be passed as a pointer in the emscripten heap (which is really just a big array in JavaScript). For strings, you can use the Pointerstringify helper function to convert to a JavaScript string. You can read more about [parameters and JavaScript to Unityscript types here](/docs/9.x.x/main-concepts/data-conversion). ::: ## Example Usage diff --git a/documentation/versioned_docs/version-9.x.x/api/take-screenshot.md b/documentation/versioned_docs/version-9.x.x/api/take-screenshot.md index 5ad02192..39fe382b 100644 --- a/documentation/versioned_docs/version-9.x.x/api/take-screenshot.md +++ b/documentation/versioned_docs/version-9.x.x/api/take-screenshot.md @@ -18,7 +18,7 @@ Takes a screenshot of the canvas and returns a data URL containing image data. A If an attempt to take a screenshot was made before the Unity Application was initialized, the function will return `undefined` instead of a data URL. :::info -In order to take screenshot of the Unity WebGL canvas, you'll need to enable preserve drawing buffer within the WebGL context attributes. Enabling this feature makes sure that the canvas is not cleared before the screenshot is taken. This setting en disabled by default, and can be enabled via the Unity Config's [WebGLRenderingContext](/docs/api/webgl-rendering-context) property. +In order to take screenshot of the Unity WebGL canvas, you'll need to enable preserve drawing buffer within the WebGL context attributes. Enabling this feature makes sure that the canvas is not cleared before the screenshot is taken. This setting en disabled by default, and can be enabled via the Unity Config's [WebGLRenderingContext](/docs/9.x.x/api/webgl-rendering-context) property. ```jsx showLineNumbers title="Example: Preserving the Drawing Buffer" const unityContext = useUnityContext({ diff --git a/documentation/versioned_docs/version-9.x.x/api/unload.md b/documentation/versioned_docs/version-9.x.x/api/unload.md index 42b60ce5..0954c52f 100644 --- a/documentation/versioned_docs/version-9.x.x/api/unload.md +++ b/documentation/versioned_docs/version-9.x.x/api/unload.md @@ -19,7 +19,7 @@ In earlier versions of Unity, it was possible to unmount the Unity Application a As of this writing, the issue has not been resolved. However, it is possible to manually unmount the Unity Application by halting navigation to the next page. A ticket has been submitted, and the Unity team has acknowledged this as a known issue. For more details, refer to the [GitHub issue](https://github.com/jeffreylanters/react-unity-webgl/issues/250). -Alternatively, you can use the unsafe `detachAndUnloadImmediate` function to immediately unmount the Unity Application. However, this is not recommended unless you are an advanced user. For more information, refer to the [Unsafe Detach and Unload Immediate](/docs/api/unsafe-detach-unmount-immediate) documentation. +Alternatively, you can use the unsafe `detachAndUnloadImmediate` function to immediately unmount the Unity Application. However, this is not recommended unless you are an advanced user. For more information, refer to the [Unsafe Detach and Unload Immediate](/docs/9.x.x/api/unsafe-detach-unmount-immediate) documentation. ::: When building a multi-page React Application, it is important to unload the Unity Application in order to completely unmount the component from the DOM to free up the memory taken by the Unity JavaScript heap, and without Unity throwing an error. Invoking the function will request the Unity Application to be unloaded from memory. The function will return a Promise that will be resolved when the Unity Application has been unloaded. From 105f57d271b6bc39fac3369a9e563a4e85b83c4f Mon Sep 17 00:00:00 2001 From: Jeffrey Lanters Date: Wed, 16 Jul 2025 13:48:28 +0200 Subject: [PATCH 120/194] docs: update introduction and support pages to reflect new contact information --- documentation/docs/introduction.md | 4 ++-- documentation/src/pages/support.md | 2 +- documentation/versioned_docs/version-9.x.x/introduction.md | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/documentation/docs/introduction.md b/documentation/docs/introduction.md index c57c3adb..1d4bf60c 100644 --- a/documentation/docs/introduction.md +++ b/documentation/docs/introduction.md @@ -1,7 +1,7 @@ # Introduction -Welcome to the React Unity WebGL documentation! My name is [Jeffrey Lanters](https://twitter.com/jeffreylanters), and I'm here to help you bring your awesome games to the web! Everything you'll need to know from get started to creating complex interactive systems can be found in this documentation. If you'll need help, feel free to open a new [discussion](https://github.com/jeffreylanters/react-unity-webgl/discussions), when you want to contribute or think you've found a problem, feel free to open a new [issue](https://github.com/jeffreylanters/react-unity-webgl/issues). And if you like what you see, please consider [starring this repository](https://github.com/jeffreylanters/react-unity-webgl/stargazers) or by [suporting the project](https://react-unity-webgl.dev/support)! +Welcome to the React Unity WebGL documentation! My name is [Jeffrey Lanters](https://jeffreylanters.me), and I'm here to help you bring your awesome games to the web! Everything you'll need to know from get started to creating complex interactive systems can be found in this documentation. If you'll need help, feel free to open a new [discussion](https://github.com/jeffreylanters/react-unity-webgl/discussions), when you want to contribute or think you've found a problem, feel free to open a new [issue](https://github.com/jeffreylanters/react-unity-webgl/issues). And if you like what you see, please consider [starring this repository](https://github.com/jeffreylanters/react-unity-webgl/stargazers) or by [suporting the project](https://react-unity-webgl.dev/support)! -If you're stuck or need professional assistance and are looking for personal help over a video call, feel free to reach out to me on [Twitter](https://twitter.com/jeffreylanters) or send me an email to [support@jeffreylanters.me](mailto:support@jeffreylanters.me). +If you're stuck or need professional assistance and are looking for personal help over a video call, feel free to reach out to me on [GitHub](https://github.com/jeffreylanters) or send me an email to [support@jeffreylanters.me](mailto:support@jeffreylanters.me). Happy coding! 🚀 diff --git a/documentation/src/pages/support.md b/documentation/src/pages/support.md index 9f13bb1a..cca8d84c 100644 --- a/documentation/src/pages/support.md +++ b/documentation/src/pages/support.md @@ -1,6 +1,6 @@ # Support the project by donating or sponsoring -Hi there! I would like to say one more thing before you start bringing your awesome games to the web. My name is [Jeffrey Lanters](https://twitter.com/jeffreylanters), I'm a Unity and Web developer with a passion for Open Source. The project you're looking at right now is one of my hobby projects. Maintaining and building this project is something **I do in my spare time**, and I have been doing so since 2017. React-Unity-WebGL will **always remain free**, but adding new features, maintaining it and keeping up-to-date with Unity's updates takes a lot of work and time. If you are able to, I would appreciate it greatly if you would consider sending a donation or becoming a sponsor to help me keep this project going. +Hi there! I would like to say one more thing before you start bringing your awesome games to the web. My name is [Jeffrey Lanters](https://jeffreylanters.me), I'm a Unity and Web developer with a passion for Open Source. The project you're looking at right now is one of my hobby projects. Maintaining and building this project is something **I do in my spare time**, and I have been doing so since 2017. React-Unity-WebGL will **always remain free**, but adding new features, maintaining it and keeping up-to-date with Unity's updates takes a lot of work and time. If you are able to, I would appreciate it greatly if you would consider sending a donation or becoming a sponsor to help me keep this project going. ## How to help? diff --git a/documentation/versioned_docs/version-9.x.x/introduction.md b/documentation/versioned_docs/version-9.x.x/introduction.md index c57c3adb..1d4bf60c 100644 --- a/documentation/versioned_docs/version-9.x.x/introduction.md +++ b/documentation/versioned_docs/version-9.x.x/introduction.md @@ -1,7 +1,7 @@ # Introduction -Welcome to the React Unity WebGL documentation! My name is [Jeffrey Lanters](https://twitter.com/jeffreylanters), and I'm here to help you bring your awesome games to the web! Everything you'll need to know from get started to creating complex interactive systems can be found in this documentation. If you'll need help, feel free to open a new [discussion](https://github.com/jeffreylanters/react-unity-webgl/discussions), when you want to contribute or think you've found a problem, feel free to open a new [issue](https://github.com/jeffreylanters/react-unity-webgl/issues). And if you like what you see, please consider [starring this repository](https://github.com/jeffreylanters/react-unity-webgl/stargazers) or by [suporting the project](https://react-unity-webgl.dev/support)! +Welcome to the React Unity WebGL documentation! My name is [Jeffrey Lanters](https://jeffreylanters.me), and I'm here to help you bring your awesome games to the web! Everything you'll need to know from get started to creating complex interactive systems can be found in this documentation. If you'll need help, feel free to open a new [discussion](https://github.com/jeffreylanters/react-unity-webgl/discussions), when you want to contribute or think you've found a problem, feel free to open a new [issue](https://github.com/jeffreylanters/react-unity-webgl/issues). And if you like what you see, please consider [starring this repository](https://github.com/jeffreylanters/react-unity-webgl/stargazers) or by [suporting the project](https://react-unity-webgl.dev/support)! -If you're stuck or need professional assistance and are looking for personal help over a video call, feel free to reach out to me on [Twitter](https://twitter.com/jeffreylanters) or send me an email to [support@jeffreylanters.me](mailto:support@jeffreylanters.me). +If you're stuck or need professional assistance and are looking for personal help over a video call, feel free to reach out to me on [GitHub](https://github.com/jeffreylanters) or send me an email to [support@jeffreylanters.me](mailto:support@jeffreylanters.me). Happy coding! 🚀 From 0e63a63acf6275af50a4ede7cef44201cbd8f347 Mon Sep 17 00:00:00 2001 From: Jeffrey Lanters Date: Wed, 16 Jul 2025 13:58:07 +0200 Subject: [PATCH 121/194] docs: add upgrading guide for version 9 --- documentation/docs/upgrading-from-version-8.md | 7 ------- documentation/docs/upgrading-from-version-9.md | 7 +++++++ documentation/sidebars.json | 4 ++++ 3 files changed, 11 insertions(+), 7 deletions(-) delete mode 100644 documentation/docs/upgrading-from-version-8.md create mode 100644 documentation/docs/upgrading-from-version-9.md diff --git a/documentation/docs/upgrading-from-version-8.md b/documentation/docs/upgrading-from-version-8.md deleted file mode 100644 index 10c9a76e..00000000 --- a/documentation/docs/upgrading-from-version-8.md +++ /dev/null @@ -1,7 +0,0 @@ -# Upgrading from version 8 - -:::info -This page is still under construction. -::: - - diff --git a/documentation/docs/upgrading-from-version-9.md b/documentation/docs/upgrading-from-version-9.md new file mode 100644 index 00000000..497cc12e --- /dev/null +++ b/documentation/docs/upgrading-from-version-9.md @@ -0,0 +1,7 @@ +# Upgrading from version 9 + +Version 10 is fully compatible with version 9, so you can upgrade without any issues. Version 10 introduces new features and improvements, but it does not break any existing functionality. However, there is one change you should be aware of: + +The long-standing unloading issue Unity introduced in Unity 2021.2 has been resolved in React Unity WebGL version 10. This means that you no longer need to call the [`unload`](/docs/api/unload) function to unmount the Unity Application when using React Unity WebGL version 10. + +Happy coding! diff --git a/documentation/sidebars.json b/documentation/sidebars.json index 8f96e313..3e9b4829 100644 --- a/documentation/sidebars.json +++ b/documentation/sidebars.json @@ -75,6 +75,10 @@ } ] }, + { + "type": "doc", + "id": "upgrading-from-version-9" + }, { "type": "doc", "id": "contributing" From 5879fdb16b423820699cb6b8beec34186f8c2c34 Mon Sep 17 00:00:00 2001 From: Jeffrey Lanters Date: Wed, 16 Jul 2025 13:58:59 +0200 Subject: [PATCH 122/194] docs: add upgrading guide for version 10 and update sidebar reference --- .../docs/{upgrading-from-version-9.md => upgrading.md} | 0 documentation/sidebars.json | 2 +- 2 files changed, 1 insertion(+), 1 deletion(-) rename documentation/docs/{upgrading-from-version-9.md => upgrading.md} (100%) diff --git a/documentation/docs/upgrading-from-version-9.md b/documentation/docs/upgrading.md similarity index 100% rename from documentation/docs/upgrading-from-version-9.md rename to documentation/docs/upgrading.md diff --git a/documentation/sidebars.json b/documentation/sidebars.json index 3e9b4829..e0f5a7bc 100644 --- a/documentation/sidebars.json +++ b/documentation/sidebars.json @@ -77,7 +77,7 @@ }, { "type": "doc", - "id": "upgrading-from-version-9" + "id": "upgrading" }, { "type": "doc", From 29a1b5c0379d7e69f73a22ac9c35517010f0111a Mon Sep 17 00:00:00 2001 From: Jeffrey Lanters Date: Wed, 16 Jul 2025 14:34:10 +0200 Subject: [PATCH 123/194] docs: update package dependencies for Unity modules and improve versioning --- testing/project/Packages/manifest.json | 5 ++- testing/project/Packages/packages-lock.json | 43 +++++++++++++++------ 2 files changed, 35 insertions(+), 13 deletions(-) diff --git a/testing/project/Packages/manifest.json b/testing/project/Packages/manifest.json index 83493a02..ed9da187 100644 --- a/testing/project/Packages/manifest.json +++ b/testing/project/Packages/manifest.json @@ -1,6 +1,9 @@ { "dependencies": { - "com.unity.ugui": "1.0.0", + "com.unity.ai.navigation": "2.0.8", + "com.unity.multiplayer.center": "1.0.0", + "com.unity.ugui": "2.0.0", + "com.unity.modules.accessibility": "1.0.0", "com.unity.modules.ai": "1.0.0", "com.unity.modules.androidjni": "1.0.0", "com.unity.modules.animation": "1.0.0", diff --git a/testing/project/Packages/packages-lock.json b/testing/project/Packages/packages-lock.json index 0c888383..e7585523 100644 --- a/testing/project/Packages/packages-lock.json +++ b/testing/project/Packages/packages-lock.json @@ -1,14 +1,37 @@ { "dependencies": { - "com.unity.ugui": { + "com.unity.ai.navigation": { + "version": "2.0.8", + "depth": 0, + "source": "registry", + "dependencies": { + "com.unity.modules.ai": "1.0.0" + }, + "url": "https://packages.unity.com" + }, + "com.unity.multiplayer.center": { "version": "1.0.0", "depth": 0, "source": "builtin", + "dependencies": { + "com.unity.modules.uielements": "1.0.0" + } + }, + "com.unity.ugui": { + "version": "2.0.0", + "depth": 0, + "source": "builtin", "dependencies": { "com.unity.modules.ui": "1.0.0", "com.unity.modules.imgui": "1.0.0" } }, + "com.unity.modules.accessibility": { + "version": "1.0.0", + "depth": 0, + "source": "builtin", + "dependencies": {} + }, "com.unity.modules.ai": { "version": "1.0.0", "depth": 0, @@ -56,6 +79,12 @@ "com.unity.modules.animation": "1.0.0" } }, + "com.unity.modules.hierarchycore": { + "version": "1.0.0", + "depth": 1, + "source": "builtin", + "dependencies": {} + }, "com.unity.modules.imageconversion": { "version": "1.0.0", "depth": 0, @@ -145,17 +174,7 @@ "com.unity.modules.ui": "1.0.0", "com.unity.modules.imgui": "1.0.0", "com.unity.modules.jsonserialize": "1.0.0", - "com.unity.modules.uielementsnative": "1.0.0" - } - }, - "com.unity.modules.uielementsnative": { - "version": "1.0.0", - "depth": 1, - "source": "builtin", - "dependencies": { - "com.unity.modules.ui": "1.0.0", - "com.unity.modules.imgui": "1.0.0", - "com.unity.modules.jsonserialize": "1.0.0" + "com.unity.modules.hierarchycore": "1.0.0" } }, "com.unity.modules.umbra": { From 7664832321c259a09108d90fc9ff7dd38026aa6a Mon Sep 17 00:00:00 2001 From: Jeffrey Lanters Date: Wed, 16 Jul 2025 14:34:15 +0200 Subject: [PATCH 124/194] docs: update EditorBuildSettings and ProjectVersion for new scene configuration and editor version --- testing/project/ProjectSettings/EditorBuildSettings.asset | 6 +++++- testing/project/ProjectSettings/MultiplayerManager.asset | 7 +++++++ testing/project/ProjectSettings/ProjectVersion.txt | 4 ++-- 3 files changed, 14 insertions(+), 3 deletions(-) create mode 100644 testing/project/ProjectSettings/MultiplayerManager.asset diff --git a/testing/project/ProjectSettings/EditorBuildSettings.asset b/testing/project/ProjectSettings/EditorBuildSettings.asset index 0147887e..2fbd7b55 100644 --- a/testing/project/ProjectSettings/EditorBuildSettings.asset +++ b/testing/project/ProjectSettings/EditorBuildSettings.asset @@ -4,5 +4,9 @@ EditorBuildSettings: m_ObjectHideFlags: 0 serializedVersion: 2 - m_Scenes: [] + m_Scenes: + - enabled: 1 + path: Assets/Main.unity + guid: 26854272bf1b541e8bdf25998a5b2aa8 m_configObjects: {} + m_UseUCBPForAssetBundles: 0 diff --git a/testing/project/ProjectSettings/MultiplayerManager.asset b/testing/project/ProjectSettings/MultiplayerManager.asset new file mode 100644 index 00000000..2a936644 --- /dev/null +++ b/testing/project/ProjectSettings/MultiplayerManager.asset @@ -0,0 +1,7 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!655991488 &1 +MultiplayerManager: + m_ObjectHideFlags: 0 + m_EnableMultiplayerRoles: 0 + m_StrippingTypes: {} diff --git a/testing/project/ProjectSettings/ProjectVersion.txt b/testing/project/ProjectSettings/ProjectVersion.txt index 5c4a30a0..c995141a 100644 --- a/testing/project/ProjectSettings/ProjectVersion.txt +++ b/testing/project/ProjectSettings/ProjectVersion.txt @@ -1,2 +1,2 @@ -m_EditorVersion: 2022.1.9f1 -m_EditorVersionWithRevision: 2022.1.9f1 (07e076b6d414) +m_EditorVersion: 6000.1.12f1 +m_EditorVersionWithRevision: 6000.1.12f1 (da0c3ee78ee0) From 02c04db452ba87453817ad4b1c30d8ec298a074c Mon Sep 17 00:00:00 2001 From: Jeffrey Lanters Date: Wed, 16 Jul 2025 14:34:34 +0200 Subject: [PATCH 125/194] Upgraded testing build to one from Unity 6 --- .../unity-build-6000.1/communication.data | Bin 0 -> 5603633 bytes .../communication.framework.js | 22 ++++++++++++++++++ .../communication.loader.js | 1 + .../unity-build-6000.1/communication.wasm | Bin 0 -> 25090153 bytes testing/src/application.tsx | 8 +++---- 5 files changed, 27 insertions(+), 4 deletions(-) create mode 100644 testing/public/unity-build-6000.1/communication.data create mode 100644 testing/public/unity-build-6000.1/communication.framework.js create mode 100644 testing/public/unity-build-6000.1/communication.loader.js create mode 100755 testing/public/unity-build-6000.1/communication.wasm diff --git a/testing/public/unity-build-6000.1/communication.data b/testing/public/unity-build-6000.1/communication.data new file mode 100644 index 0000000000000000000000000000000000000000..72c27b2f4181c040b79f2afa868d108be7413b1a GIT binary patch literal 5603633 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�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 z zYgm%LMkaYxrWcbPF*r!-Uaqc!Crp&bS8N}!uphs*9QRio1l+Bh)BZ=4>mBd@%}gRR zcJ`gMb%u<4`as=8nSt1zd8r6eaNLWxJqcr@!Krs>K_2A`!AFJQhE>HFib{Y!PRqIY z;J?v>l&dY=@vy}Co*h4KoJ6W-->AxsZGgO$Ijz2b-+}Pl=#Q1sriUn{*S9|2I?n!@ zsJs1rHVlcI*I-t^qfA4!;?>i(AlI-j=&vQTbb00qU=O&lQ z04{Om<6fZp=#uOmvDNrlM?-2~UqGS3_n7^IYU&@j48D~J`3Ci?UjMtQH=l`CrO7du zGqx4KUF!*EHB7aA82P#2t+G*_ej=YLO+dpW9D^m_;8+{y-$TK8-{5%U>4y2|K$Ur4 zXjCR~I-8SuNu5pl5h=*2q3p)a&gFWUwis*`3$88*piP3iF7r|)P#mE5&BjHZu``y> z0A2e#7wZMvVl`wOfyB|znD4hW1j3)av z5`K#IMB0eKh?r*YrMobZbyddXG0}--faQVLnTe;F6MMaZ?82TXJELUExCk3>$M?Ph zILIA+)FX41g+WI9nMX)oFU0>cxQb;Q`s+hW;Lg3gK)4ji%a$XA-@n8AldH}_rDAKr zTQFP-?wLqlGY3Zgd}=Qnu%AN@ns2oMJV$aTLSg+Qf>qfUBTsu`Prg)&7{rHWAnpaA zyoX9~gClJX&p&@UgtHDggu2_;-M&tuvHv*skMJ8AqVZ?!FiFf5H=UEHurE&)$OxLj zce7;A)C0K8usgsM792V8Xdnm7{+_Ntpd1}cPbdc)CR`c836K0`1lUt#l1?Bve_!jB zl%rpM`Q>+T8r9`0XNdN9?ata^L5KFTYd?wM;6Qn z0nQoBq{FU42OIo5Y>VShAAcH#18bCt2b=yk?%b2HV{&0-odw_8&CrpnOFy$%^X;a+BNN3oKnqJP*IoHp}$J%zM(>b zcn4f~_opd$qw;X;RemZ(KV_mHb-i=(`i&?(7JCB{VD6UGdna6Z?n2<#^L{M|?wH3C zQX1lSzi>B%De3R_nIUgq$ov&z zEUavSpC%BgLh?7^`Bj;hU?+Z-@mTOgk{sQhd@Z^?uw}ywq(#`;CJ@AnbHFJzwqR^Q zjKv5ta18Vc!cGkAI39A~5EJh8$o_a7@m~BN*I&hh=iGOs!*6q9B&IbY(#$@LQC=uu z@lc*s?RgW-^Nvwz!6tP?iQ^;*mxjoY)xy))W3vXRfpg7hkVSD8-?*-(ntweGLSR(; z!nb&TG8nZBf>m=&HuGQT7WRibfQT zfR+Noo$(YCEb!0!Prcy42uu^;{o<>e#R{CiC8Avx3l|BoLQI;K*At7s`Ch)adv0WI zWIvtNo_^-p^l8+z%svZ8BlOnaBHk&+ z@=bpa|C2(G)Q3(yazc77Z~1a{J05Q^DDqC7WS#7EZF?OmhywD99<9clj(@Mrz&}mJ z&t1@D*0@;WKu~fpuSscz;+Z@!80N(dbSjeY#W> zVkj@?hD++czIf?UjH!L`{TJVlFje1Pd<4?QM*KzUykM0l3@r8ky1u|D9)hK=$->{{ z)&4~Dol$HX*dN$mU}(w+TzKo8`Uiq;wBo#UDV}U%!UFz5Z?ss+eQ?}?At zmedebyY*k5d>**`AXE3<7vFt>Iz#xq&tW~_(*K zYoVT=3U5o;L8ez~1xy>K7B6S-_!lk{LmhO#nEGDeJuJrnggWY8=p3^zel+?ie*F*L zX2?Zh3}x{#&yd(=O!8{r*=IB=-m8oFXoNNlcMhm0INcdYPOktrjRQ1|A8Z$4P)X@gYz{XM7T@N-`o(d*2Xp8p-I{_D$qziW#-O!T!M_6Ue&q=2vf;yoG0O8kgt{EH z3AJEy=YM@;ljkgc2RPBr>6v{&1z`pZ*P%;O8XFsD!tRQWR9?p)Q$)@l)I5{H#frGJ z_<1=D6e!{+0qz%5$}~Y?+1^`B37M@m1oW0mZ9=dLX7cZF8PxE}-#_^~27xS!;w^;F z(CgQORsVGu@qUcsRXk5dsv@Du!fwR|07m+0yai-Ck&jL?g+!taI6b?QG03%JD!-`& zFKz3U_~`FOqv$z4{>FHLRxP+1*x0`j?shU&D^z#*(BVS>V?S`q1Gj`s12_{q^^HRa zBd?RZJmQL1H~;tP7}&FKLSUl5Ee81O1YVNrpzWBH<^@+lS{MGT@MWKJx^C;$^PAP( z7*qPqvuyD61y?tn6StwU&3(La8u7IM_H^-S=Ho3i13-*)!o()0a=PS`jXQYx9GdhP z0GXRdV&dIfueKv*B)6*cf4K*`Rtv9bx}B2W7kMPBn81MfKZ{}!{x ze;?Za|G)ol%)tMXTt!K6KTKeU8A#pn+=WGg*_B< z*gn9UgIqT-fFoFn+1H&qSp=F=1oZb>%zQd@RHH}(bPadnLY)8eLo)OPNKJD1=9Uki z0H6;+3i7u`|8wKk9E1byCU=Q|BA>jIj*z_@#o9ZLKk-D!9?Sw@!;32p_=e@|LDs}| zq^6oE3zOmi7ms8j{W}9}LNM+;YEs6W0;tC%Si#uJ6@JO7lP07BoG1s+{qvUFoKC02 z=ZI7y0OgTWI5`aZ$k=~|GyJX=M7;tafiaLQrNr|dYtSyvKNqy4{*LAxP632OAd~*% z5a4+BwY%qIFz+#EJRrg7IinIXATpoPf>@Ht{(}3zKuiBm@)!OyYG5aklb*W(o(Q0g z-qPrCw&38o!14R;yYC0O04|k3;}ZBd=BC1FEl2+qCv-Pd_V9=l2mk7$62cWtT zU?IcPI0x6_aJp_*qQi-QHRPGH1@e9t0+@!W-!qvy}R+8@Ko&ey(LIe}}A$LH({goeVfADhE3M8eDjH3fR~$WT(rEHE^exG-}?h!fsXxG?~+hWulH zQt8k+V0`AR#|0sa4oZ0EV#S#eBaVL$oY}@SzSE>uYHp6&D>33Fh!G~;P<%F#pR)y7 zYKzE^0{64XKa1*_cP=&^{qDOPUm_^__Jva?1qZJ<(p3PTE~t*Oc|AHZ7I&3m|YVz0GLR15(<%_44f7Dg_4K3yDQpFN|wBS#izY)Qpub;`B!#yVn1qA zcDxBrmK!&2#KTNU_i=&$5h4e{Y9AX*tPh+d(l|31?MnLyAc0F7mmUf_nHablLX=lB z;fiSWLbjZe#lKLeG#2XdWTHj|&ae$9|3r^IK4nmOl*ueo2BJ|m?`h&EiG(%E00@{9 z&E7Ei9l&#ah%64Dyh!F;0$+D2j*t>x^7>wx+q@BJX}-TaF=iif`uZ)vj0zT&scY4A zit*`*G}SFQ+KvdSj-^dwbgrN;PqL3JJBquj)K<-#TqAti;J8X7H=R>4Q1kmYC%Uj# zKtW+R$pa5qnM4Lt)!eEH{9Vnkyr_@(mnzQu@fJcWc0cl+Vdk}pGiYo0`oC*+!v%3` z^ZJ?^I0r~r3#F|(g3SR;)z zH<|_&==K^%(UVWcDD>QgrlWzz&p(g*g0QbyOp=lX*`4HNW2n=H4((5j(a#@%Cg}g> z^Uu+pGQ>bJ;ytfQzU5acNj6BXM4Hdi!UpY#WX3puo@Q}kf+vpObWW!1NzE;WfC;o) zCGsbRsd)VP&2liiK43mJRbY;>dO$N$QO+XalGUw{M@*lLKE(}-1SGVWDi$fuz0jJA zDRU3<$rNlB_yQBWiQIgU;D@nhvA7nqFIy#2f4S8Wvomtm*l+f+64QoR;Gz*!pr;j;4r~V}I?_^uj@oKI&k-)L zNOtVuyD~3ToWX2=4(NpM%%A@B>U+;3)^B7-H=X+us6jX>1702Z+ClEIKHewUK{H{u zdGAbRQbf!_loS7Sn@aZsA%`N9Bh(`mjK$Z%su#Y!=sWZ3C*MO;))S8)1wjggS`@W2 zB6Fns_~+kz+5cP9eWdnol;BoX#n1<4_vKSz`&?MlaYzD=oWW2B-gQ{_!l+#gl*ecQ z03uUIc>;eg^@QqbxA*q;N`+u?m^0_K@1u1!4Tw+)B%7GY^(-&?cp-sPs?8&O8YHQT zO-_=M90FIgbH2zGy~~ADi|4K}Qj4EijZEL<3&^@&%Z)g(!@r59j_j=r1I&n=YXXFY z3)7@`^GO0ei}>u#YMNW%^UrUNShDv8&F`fER8MI$!d4DjJWHXxOrL@{67P&MCY_oS z;&jylyf?JVxGJQXscH~cDDrv9NkNxYp>0{LO6F0_r*|3qjH(XYv^TEZ6bOVv*>}ASbmd@NMn38l-A^xE zNQH|x3{ZAR;xFd!-n|>bCCV%A*C_X`zo~rfx1W9XnaZOG7=qL%OSP!YJruN$tvK^j z9nn92Rx_ZJ$E#HP-OpVRcEEPa5BX25!!^*+2xJt3ybTsfj7F)C+z;F9%_li@o2__3JN>^~Og9UqbbR3M4A~7U zJ>!_bFo~+OZ43j_dr(}!IU8v){Pl@Ge z2VzK(Fg^w=(~?L)2k5qCCJ3xIU$)l@T#kUkw0e}_7H;>6)CSZyf!R=yD$WQ$Lt!lc zZc-A}W)p-RvVp&Ul>s4fDfT2cRykCa-WSTg-^9%L z>M|p(0|hXvD;JAQw{GV_DS1e*3EVs*ihv@}%a31^ryT#3*rKUP>vJg=n_ zly?E~ZjZtuEyn)|15KPuAnQVuGij0g;It{oS2je+DTA{_kQ=f+ zvGm$Cz}Yw)OpKOS2Ej}~h>A(bN9*>fCI%MgBuFAzF+RF(f-T6jOr{1P7)kh1XD)1* zPP1~I%_n}Y!vKI7;cI>v4Dm@%cjX#pjK*EbqGZZ~Z@CExF8 z4uwx*{xD$J&2G^#YeDA>Y%>(UI=o4t|Gkal5(GN|Oti&|5 zGcu`z9Kw!lO5;UOC&QYx7-1GQ*S?bJy%EOU_Rv+LX2Dl+C?5ZK5m-klQ%xQ>iBSws zt%3r@5Vf?zFnh(Itou=pK_40S@?>z>$)caVnBo z;dl*3>!5it(JfI!{p*wDh!^EfXdF%a7W5M~Hs1CCSa9 zU173$ags$G>8~L^A0;DIfc|2(G*@V_U!-(v+g{(6DnA2b+5~mByPQWj9-Wu3GRpy_FG|qrL~#(FPA@X;bq^ud~8|Q_2-MgaFi+}kSvmhq(b@}la+LW)G}v&AkG(E z@M42||J81K*ds>koEl8$^s1YM0%k49J@@>$&l(l6X=}sgMIhtd0_-Ckn`*wG5YoxN z;1TUv{#L;@6#QypE$9DOoHU$bgZ-GgNhJdlC{EwA7f1UT!SR{L9kLY)Ol+h_A1u_F z)dPs@4ith?S_h-E2D~(%pOa)BGwJXy5L`v&iDGpotBkE!2rmLgvr##S+2gY-)LB0r z@~EC_-A5x`1^*_uGJ={I}AV{M5V%;Fw0>_dl^M@1m~%ZaZ8aUR4PRhQlLIL8n;88J^OR!&^NPQ(3t6D(t;*hFzb=MH*11!uuWiEnt)6mkjym zb)`%YLiQu`alw2BbE{Oire;0NlaGvz9_(u}ts2<2nB7{mhfc2z9B(xw0<;P4fJso4 z^tw`(8jyRsZW4FA9cfPbKz8lTuQ=0v{NlyKgB9z26(FA7w(X8Bn3bPpeXUoFpVj*% zRb^~6=6NDE7xd+t5d?$PDKi+<6zJrPBw}*Nal%vp841DWL{p_oU=eKKOM^@--Pgby z#D=reDN(G-LHNvIemNDP!WKsMZd?9L&IveCp5C6p+W)u06)*4Kn#4^ zis4zKV)<3cjG~OoAY)QVZi}9g(S{=Rox5c=eVT(XzQ2p{yE>JUDR+0ti9l&Kpyw1;FTh|J&$ zt)Rq2&pQU)8Y&{Cuqwajh*FVHks@BU48Eb4kXV*>K%mMq@D$1@ytSmKHzE~O=w!jn zo!8;b5CAu!CaXJETrv+&cMfxzf;?i>?n68eysi%2ZXye#b}#!vn@|~Zgdm|nC+mEE zgGlm(D@Lnsp98QlFlxjEI|b&KRYQW#;E)nFFJeg_j#56pJg`v38=?NkmjX$P-yuBo zGs+7h{N_ET&CA9ESYnASe|Y5b^p|uN;9S7L1@eCru5b-{+ej1Q=N9Ef-ViCdIW`|J zciE!ZnNQ)+Lg)rAX#O*~$}*fd!-A`!^U0T<`3i8AG6QvA@Jy*@Z98DuxqH3Fq(c5p zNIt48uW5M#8_VPp~9Qv-)xMe2rbRBju# zrCC?@?ccv&842vCNfwVXIY76*{E^Wz$Lt!Fq6FIqlK;6fKgV(M%eW?5l9_O^-=W#k zXEd46LSGdED_F35G1n6-e?vbLUDGcS?WOXP1NR%bsq|tlZwziA&Vg9qESMQ)R&uHyj664KnUJdaLAg7}=n-=gFXc8A#I2`6Zn#7K_1GMUW}GB6DHy#m9~ zriaYPf*(6r>`XaI#9I_QGlM}rp;(b!s47+{M7LJqu#qT8Z+lEnW)gjG&+tms4Irf8 zbiROjOfGVYs(aGv2O(T`)#C3Cu^vX5?r$OKcP!@645^otCtwa!-j`k8OT%iJ>y~SP z%p#uu?M2eRz6jIxn#=+}yJh2s4G}vg^Hp5>Fp3rz>Y7qfuD3L6Ub?~6u_O8e!cr)3 zTZlPmG+SwC3ys<;a-390q%$FRnykRPeSvj^hi6=Xn=UL(-$6c-+B5ga z?U;9m;1g3lRJdrl$q=K<+T;cz?l>eLyWELPK$J~H^a6*?U?%AB-6AzoaIae(X^Ak) zkIjWW@}w-yA_Kkon5>V5q}m=Ze&BGlP&>lpGLVd+aU;kmT*wzzm~Gr@gTmR}+IS&b z@Yyv!b5b~C8iBY+N%BPJJ3v63n~ThYHM-neCQ;E4hvvyYyG$9Da|kN|rb(owW zE-8amFRN=|)j!S!{l4;`pJMm%@MOa2N#Yr5PfAi__OCeEh?D&Dg8IMaUW#X4ivH`y z<54@By}teS1LFqPXv2mLal>xn`qfsw3J91W!mmuCocs_`$Pc@Dehv?&1mszsfByLw zWJ`3ym9DPM*W*-Rl3qTh3yU1je}6sx{Rg07v-wACy{d^>Et-gWL#)g^w6hCN_h?*E za|Ik-hsrXa+U)`@Gy&{tm~{r{xP@w9vrl=1?SJ<~3Yn6q5z@eIJEMU|9S*bt#n|Zw z-U0)dFo9)mmrFC(%B6#pSb9SX)meVmoapb}gn(PTlWIMeH$r;I7lxePP?1+2ixX>r|EtdinGJ5CGnImj5+`JW)ZoIdxgV1B|$d2th$rJ5L*s?c!rSqzI&G7R+gkYUa=XOA)?; z%kw-Aeq-svlomA1+Zq!mQ*84dA!Bjq^e=$3iP4G&E;J!(Ag{1X*{JCeydHhW;A|Ae zd*s1|PKZ9)y(6J^c|24B;#@y+i));rBu4dRvt+AEG8bczTTHY^vd4>W%`?E_%$W2V z?|DM(;Ni$(vT(GfC8EqQW>57<8Ge_X0bY-~%C|K~fv!c;C!ypcoa_;dn{T&^3|k#2WdagU>NH;DyGL;aGC0huT6x(qRyg4e2IG> z&iU+r1^ts{K=2S@j=edsSwJAoYlSnm<5FawN{*3wPi)T3rNp~@TkJcdiN#r0l>K#p zCLKpsJ6K5iCB&G`g1N&Q(v@CWaT%6F=QXiG*Y7-vm>rE+Jj!~@BzNLPRyg)=M8OS@HnIejtqv-%W8_+T;|I8`nm7cf zNTE&U%@!J^2D883JK| z4?3riJszp#gX0j)iHyS{7wRqQ6n`}6|DR~bo3Hozb)YKF`@D0yZLZH=&FBa;{VwoQWFQGXP{k9ojL0LRk-7=qQ4+B={09UU1VutD3Lh zy5%53HoXNGPKscIB~B(Jg7Frpfya$4IS9-)#c<HAX+x$0x>}-W3d2FqZ2B?qvjje;h0vr{QeO!Zf*{bhcWD*GiNulCKjP|^ylB= zPVE?5Ve7moC-$6COh+w&EF7XLH=7Ju1$vEetmEBHuYY2nXi@g$Ze}H!>dxPH-%*Jd z=7GgXa{&k;vhmttOHRzuefWB>&}U_I2C3&w=K|(qjeWfIb~r}xdC`Ze#jw`qWL*hS zN**Q(Nf{cX=4C9G%9^6a#`$*tS7_!*BA2ra! zQs6i^_yd721&dn(fk~-}2^JA)vdo!f_EExf{_T_gz%_$@hz=9`PCn|BHTFKU?@}Pp z1o(0}I`oRx6enb9>s7=kj%kF`ImFv_@R!E{Ch7E-}U zWG#N

3y_wKB@FG4N90DEy2;_KJF`exC`FFgH|)$$6?iWaeS&_{TUICrZ?Duf|R= zvkmC5<=28t9wXC~KwtSgnwvs6%~{+CEFkfCN0I90L^R*fiT=PQx2evhaex9^RN1!2 zWaz=PIT2i0)(%woRVHl0TH5(m%>Y;{$3zP-5*4Dvk?up$8{zvp_<)8dZI`Gw9{*kC zUXe(o+_|F6*ktNNb2QvoV)BZQ&5fFQevuLrIrux{Bne|k%f7dN^O-7h@|(Y;y0X=8Z;{s%P;u-7tPN0$RCo${+S&vhDk_dA~4EN zo;>+)esPhM<}IhI;osGeN1qx# zQs4pQQNm2gmCB$sVF-GcFv->^sC(I=c@A=nt^bsXu=DriZa_w!%I;uQP$#d63e6^v zLN#1_CR{^a3S!22HuY71Ka}kqFB|Dp!t% z0EmhvAqtsw1yQ_Yr;0TtJY4cfl``Tn8Zk5~ zIIx5x4I(nUVi8n7hw_YECd8ZqF(~%)ZWof&8ZAY%Ql2s#t63Ce?CL56=M}ohX<3r#OvFR4}^joA!be7Yg;5@y-33Q5(1H+ zL9^+pxPDIcdkyPou--&C?`*|R1~>V@!!N{n;pYAJc&xXurxG)(X$TD1|!SPKGtg3 zIKvF;q)Cj-_1GLTH)bZ_Mu?pR!6zn@we(>em&9wFL$kXyn9xXF<3pg%9Q0ZdSZv-* zmkMF#8n_%}x52N!oLHC^Vw7d(kSx=q0{!Cw>|pFO24}_-fSB>cH(-i`BAmo( z6&E&5^Sq|kpd;gqnW9JQg_P~~TcRp0{bACJIr|_mOQ#gQtK16}xyIy*89F>dkOdD} z9EdqnghN3e zqAb^U=FMXfDo%b#;kKE{8n9xKC7*PA9paj5$oUyxj@3PjyiX1Ek=cf*7k)*2k#~~? z(USC5HN_&i%6C&8S&%ff@Jz&cI<*|YkNN|av%6DN4wiQLhdL*-(~px6N97tzFyZX( zB{JrgE#V}x{E!Ws%5B=?WQoSO(X**XCc5Uzho0ar068RDthgIERfD=c>9w!}zngU@ zthMEAo*{rViWx|*3hwLtD2(!QeGpL<-x*8`6Q?`b;d}0n&@!Zd9DT6kDtilNgqgNQ z#{LI#F>50pIUr)|S;&#F5une(+=;ys)uq`8$)7c+IAhOY=nd3uVn7HI9n{HDYn?0Z z8#o@}3R`BwkxYJEV(UyanL>M>yO6`r8{?#_LHpX2P3ML$h97I4BrwQT^JFPS7R})1 zo-FSRd=PZD;5=C|U4+7RHTE3}(b+J3dLR_Y>NYdmmZ7Zd6!Y@X?k1%ktG%YB7gWW0 zLFQ^TA3AX0z;;YYP5s`Q5XZL-@WNs9EPaNiAIY5_;`~3r>H~CQi#Q#UM|L1%sDXvV zCdCpec!OfpY!jeXgZ3pl8zmIUpjCU&HMSjJx!{3@-QJ6!9=}}=l2i7$!c+$+7gz(E z5xI%U5&;~K*$vt2K3*g!BGth|W1}g}ca?^L5+gt-A)u0l$-o-dR$Q3(mWcc#wjiT= z-Gapxb5*s>YavTVaDZCvpDSmqj5z~`0NY>~hDMeJqvN%I zjB?WabC>$a5#?(8k%9kUd%olLuJ0@XlflSs6SsMUr=*3%TylSB6~QA;h;9%G$+BXxNg&) z$!*w!t(6y?j%|8DrIiEtpe7v(iO-A~2|dl^j?(E7GBqGXJKZ2__rK%h0{n0ea=YmdJI zW%)qIrN$y~W3|D~S5@R+e^1PS-Zxpy=NuS{67SI(FQbEb zy^$pw+uSN~_}kk@mddja<_1%XS3ihztUKt1@p9n6JhCJ`pt)Ja=9DoZ7XR^x11u$~ z8qQ54Ew!9O zJxzfGEPl*GL8jbJb)uDaTX=owj{Lp=e&X1T2J3A(YTB5==TGnaR8V{ALUk-p(+c z5IoZfl;{KfatwPr>$$!$?$hl85C({2 zE2i%&l!nWPiX@yXU0a_=&GE<#*$v(%&B8*-A@P(YDKR2NDC zM+F{68Ptq}oth*Ncc4EVlYUg;m?5TTG)Y%)k;!fhs)B6Fw+9V8Ga4Z9y6 z1tO~s%28Nx^-AJ05g+FjTRMg8pz;Hk2L#;NfExcmY*_r%5S&jIThM+4g6-%Fm~c_U z&S(z7@spftlhRA$=5bY*;!heLCT4SmxRi%wCt7BjYepF_9K{uXfq^gzktBP{e$@pt zPmq7ef{5mt>RN1U+4wACPu9YYBKXVT@YA(<5h^K~u5xBn5SAb58Cm6`Wiep=UiQ{<)p+IkC4SBgBVsF$?aQK!ipr4g2Am(3&ln)M5pxr=lUjaW* zB{{JU1*0H=*$rzM-cQG-etkHhHoB#|JIXD`bd$Q! zDD`WaGyW@&QW5`a9h(;j;LgMMgY?R1fnz)ni8Ni!|NZ4mdNX)S=1vL43LWuZa9V3# z`DfCM$s+aVX@Quv(?az2g~0K%%a^0ia{aYjl?@3E=2nBhvKSzGu+lMK7O&kUPUo~+ zQ_9RCES9;XKyX#&I)SXZQalv`Ra|xyf1%gsLQjaS$+sD`(9^Nz+&qU=U%lzvm=ekx_1S zJSlCTk=bz#&8}BvyHAv0E)#7QRvf^#RXe+Uw z5oy)}jV-wT{L@|cIE!x+YGXp>!?|xhKWEpmVN`aQe9}^u74T9sR`r0X*DpaH}v6Wpgr!HRq=`9jXo%=f3=oabE zsKXwY^ola~E|)95oJOf^kdn8ACi^c5b1epF(sr+MJn%(4o^n(Pbbm#U-6p=6Bu(x9 zl0a>_c#$$)zl2-mPQ8|oQ-N6hQ>yQ4dN_6pK3JH92UU{PXY#`}USF7&S(UuNx`I$` z&ZvC2;BOp)(Il%AokA+HOG^a~AL{(i;Z~WvxMo4jH2{Sdz=+Vf$@%%vt*j3&UW{ci zsg;4_|GWhbGj(8D!quw zII&#RS$W!Z{tLQe_ha>kUbz&%w+k#fmbjB3b}pLc43%$aqPn}5)ZG% zw+V=LO1rzt$f8U(i2jNH<=o$^sYuIvV~D^_sSp=bvqT^27IE)Ok!kcogYY$escY_p zpd}Deb^1UgBv1T`HzKk_|5^}k_3Om?n|1DMgXA{vXIJJvatWcnW;Ah+&pFQsc?Rj- z3E+-0i2aC!< z-)zAZZ;8NtVbkl;vf&;t>L$OnH?*?1u|l9;G@abHYiFM& zI3>g~pVO3=^0eMu$#Rm&kfFJghMhj}YW;UyFBXG!(GkkC9+B$t3I%GLA%i(cS z97otvw_L@O={?Q1kPW3psE;Y;ze2=VZHtY*B237hNRd@EVxmRnNU9`}lNRpDjWR%J z55qypiXV50B;GSODktxV$?T^!g$o10+dNS@{v1VDR2~Tg#M+XUfH?L)$6_aP{n|Qz zZgAU{Vr=~`&RCcEJMv|&1#+PV(4HIMqdDX;(D#=!Qbi}L_YAG(4Lvx->^2=ZUd`W; zk^FG9)7unF8`i1;2bdc2rE5B<#3=KcMCp7K7`gB>5P7YzIixt z_rCt z?&H0J37DF2cwICO_Z=3twZ`;13T4AojXju*SCKYZ^ zlG41xRYu+EpPaF$C^r8^D-pJR(O%fRtM%k*EW=%hq#I3uovxr62~=P?65$1SLJMn}TY4Q@$7jrhEBs^xvGAj!2aXgC zdP7~$Xvu2jzQvXM!W#XY<2am*)>~cmhm|=Y0u4vuBgtnU5~Au$aF84~2teh7dqxG9 zke*aNZN_){obFH{PCfUY4tfJ(0C*yOLpKlg&k&Ji`R!Q)=5FTz%JRW-qVEgE3{k(HFryM*p;yHi;uX*^M)gpSrRR}Y2mPX9rWKyjdX;!h#fDVUXmdEOO~yTtK9Jw*+?$I?<- zV3QIS9}Ziqk%HM5UL*EVgpJwy^Aa&{KjGAQ8DCbMaV=gH3LW__Vv%Ou)247r;KHQh zb28mOYTJjWuUGSdjhauoY~L&Qf?_n zNxP5X(H#2)5L{9$;do+R|2I5)CM&#t?CI-o9Qx~UnjEL!|M1Xkg9}%q|N3tN{j@zL zPr=4tutUE!@F#jX_$%Gg&Hgj+1Qi|<()`B=MCG$>{&ty@lBUC9nPU(l3Bpehgs}LsHXZ+?Y;+$p^ySpX?e(YjMsIgA5C0yO$BQqQm$hfOU8H_c-4i`l9pAM`f4>>D4X* z5-Z)n3ynDRbSpDNf5AeQ7G|hkqcRORQFN8Drl-A4Nf|s1^)H7*rVOG#kC7y4Wa-G# zQA<`xVoxH#G>usZ${vc0RTV?6>^?%z|sw_pdGz8(+Xjn54(%HLSg@T3r6)idJI(TbV_Fnm zHg>OZG4ylhYu}8HO&dGcEt$Hedv)RL&NUsw#l{t@wN?1HZpE_Y;+*dGRhZ?XAnTW( zurN4BllUcwO1Pku82XyH%bc%j0(o2zkd!(aB<3;pS1m(AvO(7cC4^Z(koOy+ zEi8vv2BO~LrP9U{w`0PZ&NV9_H-F;XDdZ`nR8I<}j?}7`kY^V>?D#95)Y3@|BcHE&g!Xy>^_u`Y^&*5(}j83!Ax`ni8*X% zdFPOmm6BaZ;1eHN*Rf$m$Ht~jT1PO^qB<$d**GUKH8AySXXE7d#VeP+h5i)OKDT4d zl8$v_DG|;iMH90vJ~x9WWwIzer;w5@KFY*9CgU^PCXr{oo6TZYxe~UxEvQjZwz{*J zk6me&sLPc_nanOHd&o@(+*MYx6}hwAvZ*Fs_N-@TCELGn#B7aCQ|C@?Xse&y*i=1x zO8x9fam%k6Mk&f8FVB2Q zCCa+a#T`q!*R`*Lz-J6d$Kl51?RffWf%8{HTW&erbt$7yXGt316X$7JWU8NG!n@zFUbt#$I0YT({G;%Uc*5+>_up zTHLO%geiq~lS%o_F)EYj&QB9SKJF?cC5Y3Q(w}W~JzI!!OH6raFWvXJYjG|ypSi+| z6WPC6wl^%gtz+@}rp{QxH5jkS5Jd~hK?Ljop7Fwt_1kzREA>ymq|QBw+wsB_!NSZ* zcf|ybNs$UE(=wd#G%;R(sEJAOhnpC|Z{#vrZNB5o4|AEC^yFN6;Y4D{!m$37CgyYHg$IOWGrQ1c71Kb+*xgt1GTkN=QfI^PTVG!60Fmy=?`pdeKvJEhjy&$ z>c}GQTN0sKmv*jOjc=`4vSMi-{h%?RC=GL)8kf_ZGaIHRjBuK7pArQS2!yp^cO4p&4gS8%f%t6}a1)Wh3bDaItIslF~A% z=sj}YMxFqhY-+_rjs zPgzgdA1qXLYuSR)B;2zxF&2+kj-79gLLhn@+5CQ}U1cFJBps1**C@R=!qJpBLf}((81>ML-v7n-&vK4jPup#!s z=J)>0y3aZLIoAXG{PVl6XK#}i_bPY!-epZ$GfB5{ig^7hg%`GSii>zVkgs+wE{U_O z>#d*c`q~-6dDXS^vpPjx92E=(EA39f?mO+v@^zzGF#8#oziZLtt^+K8iRBwyI60U- z&zjlH|AIODZ2u^$OXa#a6TK?80A6YGmyIbi+ZEfF!?zE!r zmOtN$w3F?y^R37PJ5W4;xyi3cuk9XSHO{J=!m?UB-s2x)MYbv#VvXSMwl2Eaa&Iom zZ(e*+uzN5ouWJ|&FN!(^b6UG+WEJHX<_0}hpi?EUjQOmD>@ur&VSY)WZS^ZE&JD&| ztx999_C>|h`9O3&Uolx&T2#rMcom&HSZ#~h6{u+B9$=s4&$IIVKUr2mu%OHe|EPRQ zNq#e>)z!}`&N|m)2N+{6zLtJUcCa|VtfS?cP}97iIE&SNxMig-9$_UkUulmj&MM3= z>|?jBtQ=`SP*_q_T2xk9Tv6PQKl?YzT{5G-X_ggN_=(k#ds)BtEz4XSH0s*XmGQbbDBCesiT2 z=-kPFCt2ukSz>!j5=m>n$3FD?t_1oO)CD>}LZl|@#Jr-fCW6D-NEC_YIam0HQ8 z3iC_LD$3}{gO;CHW3I@fsfEQA<>$NnovrAHi}FiLi_0s^3X7-PDU1K<3Ut2Owj*BP z#dyp8k;_vWcFHO)Ehi=wCFQxn;w<~bL90z^AIom*j@aVz7g^CRpB2?;xja_Hvth1| zVbz6&MLhKTB+Pe>6+O${s&tmyj8mEd3F_7)VElv9CqZeL8L<-gq>!32tO z1xhZkE&nC1gosa=yo2m?4}SsLV{K1PFDkeEgY3lU$_VS^>DAs;b`}(M8fL|gC?w>W zR%BvHCJ$k9F0=jPt;j&})8X#G;!?iqeO`6*R?GiNn78x1+W8%=Kv@>6e%WQ*=CIXk zT@fAL&$FkfxU9Uqq;p|qF7IPT#MW3X%Abvjn(qy7jxhp!*Jc{SIrIvrRo#uiucEDF*ac%OZ^U{WYyxr2rMeTy<$mnrC-|sQLQI_wf zaBiaT-5gGb__KiS>UR5zYzCt73fx zi!Zw0YMoNJDmJ08IAKacap3`vcSKR~emCDG%)fn+-K>J5;+H)!ZOXdFTgAGmiC`Dn`byOd4_^i1>gSqo zpIlO4$EB71%@bI>(qmhz!(AN`f|ZpgtU$?2uCR!~c6!+$+y4OfaD5-{xzYB&Zrkqr z-K~r7ce`(I5h!~kAuLe-TeO!aU!y#}mt*+4oYK}MG10Bc-*gAcXGcePwobXpRh z8J!j7>mK9JifR=o`y$G1@jyK1(lGzWVV>|s-ay$RuP2rFIDa@69w?9Vj|yw;jyTWL zfs02tS3LhPcZ~n2H#fcTD2J|(jm;`5=3gb7xVI|I>-&T6^{`vG`uY8XygB~CQI>D6 z?Z3#|EfAH%D<1r5jl9KNc2g`*vDe!>Xg%QKrH0hS+~IQ3qhSolbpI7rSaiJACi^=p zHK)Dp8en;c2K|F9kLzA5tVdg4Q>uTP*B^Dt>wi2o!OIsa7h3Vfh54OtN-F4F*4B=T z*uy(nc6gwe&lq}lw#^B4pXa`}p{8kJ!~CvMmqcY}x(;XF(0_FA0mJ$YANx+Go0kl{ z1BOoNH(~6QMmze)kEhIR;Q8USg)?WySdZ2;O`pxfo#v*R`3(OYE9TZS=W~ zS6J0i3mR&s*LJmBw`bVCwrO3HE&JPy_B@=)@NdrGdtEHw<_v$piYh4X`mNQ%_eu-k1c4UQQ@W{3EjRseELhWPa9G|6xy9pm2HCY1@iAx%@i+%&gOY5M?`JEA6yn5-dNTSB~1& z-oL1gJ2K6~OR}!|2tUu%b86@3TK*j!Z2zJTcKAul+Ud2P36Emc>Su*V=XG?ovV4Ud znY0l}MVDGJ;?9j$c(~ahj02IW5O&Ftv+c8u^}kQ*D5o*Q;wgug$Z@whqHl{=&U z-JJZ~;1@ZpX|Zv+{?6fUyN@d|YgxPSK`z!Z|8o)Ho)yXdA$eKRCn8)eTlCH=&M$1? z4-~HAF|qaMIfRk}u zsztEiwCmg0@9!(j;tO|w^Q7@;x`3ejPV~Ra-@d@@=O!ZG7g_$Wf>gh|ptNmKS%c*X zxA^zz(_b=5Vj^C-JmT&S{=9{+GNl{wuhhab9M-K>4c$uHvHn%3*QE#lakI20F)=R{Fgi zSUf#4+V3s&v{}3}BCN_EUzBTGcSf(|AwxM2LrS(=c2o%$x?L{*D$Jom|4vtWSVt=| zJ<`6aDC(by{3!xo&&9!lp9=k9vt0h~3rn)56^*g{sk|y#99uMmH8jy<{caWej~9AU zijEfsijNmg-gsNQe|x-r+MYUO%A`jh>ofU|nqdQbw^;Vx?0`EXI+@q3iZ{gZRYQS@ zq=XvlB==BW{ps-C-(A>e`?Y_red$Qrd)s*mbJ8{L`*XefXHT7Q*)3~s`g!%p&y%z< zEc2q{6~8op`CI(-zN-)Rs+_Hjd*{sBaKk%s>)yzD z87s<`eD>3Y`?RsJKBi;k(d*tGv2)YrVJQ_$Kjh^w*Eu6UTQxlR@mEjG?lbI~uuZWa zMFvmWX;S7Ql9L+@|uPx6Hg|@^?T*r z0daF$HD8|cs_(m~^slbDt!UNPLla(a{n292%%iytW9^d(cl2Gqt)autbz{8m-aO=; zJ-znjB+SWeu`YE?=9FKDygvU>!>sg^3HN{V%h)%^U)*}${X;h#oOF+Gmvv#|)6YKn zM*B6Jjsz1I{M_IQ{E&Fln->ngbnEI1?|ER?_%D-hnSRsgu=fva-L~$;h3|Zk{eG0c z!TK!qWWt3Dqq{Djbi^|@uj+y)Du0^vk2~H^J5~9)XWyL-R!N`lCpSDz%?ls!9D8b> zd;a=e$Cejt9o{ss`HQluK(F3o){a?t+qnno8*WKBnQ;7%!@GucTY2M=ldttD>OAl6 zo5HFtp567=u<$?ZAMy{5AKY+W!pX$D?*4WEz{~dT+u`ba@Pp-Zem!sS-BKBkeJ|v9esa$CkNWf&>%HQ__Eo($>>J~o`hoS;s4*kk z+NmXN+9vn9AkBL?DRn8Yu!Jpbn>^-7z<#Gwirvae3g;y)yV**L7-&ToT1j4#u4XGS zk{4R1vODUj^k`m^i6(iBWDMUP;O6MqEf$-Td;=|BmQC!c`&T$Ij11x=N5r29?Ha(Y zgbFLg!>+{AOdVaorlhH%y;Vo;q!v~?Wz}+vmBK5#iOKx%L8!#tF|I^jgh?#iWM>Ss zV_ZqCo2^7|*LH6HnbOQxw@kIIE3Kr|3S0k-3vXXV-l->AS=njUS2iytCGmAQ$~bT& zRMp_#5N*G7X=BFh(7tvHLaEG(P^x|Cgv1Wy!|NqU9d~PIViw8mBs=wTwT#SiS@+o4 z*;b@Gv98LUl;eaUcdf04HFH!Rx1y_nd~O71(@y?bu-8h7q4|Yt?UdMNE2+q<(o&1p zwpT4n*z22W@%O+(RVgd9QV3;IIh%Pjkkpy{;;`b7D=}`n@=U7aka#wAaf&GYn=7g7 zZkPLGcVg~6c2c+HE)~3WYgkhEBcVEM=A0h0ZFhWF#y)$7JE`5n^jXVSa_JrU3FL}I%;$rEgI z<-(?>`uSsPnuqFDwB#I~g0_jV0^NDFHjFP3%`LS&F%i+8yyPB3S*@>kzfjw_pqfWl z{VuGT-*m1Od&~-(Y9;3-Sz%)%BH!x}(Jjo+rxe1L+R6DzR-n&MmW$W3YiC#+c?`}U z)lClYT63rTK;MnLvAxkw=9R^iE=75fC-Ur}R`Zy})N)?qF*})8*OGZI73d#yB_$V8 zskS5r^s+gT>-52)!HLRf5-i=o4)Wk#Ws?yW%?7>HyTUqf3w&YE_hj;gu_8yy8Hn5MU z$(ml+n`Dpky#xDL*4`DK$Wr_7>({O8VObaPhR=dNTk?|j>`wImlwl{@t%|7LhzXTD zyG_W8OmL6PcV}8}tnPbF%X52dZfdOk2JA3* z8{dow|36D3(!*vH`Mzl%VOwECY4Ynt8Re8X@z{(8d>Q`8tC(OUV^6*~6tx>tce`V*_}c^udOF5c^=`X?ZvDBo%s@6D;t9m*UwMZp zC4PaojW5#|RTvw{Kkm&9@O3zufl_{@dPk-O#*U5j20RN2V!Xk`m{MO%FK?>Nzig}O zr2_*sDrUR7bBcZ(a% z%gEJr`&wGxb&ae0B(G1+3@c(u;V|Bdo6&~%lDgSeVP?(@`$S@@{Yp|?YP0{Z*!uZR z4fS<(H4VAJ-W)e?THWHjzPvxsu)vDl9_JewZBIyy8#lg1L%;d6c%?gkPkzT-#+83k zbOK@ZRrT;Ch548AeGz-z;af|18N;_Rir1n}w+!^2>dH(`;$^8dVeySTzMSFe9q>$b zElCYuWd(XXX8W=>hTaJ(OZ4w`olXi=?dACRy{-{`cwINsGbj+T*R>>OBm*NRY-pRi z2i7;#UPNuH>k6%##@947)lRRj3$N(YZ`!=trlyv~(`)J`B>6WF@B|_^dYfA%ZuDBe z+v&l3y@4nz>Z*BTcw=h*tjDZC^maXVa0R&6A}KYyjm->-*>1(R&#Wx2p5Bz|l~<0fX-rNJ#GD8_-8wM%L|CTxH$y0ip}xK;qszpLGxTn(dUiNZ!85vKjMIC$`Mn3_ z53jzkc2;#0?`UM?X3S@2=v}=t9>G)P#zvC|rw*%WoISL5{#?$TSJO1ReumlAx2~qT zVQd3$w$;oSTHDyfe%>RPp||83GrAPzX4E!@YS35NWprt3SXgsO?*E^a99GZ!Dz!BY z|7}H0L;lw>jsIh6JHEbdA>H-g1^0hkoyRO}n92LWXRE9^8?oeo~omQ)N)z5s?{22|r?K61zSu&bmJ1;a% z&YX$vcj&`?0d+NJK4#&J+WIr@?ORvhH2chZS^0QGHc-ilYZlbA zaL%7~#yqOVj2zHVz2M9hsjB70xu*JtGv+Yh%wZhB3e%TX)STsP6<#~Nk$3%@YPiRu zj>1@;#?&;_a&N>%XFap_%%K^`?5}Q^K6`QB`m@AnV13i*8ZA|4Y}}w>ylH;sz4N&F z#kprh?-HN+xcLhfHl2NM|N4fr6{HM?*37D&e&%64c+805|2u4FENm!m9~0NJ5AI>r z4Lp0Pt2^7k8OCivwF`Jt`Yc^Ek~=wSr`Odu&m+!Qr;#-cdOy6HyKesTfE_t|aUuCjL__@oJ)EdHb0(t~&Tp!nS2Kv~rZWsj%n!{(=WeI}v-!;9dd&2Onwt52 zs~7Ns`I#pvkGr@pV|+D(eSTB#`PFrciPxE{rH5%XGX`lwaqL-+ThLJ3R5Pr)aqby| zFeY>e87??W?V1{Ds(Byo%&W(kh0_|F)Nf}lha;S4k!L()?9ef1-dEGmz`OJRY5#v3 z6g;19(n`>uRn@tSoFzx+P@VGsaHw-%(b-}&wziJjuhdjOz5YKO z$wTzfH5V-8__OEue~#0$oBwo$4z=aqPC4rZ`~Nyv1LSOT`~NzeKX7@*nvd^4;mrF+ zpLtgeSI)Y#EMwzqXVjee0Z8as&lxj6hxgykxO2jPt&~FjZ%-uu{gK&!eb(_`_Wauw zB;R?Iknaq=|8kVVtS24}lYifC9t@5f6xujBH>1gUwlT3d_kYU&i^_BV?Z3&F%$nJp z*EE|YHFTTSy!sh6-AkhuRo6D$HWnbu;p2Ev%i%^-8>#q{-{j-DCmh(M)q_sVNgwSm@t>k;Ncz*iR zTUpj5Ub7f^B+Ckx@j_Q@Cu>r&WxbNw$-2G;w~KY@WKFomZEb%w*P8k?uWekL$LGw$ ztyY^$EIveQ9oSOB+pyf)yS;?(_MpB`mhg!YUO{`h#M;^vX4Mr|SVwsCv#MRCwO|x) zf;M3VcPnnIR4f0BxAI=^|N0-z5B-lK6begv_@U_*#aO(-#+P(B+uNY_1&!^IDp}e5 zMDbH((!AamI*u3kLJlwvMdd~HLffaJ&adG|W$CU=mAjB1ZmhH}=11jUYSJq(g`XSw zQC+w2qxwF;kB-~MkLvdnKgxFxKPqoOKRW(x<2%N8jYo{{8Q(X4U_6RL`1uDvDld!7 zlppUfa^of+*2ZY$GtAuEWLdq;_TiXDnwv+svz9-;fNJNB*b>(uL&@5PN%$P9zI^U3 zS^q-*vwZZs^c(psJNMg@mq{lYlZ-8l-0~kfFWK12*xHz4Of|MKrWyGj z#L)QxW6;>vm|<*Z%tZBLd(`;gZJJO&6{F(S)1(KZ`t2O#KWh@d6zB6%$4x`+pNASB z4aR2FahIavc?EXCwHS&c>iCZ_2ERbn<45E_>lD9~|7qkCUKV$$gzA@u$~PO8FVom6 z#42RUT1}|qS6~L-iFvpe+v2xoyN^tiE<~+0qp%$=Fxzjzj-+>D7Jh&lPkhinlrJ{~ zgzBG%?6UYItkoGi<2g9r?0*sOCVdb$;XE3>8GTHGd+;&56UUMHUHBuigNpOJsPjHYjaL^z<)0RR1;FZtDVT%fkIj;iM@ldd(+L&c9T7!KKlDrb@L5>z=?qRP1r)!#Ro?Q2o( zzRT?2Y|>lI{%t0`6P53isPgt0UqI#iqVXkEJzq8ZU&q}9=uMNpu9Y)BZ$R}A?+b_W zdlZ!qZ}*1Wjmn4jLqq$YGd^$JXZ*YIWek;zYTxT7{T`})9~gNHKGcrSQ0@2{b>4SI z-u@2N>m(|lA5rl;g~}(4K_eqk@$jMYNkX+J8I@lv)c8+9T@!Or=RJrS_z04v^#)#u zU!mst6fTxEWQSmr=(Z zMa_#ZQ0s$-Ox2D`?2Fxumti*P7f|i`2DJ`+hi$PP7fp@-DpdQ1qPCAh<X$ay9(y1mx2B`&a|!mrwW#a+`^eH^9Y-Di8>&8OWWv&H zWuV4S4l?wuGE}{)Q1O~zoQgK-+33Pr)cJE!{nv!*ucgS+X01SminSJ9_$VqKJ5cp` z+-%>6JxK3I+A)}Z>~E>u5kG3lMC^PWYW z_cD6$2&z8+KsSDfs@KODhMyY0F#EqYerLA-VA4OE^lv8p7b>6An2k1*c_`-KQe1={ z{1vsH{Dq2R5`$mu$U@b>5Y@hJ7=itb!;E85`zNBtTMg>G1sIM?P;tA$?7z!we-Ksv zc2rz;q2l%es{DhfeBMIk`w^;~n~;P{(gZ#p!X>d9R_y<;TcWu})(Sw(aD^dnmHWx)3$4??laq zU8sEap~l%!R6V~%jkjMh5@WKR@>`(BONL2vH%+Ks-BI-&jG9;DP~)WriwS%!Dxcd6 z9XF%)Z^I~j6cx9pQT_CS+0Q*mq4Qor_0QX8|NE%(j-lFn95vr!ikx*j3ss*%sK=9I zF&^ij+Iz9_7F7Hm!gzcR72ns5A7dQpA2A-?#g0j+__Rlz-vzZE3^UF|jkC*8^JxRB zAMZfb=TTJu{2etfPNL@9PsoyE{feq*N{M9!u^81~qfv3HMwLGs^*H|$RR3>4wfia5 z@h_s{c^DPH_fc{G$oMI$eqUe*{1Vl_zEY>YZBY9QQR^Hx8-?mS1XbT*sQgBv@*j&T z?_5+pr(iD5M8)xDRQvBnwR<;eyg!8ta6hWN@-ipC&Zu^FL&blTahkCa6WPAZxW@RP z@mb>`I?j7L%V{cMb^aMEd*!1f|zU*kCAEaPJ13RL{>Fg{@1WqjWF zs_{MJXQ*-ZgYhraxQVEAY=MdsFAas(hYDjq<7nd)46S!2&4S;-uRci;VqI@tbI@H(qI6V|>WC$M}}<3)J}e(-_m$NvEO4 zbv}mX4JMN=G7iL+q^FqlLgV#D-MFUXpF$n?hVcvIDPtlJ{?yJ+sOv%x)cQKaIMz7X zIMY~ZsCu>UoQO7@S zJcugi80xz51FAk&l~YbKYMd3L^6!ZnpTkh`n~s{Fb5P}6Xk3np+j`XcdJm@H&hp?FaZ{XwT?(bZ8pTrAEAHjSaK7ea9F2TY08rC5

0&L3@4Mm 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

bs* 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