import type {ComponentType} from 'react' import {createExternalState} from '../../utils/createExternalState' import {Counter} from '../../utils/sundry' /** * @zh 堆栈中的一个屏幕条目。`id` 由内部计数器生成,作为 React key 保证 keep-alive 稳定。 * @en A single screen entry in the stack. `id` is generated by an internal counter and used as * the React key to keep-alive state stable across pushes/pops. */ export interface StackEntry
{ id: number Component: ComponentType
params: P } /** * @zh 堆栈状态操作接口。每个 `AppStackRouter` 实例独立持有一个 store,互不串扰。 * @en Stack state operations. Each `AppStackRouter` instance owns an isolated store. */ export interface StackStore { /** * @zh 当前堆栈(只读快照,不含根屏幕)。 * @en Current stack snapshot (read-only, excludes the root screen). */ getStack: () => StackEntry[] /** * @zh 压入一个新屏幕到栈顶。 * @en Push a new screen onto the top of the stack. */ push:
(Component: ComponentType
, params?: P) => void /** * @zh 弹出栈顶屏幕。栈空时为空操作。 * @en Pop the top screen. No-op when the stack is empty. */ pop: () => StackEntry | undefined /** * @zh 替换栈顶屏幕,不改变栈深度。 * @en Replace the top screen without changing stack depth. */ replace:
(Component: ComponentType
, params?: P) => void
/**
* @zh 清空整个堆栈,回到根屏幕。
* @en Clear the entire stack, returning to the root screen.
*/
reset: () => void
/**
* @zh 堆栈是否可出栈(深度 > 0)。
* @en Whether the stack can be popped (depth > 0).
*/
canPop: () => boolean
/**
* @zh 当前栈深度(不含根屏幕)。
* @en Current stack depth (excludes the root screen).
*/
getSize: () => number
/**
* @zh 在组件中订阅堆栈快照。栈内容变化时重渲染。
* @en Subscribe to the stack snapshot from a component. Re-renders when stack content changes.
*/
useStack: () => StackEntry[]
/**
* @zh 在组件中只订阅栈深度(数字)。仅当深度变化时重渲染,比 `useStack` 更细粒度。
* @en Subscribe to only the stack depth (number) from a component. Re-renders only when the depth
* changes; finer-grained than `useStack`.
*/
useSize: () => number
}
/**
* @zh 创建一个独立的堆栈 store。内部基于 `createExternalState`,通过 `useSyncExternalStore` 订阅。
* @en Create an isolated stack store. Built on `createExternalState`, subscribed via `useSyncExternalStore`.
*/
export function createStackStore(maxStackSize = Number.POSITIVE_INFINITY): StackStore {
const counter = new Counter()
const state = createExternalState