Transform kernel application data to kernel React-like contexts.
This commit is contained in:
parent
60dfd776c6
commit
43c0297b04
8 changed files with 156 additions and 126 deletions
|
@ -39,7 +39,8 @@ import {Await, useAsync} from "../src/Async";
|
||||||
import {NotifyErrorsBoundary} from "../src/Components/Errors/NotifyErrorsBoundary";
|
import {NotifyErrorsBoundary} from "../src/Components/Errors/NotifyErrorsBoundary";
|
||||||
import {DemoFailingComponent, DemoResetComponent} from "./DemoFailingComponent";
|
import {DemoFailingComponent, DemoResetComponent} from "./DemoFailingComponent";
|
||||||
import {Tip} from "../src/Components/Tips/Tip";
|
import {Tip} from "../src/Components/Tips/Tip";
|
||||||
import {useKernelApplicationData} from "../src/KernelContext";
|
import {useKernelContext} from "../src/KernelGlobalContext";
|
||||||
|
import {KernelContext} from "./DemoKernelContext";
|
||||||
|
|
||||||
export function DemoApp()
|
export function DemoApp()
|
||||||
{
|
{
|
||||||
|
@ -74,7 +75,7 @@ export function DemoApp()
|
||||||
|
|
||||||
const [failingComponentsCount, setFailingComponentsCount] = useState(0);
|
const [failingComponentsCount, setFailingComponentsCount] = useState(0);
|
||||||
|
|
||||||
const [kernelApplicationData, setKernelApplicationData] = useKernelApplicationData("customData", "");
|
const [kernelContext, setKernelContext] = useKernelContext(KernelContext);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Application>
|
<Application>
|
||||||
|
@ -618,10 +619,10 @@ export function DemoApp()
|
||||||
|
|
||||||
<Card>
|
<Card>
|
||||||
<label>
|
<label>
|
||||||
Kernel application custom data
|
Kernel context data
|
||||||
<input type={"text"} name={"kernel-application-data"}
|
<input type={"text"} name={"kernel-context-data"}
|
||||||
value={kernelApplicationData}
|
value={kernelContext}
|
||||||
onChange={(event) => setKernelApplicationData(event.currentTarget.value)} />
|
onChange={(event) => setKernelContext(event.currentTarget.value)} />
|
||||||
</label>
|
</label>
|
||||||
|
|
||||||
<Buttons placement={"center"}>
|
<Buttons placement={"center"}>
|
||||||
|
|
6
demo/DemoKernelContext.tsx
Normal file
6
demo/DemoKernelContext.tsx
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
import {createKernelContext} from "../src/KernelGlobalContext";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create kernel context.
|
||||||
|
*/
|
||||||
|
export const KernelContext = createKernelContext("");
|
|
@ -1,7 +1,8 @@
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import {Subapp, useSubapp} from "../src/Components/Subapps/Subapps";
|
import {Subapp, useSubapp} from "../src/Components/Subapps/Subapps";
|
||||||
import {Card} from "../src/Components/Card";
|
import {Card} from "../src/Components/Card";
|
||||||
import {useKernelApplicationData} from "../src/KernelContext";
|
import {useKernelContext} from "../src/KernelGlobalContext";
|
||||||
|
import {KernelContext} from "./DemoKernelContext";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A demo Subapp component.
|
* A demo Subapp component.
|
||||||
|
@ -11,8 +12,8 @@ export function DemoSubapp()
|
||||||
// Get subapp close function.
|
// Get subapp close function.
|
||||||
const {uuid, close} = useSubapp();
|
const {uuid, close} = useSubapp();
|
||||||
|
|
||||||
// Get kernel application custom data.
|
// Get kernel context data.
|
||||||
const [kernelApplicationData] = useKernelApplicationData("customData", "");
|
const [kernelContext] = useKernelContext(KernelContext);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Subapp title={"My complex subapp"}>
|
<Subapp title={"My complex subapp"}>
|
||||||
|
@ -21,7 +22,7 @@ export function DemoSubapp()
|
||||||
|
|
||||||
<p>UUID : <code>{uuid}</code></p>
|
<p>UUID : <code>{uuid}</code></p>
|
||||||
|
|
||||||
{kernelApplicationData && <p><strong>Kernel application data</strong>: <code>{kernelApplicationData}</code></p>}
|
{kernelContext && <p><strong>Kernel context data</strong>: <code>{kernelContext}</code></p>}
|
||||||
|
|
||||||
<button onClick={close}>Close the subapp</button>
|
<button onClick={close}>Close the subapp</button>
|
||||||
</Card>
|
</Card>
|
||||||
|
|
2
index.ts
2
index.ts
|
@ -49,5 +49,5 @@ export * from "./src/Components/Tips/Tip";
|
||||||
|
|
||||||
export * from "./src/Async";
|
export * from "./src/Async";
|
||||||
export * from "./src/GlobalState";
|
export * from "./src/GlobalState";
|
||||||
export * from "./src/KernelContext";
|
export * from "./src/KernelGlobalContext";
|
||||||
export * from "./src/Utils";
|
export * from "./src/Utils";
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
{
|
{
|
||||||
"version": "1.8.0",
|
"version": "1.8.1",
|
||||||
"name": "@kernelui/core",
|
"name": "@kernelui/core",
|
||||||
"description": "Kernel UI Core.",
|
"description": "Kernel UI Core.",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
|
|
|
@ -3,7 +3,7 @@ import React from "react";
|
||||||
import {createBrowserRouter, RouterProvider} from "react-router-dom";
|
import {createBrowserRouter, RouterProvider} from "react-router-dom";
|
||||||
import {CurtainsProvider} from "../Components/Curtains/Curtains";
|
import {CurtainsProvider} from "../Components/Curtains/Curtains";
|
||||||
import {NotificationsProvider} from "../Components/Notifications/Notifications";
|
import {NotificationsProvider} from "../Components/Notifications/Notifications";
|
||||||
import {KernelContextProvider} from "../KernelContext";
|
import {KernelGlobalContextProvider} from "../KernelGlobalContext";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Main Kernel UI app component which initializes everything.
|
* Main Kernel UI app component which initializes everything.
|
||||||
|
@ -15,7 +15,7 @@ export function Kernel({header, footer, router}: {
|
||||||
})
|
})
|
||||||
{
|
{
|
||||||
return (
|
return (
|
||||||
<KernelContextProvider>
|
<KernelGlobalContextProvider>
|
||||||
<IconContext.Provider value={{
|
<IconContext.Provider value={{
|
||||||
size: "1em",
|
size: "1em",
|
||||||
weight: "bold",
|
weight: "bold",
|
||||||
|
@ -28,6 +28,6 @@ export function Kernel({header, footer, router}: {
|
||||||
</CurtainsProvider>
|
</CurtainsProvider>
|
||||||
</NotificationsProvider>
|
</NotificationsProvider>
|
||||||
</IconContext.Provider>
|
</IconContext.Provider>
|
||||||
</KernelContextProvider>
|
</KernelGlobalContextProvider>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,111 +0,0 @@
|
||||||
import React, {useCallback, useContext, useMemo, useState} from "react";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Application data setter function type.
|
|
||||||
*/
|
|
||||||
export type ApplicationDataSetter<IdentifierType extends string|symbol|number = string, ValueType = any> = (identifier: IdentifierType, value: ValueType) => void;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Application data dispatcher function type.
|
|
||||||
*/
|
|
||||||
export type KernelApplicationDataDispatcher<ValueType = any> = (value: ValueType) => void;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Kernel application data type.
|
|
||||||
*/
|
|
||||||
export type KernelApplicationData = Record<string, any>;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Kernel context data.
|
|
||||||
*/
|
|
||||||
export interface KernelContextData
|
|
||||||
{
|
|
||||||
application: {
|
|
||||||
data: KernelApplicationData;
|
|
||||||
setData: ApplicationDataSetter;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* React Kernel context.
|
|
||||||
*/
|
|
||||||
export const KernelContext = React.createContext<KernelContextData>({
|
|
||||||
application: {
|
|
||||||
data: {},
|
|
||||||
setData: () => {},
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Kernel context provider.
|
|
||||||
*/
|
|
||||||
export function KernelContextProvider({children}: React.PropsWithChildren<{}>)
|
|
||||||
{
|
|
||||||
// Kernel application data initialization.
|
|
||||||
const [kernelApplicationData, setKernelApplicationData] = useState<KernelApplicationData>({});
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Change application data function.
|
|
||||||
*/
|
|
||||||
const changeApplicationData = useCallback((applicationUpdate: Partial<KernelApplicationData>) => {
|
|
||||||
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<KernelContextData>(() => ({
|
|
||||||
application: {
|
|
||||||
data: kernelApplicationData,
|
|
||||||
setData: applicationDataSetter,
|
|
||||||
},
|
|
||||||
}), [kernelApplicationData, applicationDataSetter]);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<KernelContext.Provider value={kernelContextValue}>
|
|
||||||
{children}
|
|
||||||
</KernelContext.Provider>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 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<T>(identifier: string, initialValue: T): [T, KernelApplicationDataDispatcher<T>]
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* 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];
|
|
||||||
}
|
|
133
src/KernelGlobalContext.tsx
Normal file
133
src/KernelGlobalContext.tsx
Normal file
|
@ -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<T>(defaultValue: T): KernelContext<T>
|
||||||
|
{
|
||||||
|
return {
|
||||||
|
uuid: uuidv4(),
|
||||||
|
defaultValue: defaultValue,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Kernel context definition object.
|
||||||
|
*/
|
||||||
|
export interface KernelContext<T>
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Kernel context UUID.
|
||||||
|
*/
|
||||||
|
uuid: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Kernel context default value.
|
||||||
|
*/
|
||||||
|
defaultValue: T;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Kernel context setter function type.
|
||||||
|
*/
|
||||||
|
export type KernelContextSetter<IdentifierType extends string|symbol|number = string, ValueType = any> = (identifier: IdentifierType, value: ValueType) => void;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Kernel contexts type.
|
||||||
|
*/
|
||||||
|
export type KernelContexts = Record<string, any>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Kernel context dispatcher function type.
|
||||||
|
*/
|
||||||
|
export type KernelContextDispatcher<ValueType = any> = (value: ValueType) => void;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Kernel global context data.
|
||||||
|
*/
|
||||||
|
export interface KernelGlobalContextData
|
||||||
|
{
|
||||||
|
contexts: KernelContexts;
|
||||||
|
setContext: KernelContextSetter;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* React Kernel global context.
|
||||||
|
*/
|
||||||
|
export const KernelGlobalContext = React.createContext<KernelGlobalContextData>({
|
||||||
|
contexts: {},
|
||||||
|
setContext: () => {},
|
||||||
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Kernel global context provider.
|
||||||
|
*/
|
||||||
|
export function KernelGlobalContextProvider({children}: React.PropsWithChildren<{}>)
|
||||||
|
{
|
||||||
|
// Kernel contexts initialization.
|
||||||
|
const [kernelContexts, setKernelContexts] = useState<KernelContexts>({});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Change kernel contexts.
|
||||||
|
*/
|
||||||
|
const changeKernelContexts = useCallback((kernelContextsUpdate: Partial<KernelContexts>) => {
|
||||||
|
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<KernelGlobalContextData>(() => ({
|
||||||
|
contexts: kernelContexts,
|
||||||
|
setContext: kernelContextSetter,
|
||||||
|
}), [kernelContexts, kernelContextSetter]);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<KernelGlobalContext.Provider value={kernelContextValue}>
|
||||||
|
{children}
|
||||||
|
</KernelGlobalContext.Provider>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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<T>(context: KernelContext<T>): [T, KernelContextDispatcher<T>]
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* 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];
|
||||||
|
}
|
Loading…
Reference in a new issue