{"version":3,"sources":["../src/lib/hooks/useId.ts","../src/lib/hooks/useStepper.ts"],"sourcesContent":["import React from 'react';\n\nexport const getRandomId = () => {\n  if ('randomUUID' in crypto) {\n    return crypto.randomUUID();\n  }\n  const uint32 = window.crypto.getRandomValues(new Uint32Array(1))[0];\n  return uint32.toString(16);\n};\n\nconst isReact18 = React.version.includes('18');\n\nexport const useIsomorphicId = () => {\n  if (isReact18) {\n    // eslint-disable-next-line react-hooks/rules-of-hooks\n    return React.useId();\n  }\n  // eslint-disable-next-line react-hooks/rules-of-hooks\n  const localId = React.useRef(getRandomId());\n  return localId.current;\n};\n","import React from 'react';\nimport type { HTMLAttributes, KeyboardEvent } from 'react';\nimport { useIsomorphicId } from './useId';\nimport type { Steps, StepperOrientation } from '../types';\n\n/**\n * Props for build stepper.\n */\ntype StepperProps = {\n  /** List of steps. */\n  steps: Steps[];\n  /** Current step selected. */\n  currentStep?: number;\n  /** Orientation. Default is horizontal. */\n  orientation?: StepperOrientation;\n};\n\n/**\n * Types for the stepper state.\n */\ntype StepperState = {\n  /** returns the current step. */\n  currentStep: number;\n  /** Unique ID to the progress bar. */\n  progressId: string;\n  /** These ID you can use with a span element to represent the progress bar label. */\n  labelId: string;\n  /** Check if has previuos step. */\n  hasPreviousStep?: boolean;\n  /** Check if has next step. */\n  hasNextStep?: boolean;\n  /** returns the total steps. */\n  totalSteps: number;\n};\n\n/**\n * Hook to use stepper.\n */\ntype UseStepper = {\n  /** Props to use into any React element to represent the stepper. */\n  stepperProps: HTMLAttributes<HTMLElement>;\n  /** Props to use into any React Element to represent the steps. */\n  stepsProps: HTMLAttributes<HTMLElement>[];\n  /** props to use into a HTMLElement to represents a progress bar. */\n  progressProps: HTMLAttributes<HTMLElement>;\n  /** the stepper state with current step, disabled steps and other props. */\n  state: StepperState;\n  /** Next step */\n  nextStep: () => void;\n  /** Previous step */\n  prevStep: () => void;\n  /** Choise a step to go to. */\n  setStep: (step: number) => void;\n};\n\nconst useStepper = ({\n  orientation = 'horizontal',\n  ...rest\n}: StepperProps): UseStepper => {\n  const { steps, currentStep } = rest;\n  // IDs\n  const stepperId = useIsomorphicId();\n  const progressId = useIsomorphicId();\n  const labelId = `${useIsomorphicId()}-label`;\n  // States & Ref's\n  const [_currentStep, setCurrentStep] = React.useState(currentStep ?? 0);\n  const hasPreviousStep = React.useRef(false);\n  const hasNextStep = React.useRef(false);\n  const stepElementsRef = React.useRef<HTMLElement[]>([]);\n  const currentStepFocused = React.useRef<number | null>(null);\n  const totalSteps = React.useRef(steps.length);\n\n  // Check previous step\n  hasPreviousStep.current = _currentStep < steps.length - 1;\n  hasPreviousStep.current = _currentStep > 0;\n\n  // Check next step\n  hasNextStep.current = _currentStep < steps.length - 1;\n\n  // Handlers\n  const guessNextAvailableStep = React.useCallback(\n    (currentIndex: number): number => {\n      const nextStep = steps[currentIndex + 1];\n      const isNextStepDisabled = nextStep?.disabled;\n      if (isNextStepDisabled) {\n        return guessNextAvailableStep(currentIndex + 1);\n      }\n      return currentIndex + 1;\n    },\n    [steps]\n  );\n\n  const guessPreviousAvailableStep = React.useCallback(\n    (currentIndex: number) => {\n      const previousStep = steps[currentIndex - 1];\n      const isPreviousStepDisabled = previousStep?.disabled;\n      if (isPreviousStepDisabled) {\n        return guessPreviousAvailableStep(currentIndex - 1);\n      }\n      return currentIndex - 1;\n    },\n    [steps]\n  );\n\n  const nextStep = React.useCallback(() => {\n    if (_currentStep === steps?.length - 1) return;\n\n    setCurrentStep((currentStep) => {\n      return guessNextAvailableStep(currentStep);\n    });\n  }, [_currentStep, guessNextAvailableStep, steps?.length]);\n\n  const prevStep = React.useCallback(() => {\n    if (_currentStep === 0) return;\n    setCurrentStep((currentStep) => {\n      return guessPreviousAvailableStep(currentStep);\n    });\n  }, [_currentStep, guessPreviousAvailableStep]);\n\n  const _getNextArrayItem = (el: HTMLElement) => {\n    const currentIndex = stepElementsRef.current.indexOf(el);\n    const nextItem = (currentIndex + 1) % stepElementsRef.current.length;\n    return stepElementsRef.current[nextItem];\n  };\n\n  const _getPreviousArrayItem = (el: HTMLElement) => {\n    const currentIndex = stepElementsRef.current.indexOf(el);\n    const previousItem =\n      (currentIndex - 1 + stepElementsRef.current.length) %\n      stepElementsRef.current.length;\n    return stepElementsRef.current[previousItem];\n  };\n\n  // handle keydown\n  const handleKeydown = React.useCallback(\n    (event: KeyboardEvent<HTMLElement>, index: number) => {\n      const kbLeftRightArrowsKeys = [37, 39];\n      const kbEnterSpaceKeys = [13, 32];\n      const previousElement = stepElementsRef.current[index - 1];\n      const nextElement = stepElementsRef.current[index + 1];\n      const nextElToFocus = _getNextArrayItem(nextElement);\n      const prevElToFocus = _getPreviousArrayItem(previousElement);\n      // Only focus if the next element is not disabled\n      const isNextElementDisabled = nextElement?.getAttribute('aria-disabled');\n      const isNextElementDisabledBoolean = isNextElementDisabled === 'true';\n      const isPreviousElementDisabled =\n        previousElement?.getAttribute('aria-disabled');\n      const isPreviousElementDisabledBoolean =\n        isPreviousElementDisabled === 'true';\n\n      if (kbLeftRightArrowsKeys.includes(event?.keyCode)) {\n        event?.preventDefault();\n        // Focus prev or next step when user press left or right arrow\n        if (event?.keyCode === 39) {\n          if (isNextElementDisabledBoolean) {\n            nextElToFocus?.focus();\n            currentStepFocused.current = stepElementsRef.current.findIndex(\n              (el) => el.id === nextElToFocus.id\n            );\n            return;\n          }\n          stepElementsRef.current[index + 1]?.focus();\n          currentStepFocused.current = index + 1;\n        }\n        if (event?.keyCode === 37) {\n          if (isPreviousElementDisabledBoolean) {\n            prevElToFocus?.focus();\n            currentStepFocused.current = stepElementsRef.current.findIndex(\n              (el) => el.id === prevElToFocus.id\n            );\n            return;\n          }\n          stepElementsRef.current[index - 1]?.focus();\n          currentStepFocused.current = index - 1;\n        }\n      }\n      if (kbEnterSpaceKeys.includes(event?.keyCode)) {\n        // If user press enter or space, go to next step\n        setCurrentStep(currentStepFocused.current as number);\n      }\n    },\n    []\n  );\n\n  // build the stepper props.\n  const stepperProps: HTMLAttributes<HTMLElement> = React.useMemo(\n    () => ({\n      role: 'tablist',\n      'aria-orientation': orientation,\n    }),\n    [orientation]\n  );\n\n  // Build the steps props.\n  const stepsProps = React.useMemo(() => {\n    // TODO: Maybe return aria-controls?\n    return steps?.map((step, index) => {\n      return {\n        role: 'tab',\n        tabIndex: index === _currentStep ? 0 : -1,\n        id: `${stepperId}-${index}`,\n        'aria-posinset': index + 1,\n        'aria-setsize': steps.length,\n        'aria-disabled': step?.disabled,\n        'aria-current': index === _currentStep ? 'step' : undefined,\n        'aria-selected': index === _currentStep,\n        onKeyDown: (event) => handleKeydown(event, index),\n        onClick: () => (step.disabled ? null : setCurrentStep(index)),\n        ref: (element: HTMLElement) =>\n          (stepElementsRef.current[index] = element),\n      } as HTMLAttributes<HTMLElement>;\n    });\n  }, [_currentStep, handleKeydown, stepperId, steps]);\n\n  // build the progress bar props.\n  const progressProps = React.useMemo<HTMLAttributes<HTMLElement>>(\n    () => ({\n      'aria-valuenow': _currentStep,\n      'aria-valuemin': 0,\n      'aria-valuemax': steps.length - 1,\n      role: 'progressbar',\n      'aria-labelledby': labelId,\n      tabIndex: -1, // prevent focus\n    }),\n    [_currentStep, labelId, steps]\n  );\n\n  // build the stepper state.\n  const state = React.useMemo(\n    () => ({\n      labelId,\n      progressId: progressId as string,\n      currentStep: _currentStep,\n      hasPreviousStep: hasPreviousStep.current,\n      hasNextStep: hasNextStep.current,\n      totalSteps: totalSteps.current,\n    }),\n    [progressId, labelId, _currentStep]\n  );\n\n  return {\n    stepperProps,\n    stepsProps,\n    progressProps,\n    state,\n    nextStep,\n    prevStep,\n    setStep: setCurrentStep,\n  };\n};\n\nexport {\n  useStepper,\n  StepperProps,\n  StepperState,\n  UseStepper,\n  // Reexport internal types\n  Steps,\n};\n"],"mappings":"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","names":["React","React","nextStep","currentStep"]}