Files
xingrin/frontend/hooks/use-step.ts
2025-12-12 18:04:57 +08:00

72 lines
1.5 KiB
TypeScript

"use client"
import { useCallback, useState } from 'react'
import type { Dispatch, SetStateAction } from 'react'
type UseStepActions = {
goToNextStep: () => void
goToPrevStep: () => void
reset: () => void
canGoToNextStep: boolean
canGoToPrevStep: boolean
setStep: Dispatch<SetStateAction<number>>
}
type SetStepCallbackType = (step: number | ((step: number) => number)) => void
/**
* 步骤导航 Hook
* @param maxStep 最大步骤数
* @returns [currentStep, actions]
*/
export function useStep(maxStep: number): [number, UseStepActions] {
const [currentStep, setCurrentStep] = useState(1)
const canGoToNextStep = currentStep + 1 <= maxStep
const canGoToPrevStep = currentStep - 1 > 0
const setStep = useCallback<SetStepCallbackType>(
step => {
const newStep = step instanceof Function ? step(currentStep) : step
if (newStep >= 1 && newStep <= maxStep) {
setCurrentStep(newStep)
return
}
throw new Error('Step not valid')
},
[maxStep, currentStep],
)
const goToNextStep = useCallback(() => {
if (canGoToNextStep) {
setCurrentStep(step => step + 1)
}
}, [canGoToNextStep])
const goToPrevStep = useCallback(() => {
if (canGoToPrevStep) {
setCurrentStep(step => step - 1)
}
}, [canGoToPrevStep])
const reset = useCallback(() => {
setCurrentStep(1)
}, [])
return [
currentStep,
{
goToNextStep,
goToPrevStep,
canGoToNextStep,
canGoToPrevStep,
setStep,
reset,
},
]
}
export type { UseStepActions }