diff --git a/src/App.tsx b/src/App.tsx
index 03b54f3..8922571 100644
--- a/src/App.tsx
+++ b/src/App.tsx
@@ -1,4 +1,5 @@
import { createBrowserRouter, RouterProvider } from 'react-router-dom';
+import { ColorFunctionProvider } from './ColorFunctionContext';
import { Notifications } from './components/Notifications';
import { Home } from './pages/Home';
import { MainLayout } from './pages/MainLayout';
@@ -28,9 +29,11 @@ const routes = createBrowserRouter([
export function App() {
return (
-
- Color Lab
-
-
+
+
+ Color Lab
+
+
+
);
}
diff --git a/src/ColorFunctionContext.tsx b/src/ColorFunctionContext.tsx
new file mode 100644
index 0000000..eba7730
--- /dev/null
+++ b/src/ColorFunctionContext.tsx
@@ -0,0 +1,56 @@
+import {
+ createContext,
+ ReactNode,
+ useCallback,
+ useEffect,
+ useMemo,
+ useState,
+ useTransition,
+} from 'react';
+import type * as Wasm from './pkg/color_module';
+import init from './pkg/color_module';
+
+export const ColorFunctionContext = createContext<{
+ colorFn: Wasm.InitOutput | null;
+ isLoading: boolean;
+ error: Error | null;
+}>({
+ colorFn: null,
+ isLoading: true,
+ error: null,
+});
+
+type WasmProviderProps = {
+ children?: ReactNode;
+};
+
+export function ColorFunctionProvider({ children }: WasmProviderProps) {
+ const [wasmInstance, setWasmInstance] = useState(null);
+ const [isPending, startTransition] = useTransition();
+ const [error, setError] = useState(null);
+
+ const loadWasm = useCallback(() => {
+ startTransition(async () => {
+ try {
+ const wasm = await init();
+ setWasmInstance(wasm);
+ } catch (e) {
+ console.error('[Load WASM]', e);
+ setError(e);
+ }
+ });
+ }, []);
+ const contextValue = useMemo(
+ () => ({
+ colorFn: wasmInstance,
+ isLoading: isPending,
+ error,
+ }),
+ [wasmInstance, isPending, error],
+ );
+ useEffect(() => {
+ loadWasm();
+ }, []);
+
+ return {children};
+}
diff --git a/src/pages/SchemeDetail.tsx b/src/pages/SchemeDetail.tsx
index b509597..e0be4a3 100644
--- a/src/pages/SchemeDetail.tsx
+++ b/src/pages/SchemeDetail.tsx
@@ -1,3 +1,23 @@
+import { isNil } from 'lodash-es';
+import { useEffect } from 'react';
+import { useNavigate, useParams } from 'react-router-dom';
+import { useScheme } from '../stores/schemes';
+
export function SchemeDetail() {
- return ;
+ const { id } = useParams();
+ const scheme = useScheme(id);
+ const navigate = useNavigate();
+
+ useEffect(() => {
+ if (isNil(scheme)) {
+ navigate('../not-found');
+ }
+ }, [scheme, navigate]);
+
+ return (
+
+
{scheme?.name}
+
{scheme?.description}
+
+ );
}