Files
supabase/packages/ui-patterns/CommandMenu/internal/state/pagesState.ts
Charis 71f012a527 feat(command menu v2): complete state management (#27019)
Add all the outstanding pieces for state management of new command menu:

- Pages state (handles routing between command menu views, e.g., docs
  search, AI, etc.)
- View state (handles opening and closing and initiation (needed for
  lazy loading))
- Query state (handles active search term)
2024-06-05 10:53:00 -04:00

59 lines
1.5 KiB
TypeScript

import { type ReactNode } from 'react'
import { proxy } from 'valtio'
import { type ICommandSection } from '../CommandSection'
type PageComponent = () => ReactNode
enum PageType {
Commands,
Component,
}
interface CommandsPage {
type: PageType.Commands
sections: ICommandSection[]
}
interface ComponentPage {
type: PageType.Component
component: PageComponent
}
type PageDefinition = CommandsPage | ComponentPage
const isCommandsPage = (page: PageDefinition): page is CommandsPage =>
page.type === PageType.Commands
const isComponentPage = (page: PageDefinition): page is ComponentPage =>
page.type === PageType.Component
type IPagesState = {
commandPages: Record<string, PageDefinition>
pageStack: Array<string>
registerNewPage: (name: string, page: PageDefinition) => () => void
appendPageStack: (name: string) => void
popPageStack: () => void
}
const initPagesState = () => {
const state: IPagesState = proxy({
commandPages: {},
pageStack: [],
registerNewPage: (name, definition) => {
state.commandPages[name] = definition
return () => {
state.pageStack = state.pageStack.filter((page) => page !== name)
delete state.commandPages[name]
}
},
appendPageStack: (name) =>
name in state.commandPages && state.pageStack.at(-1) !== name && state.pageStack.push(name),
popPageStack: () => state.pageStack.pop(),
})
return state
}
export { PageType, initPagesState, isCommandsPage, isComponentPage }
export type { IPagesState, PageDefinition }