diff --git a/demo/DemoApp.tsx b/demo/DemoApp.tsx index ad72cbf..477ff98 100644 --- a/demo/DemoApp.tsx +++ b/demo/DemoApp.tsx @@ -39,7 +39,8 @@ import {Await, useAsync} from "../src/Async"; import {NotifyErrorsBoundary} from "../src/Components/Errors/NotifyErrorsBoundary"; import {DemoFailingComponent, DemoResetComponent} from "./DemoFailingComponent"; import {Tip} from "../src/Components/Tips/Tip"; -import {useKernelApplicationData} from "../src/KernelContext"; +import {useKernelContext} from "../src/KernelGlobalContext"; +import {KernelContext} from "./DemoKernelContext"; export function DemoApp() { @@ -74,7 +75,7 @@ export function DemoApp() const [failingComponentsCount, setFailingComponentsCount] = useState(0); - const [kernelApplicationData, setKernelApplicationData] = useKernelApplicationData("customData", ""); + const [kernelContext, setKernelContext] = useKernelContext(KernelContext); return ( @@ -618,10 +619,10 @@ export function DemoApp() diff --git a/demo/DemoKernelContext.tsx b/demo/DemoKernelContext.tsx new file mode 100644 index 0000000..9b6966d --- /dev/null +++ b/demo/DemoKernelContext.tsx @@ -0,0 +1,6 @@ +import {createKernelContext} from "../src/KernelGlobalContext"; + +/** + * Create kernel context. + */ +export const KernelContext = createKernelContext(""); diff --git a/demo/DemoSubapp.tsx b/demo/DemoSubapp.tsx index 0132755..7808305 100644 --- a/demo/DemoSubapp.tsx +++ b/demo/DemoSubapp.tsx @@ -1,7 +1,8 @@ import React from "react"; import {Subapp, useSubapp} from "../src/Components/Subapps/Subapps"; import {Card} from "../src/Components/Card"; -import {useKernelApplicationData} from "../src/KernelContext"; +import {useKernelContext} from "../src/KernelGlobalContext"; +import {KernelContext} from "./DemoKernelContext"; /** * A demo Subapp component. @@ -11,8 +12,8 @@ export function DemoSubapp() // Get subapp close function. const {uuid, close} = useSubapp(); - // Get kernel application custom data. - const [kernelApplicationData] = useKernelApplicationData("customData", ""); + // Get kernel context data. + const [kernelContext] = useKernelContext(KernelContext); return ( @@ -21,7 +22,7 @@ export function DemoSubapp()

UUID : {uuid}

- {kernelApplicationData &&

Kernel application data: {kernelApplicationData}

} + {kernelContext &&

Kernel context data: {kernelContext}

}
diff --git a/index.ts b/index.ts index bf6dbb1..c6b073c 100644 --- a/index.ts +++ b/index.ts @@ -49,5 +49,5 @@ export * from "./src/Components/Tips/Tip"; export * from "./src/Async"; export * from "./src/GlobalState"; -export * from "./src/KernelContext"; +export * from "./src/KernelGlobalContext"; export * from "./src/Utils"; diff --git a/package.json b/package.json index 804f2e7..6de686b 100644 --- a/package.json +++ b/package.json @@ -1,5 +1,5 @@ { - "version": "1.8.0", + "version": "1.8.1", "name": "@kernelui/core", "description": "Kernel UI Core.", "scripts": { diff --git a/src/Application/Kernel.tsx b/src/Application/Kernel.tsx index 9d4e343..e0cf4d1 100644 --- a/src/Application/Kernel.tsx +++ b/src/Application/Kernel.tsx @@ -3,7 +3,7 @@ import React from "react"; import {createBrowserRouter, RouterProvider} from "react-router-dom"; import {CurtainsProvider} from "../Components/Curtains/Curtains"; import {NotificationsProvider} from "../Components/Notifications/Notifications"; -import {KernelContextProvider} from "../KernelContext"; +import {KernelGlobalContextProvider} from "../KernelGlobalContext"; /** * Main Kernel UI app component which initializes everything. @@ -15,7 +15,7 @@ export function Kernel({header, footer, router}: { }) { return ( - + - + ); } diff --git a/src/KernelContext.tsx b/src/KernelContext.tsx deleted file mode 100644 index d763a72..0000000 --- a/src/KernelContext.tsx +++ /dev/null @@ -1,111 +0,0 @@ -import React, {useCallback, useContext, useMemo, useState} from "react"; - -/** - * Application data setter function type. - */ -export type ApplicationDataSetter = (identifier: IdentifierType, value: ValueType) => void; - -/** - * Application data dispatcher function type. - */ -export type KernelApplicationDataDispatcher = (value: ValueType) => void; - -/** - * Kernel application data type. - */ -export type KernelApplicationData = Record; - -/** - * Kernel context data. - */ -export interface KernelContextData -{ - application: { - data: KernelApplicationData; - setData: ApplicationDataSetter; - }; -} - -/** - * React Kernel context. - */ -export const KernelContext = React.createContext({ - application: { - data: {}, - setData: () => {}, - }, -}); - -/** - * Kernel context provider. - */ -export function KernelContextProvider({children}: React.PropsWithChildren<{}>) -{ - // Kernel application data initialization. - const [kernelApplicationData, setKernelApplicationData] = useState({}); - - /** - * Change application data function. - */ - const changeApplicationData = useCallback((applicationUpdate: Partial) => { - setKernelApplicationData({ - ...kernelApplicationData, - ...applicationUpdate, - }); - }, [kernelApplicationData, setKernelApplicationData]); - - /** - * Application data setter function. - */ - const applicationDataSetter = useCallback((identifier: string, data: any) => ( - changeApplicationData({ - [identifier]: data, - }) - ), [changeApplicationData]); - - // Initialize kernel context value. - const kernelContextValue = useMemo(() => ({ - application: { - data: kernelApplicationData, - setData: applicationDataSetter, - }, - }), [kernelApplicationData, applicationDataSetter]); - - return ( - - {children} - - ); -} - -/** - * Get kernel context data. - */ -export function useKernelContext(): KernelContextData -{ - return useContext(KernelContext); -} - -/** - * Initialize or get kernel application data with given identifier. - * @param identifier Application data identifier. - * @param initialValue Application data initial value. - */ -export function useKernelApplicationData(identifier: string, initialValue: T): [T, KernelApplicationDataDispatcher] -{ - /** - * Get kernel context. - */ - const kernelContext = useKernelContext(); - - /** - * Function to set application data. - */ - const setApplicationData = useCallback( - (newValue: T) => kernelContext.application.setData(identifier, newValue), - [kernelContext.application.setData] - ); - - // Return kernel application data. - return [kernelContext.application.data?.[identifier] ?? initialValue, setApplicationData]; -} diff --git a/src/KernelGlobalContext.tsx b/src/KernelGlobalContext.tsx new file mode 100644 index 0000000..2c1942b --- /dev/null +++ b/src/KernelGlobalContext.tsx @@ -0,0 +1,133 @@ +import React, {useCallback, useContext, useMemo, useState} from "react"; +import {v4 as uuidv4} from "uuid"; + +/** + * Create Kernel context. + * @param defaultValue Kernel context default value. + */ +export function createKernelContext(defaultValue: T): KernelContext +{ + return { + uuid: uuidv4(), + defaultValue: defaultValue, + }; +} + +/** + * Kernel context definition object. + */ +export interface KernelContext +{ + /** + * Kernel context UUID. + */ + uuid: string; + + /** + * Kernel context default value. + */ + defaultValue: T; +} + +/** + * Kernel context setter function type. + */ +export type KernelContextSetter = (identifier: IdentifierType, value: ValueType) => void; + +/** + * Kernel contexts type. + */ +export type KernelContexts = Record; + +/** + * Kernel context dispatcher function type. + */ +export type KernelContextDispatcher = (value: ValueType) => void; + +/** + * Kernel global context data. + */ +export interface KernelGlobalContextData +{ + contexts: KernelContexts; + setContext: KernelContextSetter; +} + +/** + * React Kernel global context. + */ +export const KernelGlobalContext = React.createContext({ + contexts: {}, + setContext: () => {}, +}); + +/** + * Kernel global context provider. + */ +export function KernelGlobalContextProvider({children}: React.PropsWithChildren<{}>) +{ + // Kernel contexts initialization. + const [kernelContexts, setKernelContexts] = useState({}); + + /** + * Change kernel contexts. + */ + const changeKernelContexts = useCallback((kernelContextsUpdate: Partial) => { + setKernelContexts({ + ...kernelContexts, + ...kernelContextsUpdate, + }); + }, [kernelContexts, setKernelContexts]); + + /** + * Kernel context setter function. + */ + const kernelContextSetter = useCallback((identifier: string, data: any) => ( + changeKernelContexts({ + [identifier]: data, + }) + ), [changeKernelContexts]); + + // Initialize kernel global context value. + const kernelContextValue = useMemo(() => ({ + contexts: kernelContexts, + setContext: kernelContextSetter, + }), [kernelContexts, kernelContextSetter]); + + return ( + + {children} + + ); +} + +/** + * Get kernel global context data. + */ +function useKernelGlobalContext(): KernelGlobalContextData +{ + return useContext(KernelGlobalContext); +} + +/** + * Initialize or get kernel context with given identifier. + * @param context Context object. + */ +export function useKernelContext(context: KernelContext): [T, KernelContextDispatcher] +{ + /** + * Get kernel global context. + */ + const kernelGlobalContext = useKernelGlobalContext(); + + /** + * Function to set kernel context. + */ + const setContext = useCallback( + (newValue: T) => kernelGlobalContext.setContext(context.uuid, newValue), + [kernelGlobalContext.setContext], + ); + + // Return kernel context and its dispatcher. + return [kernelGlobalContext.contexts?.[context.uuid] ?? context.defaultValue, setContext]; +}