pagesState.ts58 lines · main
1import { type ReactNode } from 'react'
2import { proxy } from 'valtio'
3
4import { type ICommandSection } from '../types'
5
6type PageComponent = () => ReactNode
7
8enum PageType {
9 Commands,
10 Component,
11}
12
13interface CommandsPage {
14 type: PageType.Commands
15 sections: ICommandSection[]
16}
17
18interface ComponentPage {
19 type: PageType.Component
20 component: PageComponent
21}
22
23type PageDefinition = CommandsPage | ComponentPage
24
25const isCommandsPage = (page: PageDefinition): page is CommandsPage =>
26 page.type === PageType.Commands
27const isComponentPage = (page: PageDefinition): page is ComponentPage =>
28 page.type === PageType.Component
29
30type IPagesState = {
31 commandPages: Record<string, PageDefinition>
32 pageStack: Array<string>
33 registerNewPage: (name: string, page: PageDefinition) => () => void
34 appendPageStack: (name: string) => void
35 popPageStack: () => void
36}
37
38const initPagesState = () => {
39 const state: IPagesState = proxy({
40 commandPages: {},
41 pageStack: [],
42 registerNewPage: (name, definition) => {
43 state.commandPages[name] = definition
44 return () => {
45 state.pageStack = state.pageStack.filter((page) => page !== name)
46 delete state.commandPages[name]
47 }
48 },
49 appendPageStack: (name) =>
50 name in state.commandPages && state.pageStack.at(-1) !== name && state.pageStack.push(name),
51 popPageStack: () => state.pageStack.pop(),
52 })
53
54 return state
55}
56
57export { PageType, initPagesState, isCommandsPage, isComponentPage }
58export type { IPagesState, PageDefinition }