"use client"; /** * SidebarContext:基于 XState v5 的 React Context Provider * * 业务事件通过 `useMachine(sidebarMachine).send()` 派发。 * XState 自动处理状态转换(无异步副作用)。 * * 兼容性:保持原 `useSidebarState()` / `useSidebarDispatch()` API。 * 内部将 XState 状态机快照映射回原 `SidebarState` 形状。 */ import { type Dispatch, type ReactNode, createContext, useContext, useMemo, } from "react"; import { useMachine } from "@xstate/react"; import { sidebarMachine } from "./sidebar-machine"; import type { SidebarContext as MachineContext, SidebarEvent, } from "./sidebar-machine"; /** * 对外暴露的 State 形状(保持与原 SidebarState 兼容) */ export interface SidebarState { currentPage: MachineContext["currentPage"]; selectedBottomNavItem: MachineContext["selectedBottomNavItem"]; characterName: string; characterProgress: number; } const SidebarStateCtx = createContext(null); const SidebarDispatchCtx = createContext | null>(null); export function SidebarProvider({ children }: { children: ReactNode }) { const [state, send] = useMachine(sidebarMachine); // 映射 XState 状态机快照 → 原 SidebarState 形状 const sidebarState = useMemo( () => ({ currentPage: state.context.currentPage, selectedBottomNavItem: state.context.selectedBottomNavItem, characterName: state.context.characterName, characterProgress: state.context.characterProgress, }), [state], ); return ( {children} ); } export function useSidebarState(): SidebarState { const ctx = useContext(SidebarStateCtx); if (!ctx) throw new Error("useSidebarState must be used inside "); return ctx; } export function useSidebarDispatch(): Dispatch { const ctx = useContext(SidebarDispatchCtx); if (!ctx) throw new Error("useSidebarDispatch must be used inside "); return ctx; }