Compare commits
10 commits
Author | SHA1 | Date | |
---|---|---|---|
989f1f04d2 | |||
7bbd04e47a | |||
4f2c5a5245 | |||
206d51e4cb | |||
43c0297b04 | |||
60dfd776c6 | |||
e7266d0ab6 | |||
a5f16cd3fc | |||
6252ed3045 | |||
06b2b9f5e1 |
14 changed files with 1143 additions and 859 deletions
|
@ -38,6 +38,9 @@ import {Box} from "../src/Components/Box";
|
|||
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 {useKernelContext} from "../src/KernelGlobalContext";
|
||||
import {KernelContext} from "./DemoKernelContext";
|
||||
|
||||
export function DemoApp()
|
||||
{
|
||||
|
@ -72,6 +75,8 @@ export function DemoApp()
|
|||
|
||||
const [failingComponentsCount, setFailingComponentsCount] = useState(0);
|
||||
|
||||
const [kernelContext, setKernelContext] = useKernelContext(KernelContext);
|
||||
|
||||
return (
|
||||
<Application>
|
||||
<MainMenu>
|
||||
|
@ -163,6 +168,10 @@ export function DemoApp()
|
|||
<Radio name={"radio-test"}>Radio box test</Radio>
|
||||
<Radio name={"radio-test"}>Radio box test</Radio>
|
||||
|
||||
<Tip>
|
||||
A tip component, very useful in forms which require some explanations.
|
||||
</Tip>
|
||||
|
||||
<Select options={{
|
||||
"a": "AAAAAA",
|
||||
"b": "BBBBBB",
|
||||
|
@ -604,6 +613,23 @@ export function DemoApp()
|
|||
</NotifyErrorsBoundary>
|
||||
</Card>
|
||||
|
||||
<h2>
|
||||
Global states
|
||||
</h2>
|
||||
|
||||
<Card>
|
||||
<label>
|
||||
Kernel context data
|
||||
<input type={"text"} name={"kernel-context-data"}
|
||||
value={kernelContext}
|
||||
onChange={(event) => setKernelContext(event.currentTarget.value)} />
|
||||
</label>
|
||||
|
||||
<Buttons placement={"center"}>
|
||||
<button type={"button"} onClick={easySubapp}>Open demo subapp to see if it works</button>
|
||||
</Buttons>
|
||||
</Card>
|
||||
|
||||
</Application>
|
||||
);
|
||||
}
|
||||
|
|
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,6 +1,8 @@
|
|||
import React from "react";
|
||||
import {Subapp, useSubapp} from "../src/Components/Subapps/Subapps";
|
||||
import {Card} from "../src/Components/Card";
|
||||
import {useKernelContext} from "../src/KernelGlobalContext";
|
||||
import {KernelContext} from "./DemoKernelContext";
|
||||
|
||||
/**
|
||||
* A demo Subapp component.
|
||||
|
@ -10,6 +12,9 @@ export function DemoSubapp()
|
|||
// Get subapp close function.
|
||||
const {uuid, close} = useSubapp();
|
||||
|
||||
// Get kernel context data.
|
||||
const [kernelContext] = useKernelContext(KernelContext);
|
||||
|
||||
return (
|
||||
<Subapp title={"My complex subapp"}>
|
||||
<Card>
|
||||
|
@ -17,6 +22,8 @@ export function DemoSubapp()
|
|||
|
||||
<p>UUID : <code>{uuid}</code></p>
|
||||
|
||||
{kernelContext && <p><strong>Kernel context data</strong>: <code>{kernelContext}</code></p>}
|
||||
|
||||
<button onClick={close}>Close the subapp</button>
|
||||
</Card>
|
||||
</Subapp>
|
||||
|
|
2
index.ts
2
index.ts
|
@ -45,7 +45,9 @@ export * from "./src/Components/Select/Suggestible";
|
|||
export * from "./src/Components/Steps/Steps";
|
||||
export * from "./src/Components/Steps/StepsContext";
|
||||
export * from "./src/Components/Subapps/Subapps";
|
||||
export * from "./src/Components/Tips/Tip";
|
||||
|
||||
export * from "./src/Async";
|
||||
export * from "./src/GlobalState";
|
||||
export * from "./src/KernelGlobalContext";
|
||||
export * from "./src/Utils";
|
||||
|
|
22
package.json
22
package.json
|
@ -1,5 +1,5 @@
|
|||
{
|
||||
"version": "1.6.2",
|
||||
"version": "1.8.3",
|
||||
"name": "@kernelui/core",
|
||||
"description": "Kernel UI Core.",
|
||||
"scripts": {
|
||||
|
@ -27,24 +27,24 @@
|
|||
},
|
||||
"devDependencies": {
|
||||
"@phosphor-icons/react": "^2.1.7",
|
||||
"@types/node": "^20.14.10",
|
||||
"@types/react": "^18.3.3",
|
||||
"@types/react-dom": "^18.3.0",
|
||||
"@types/node": "^22.7.4",
|
||||
"@types/react": "^18.3.12",
|
||||
"@types/react-dom": "^18.3.1",
|
||||
"@types/uuid": "^10",
|
||||
"@vitejs/plugin-react": "^4.3.0",
|
||||
"@vitejs/plugin-react": "^4.3.4",
|
||||
"less": "^4.2.0",
|
||||
"react": "^18.3.1",
|
||||
"react-dom": "^18.3.1",
|
||||
"react-router-dom": "^6.24.1",
|
||||
"typescript": "^5.4.5",
|
||||
"vite": "^5.2.11",
|
||||
"vite-plugin-dts": "^3.9.1"
|
||||
"react-router-dom": "^7.0.1",
|
||||
"typescript": "^5.6.2",
|
||||
"vite": "^6.0.1",
|
||||
"vite-plugin-dts": "^4.3.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@phosphor-icons/react": "^2.1.7",
|
||||
"react": "^18.3.1",
|
||||
"react-dom": "^18.3.1",
|
||||
"react-router-dom": "^6.24.1"
|
||||
"react-router-dom": "^7.0.1"
|
||||
},
|
||||
"packageManager": "yarn@4.5.0"
|
||||
"packageManager": "yarn@4.5.3"
|
||||
}
|
||||
|
|
|
@ -3,6 +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 {KernelGlobalContextProvider} from "../KernelGlobalContext";
|
||||
|
||||
/**
|
||||
* Main Kernel UI app component which initializes everything.
|
||||
|
@ -14,17 +15,19 @@ export function Kernel({header, footer, router}: {
|
|||
})
|
||||
{
|
||||
return (
|
||||
<IconContext.Provider value={{
|
||||
size: "1em",
|
||||
weight: "bold",
|
||||
}}>
|
||||
<NotificationsProvider>
|
||||
<CurtainsProvider>
|
||||
{header}
|
||||
<RouterProvider router={router} />
|
||||
{footer}
|
||||
</CurtainsProvider>
|
||||
</NotificationsProvider>
|
||||
</IconContext.Provider>
|
||||
<KernelGlobalContextProvider>
|
||||
<IconContext.Provider value={{
|
||||
size: "1em",
|
||||
weight: "bold",
|
||||
}}>
|
||||
<NotificationsProvider>
|
||||
<CurtainsProvider>
|
||||
{header}
|
||||
<RouterProvider router={router} />
|
||||
{footer}
|
||||
</CurtainsProvider>
|
||||
</NotificationsProvider>
|
||||
</IconContext.Provider>
|
||||
</KernelGlobalContextProvider>
|
||||
);
|
||||
}
|
||||
|
|
17
src/Components/Tips/Tip.tsx
Normal file
17
src/Components/Tips/Tip.tsx
Normal file
|
@ -0,0 +1,17 @@
|
|||
import React from "react";
|
||||
import {classes} from "../../Utils";
|
||||
import {Info} from "@phosphor-icons/react";
|
||||
|
||||
/**
|
||||
* Simple text tip component.
|
||||
*/
|
||||
export function Tip({className, children, ...props}: React.PropsWithChildren<React.HTMLAttributes<HTMLParagraphElement>>)
|
||||
{
|
||||
return (
|
||||
<p className={classes("tip", className)} {...props}>
|
||||
<Info weight={"duotone"} />
|
||||
|
||||
{children}
|
||||
</p>
|
||||
);
|
||||
}
|
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];
|
||||
}
|
|
@ -20,3 +20,4 @@
|
|||
@import "components/_steps-counter";
|
||||
@import "components/_subapp";
|
||||
@import "components/_table";
|
||||
@import "components/_tip";
|
||||
|
|
|
@ -20,6 +20,7 @@ a.button, button, input[type="submit"], input[type="reset"]
|
|||
font-weight: 600;
|
||||
text-decoration: none;
|
||||
vertical-align: middle;
|
||||
text-align: center;
|
||||
|
||||
cursor: pointer;
|
||||
|
||||
|
|
|
@ -4,6 +4,12 @@ h1, h2, h3, h4, h5, h6
|
|||
|
||||
&.center, &.main
|
||||
{ text-align: center; }
|
||||
|
||||
> svg
|
||||
{
|
||||
position: relative;
|
||||
bottom: -0.15em;
|
||||
}
|
||||
}
|
||||
|
||||
h1
|
||||
|
|
28
src/styles/components/_tip.less
Normal file
28
src/styles/components/_tip.less
Normal file
|
@ -0,0 +1,28 @@
|
|||
p.tip
|
||||
{
|
||||
position: relative;
|
||||
|
||||
margin: auto;
|
||||
width: 30em;
|
||||
padding: 0.3em 0.5em 0.3em 3em;
|
||||
border-radius: 0.3em;
|
||||
box-sizing: border-box;
|
||||
|
||||
border: solid var(--background-darkest) thin;
|
||||
color: var(--foreground-lightest);
|
||||
|
||||
svg
|
||||
{
|
||||
position: absolute;
|
||||
top: 0.3em;
|
||||
left: 0.5em;
|
||||
|
||||
display: inline-block;
|
||||
margin: 0;
|
||||
|
||||
color: var(--primary);
|
||||
font-size: 1.5em;
|
||||
|
||||
vertical-align: middle;
|
||||
}
|
||||
}
|
|
@ -23,6 +23,7 @@ export default defineConfig(({ mode }: ConfigEnv): UserConfig => {
|
|||
plugins: [
|
||||
react(),
|
||||
dts({
|
||||
rollupTypes: true,
|
||||
insertTypesEntry: true,
|
||||
exclude: ["demo", "node_modules"],
|
||||
}),
|
||||
|
|
Loading…
Add table
Reference in a new issue