{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "loading-bar",
  "title": "Loading Bar",
  "description": "A global top-edge loading indicator with local rendering and provider-driven controls.",
  "files": [
    {
      "path": "registry/rivetui/components/loading-bar/loading-bar.tsx",
      "content": "\"use client\";\n\nimport * as React from \"react\";\n\nimport { cn } from \"@/lib/utils\";\n\ntype LoadingBarPosition = \"fixed\" | \"absolute\";\n\ntype LoadingBarProps = Omit<React.ComponentProps<\"div\">, \"children\"> & {\n  active?: boolean;\n  value?: number;\n  position?: LoadingBarPosition;\n  label?: string;\n};\n\ntype LoadingBarController = {\n  active: boolean;\n  value: number | undefined;\n  start: (label?: string) => void;\n  setProgress: (value: number, label?: string) => void;\n  complete: () => void;\n  reset: () => void;\n};\n\ntype LoadingBarProviderProps = React.PropsWithChildren<{\n  className?: string;\n  completionDuration?: number;\n  label?: string;\n  position?: LoadingBarPosition;\n}>;\n\ntype LoadingBarState = {\n  active: boolean;\n  label: string | undefined;\n  value: number | undefined;\n};\n\nconst LoadingBarContext = React.createContext<LoadingBarController | null>(null);\n\nfunction LoadingBar({\n  active = true,\n  value,\n  position = \"fixed\",\n  label = \"Loading page\",\n  className,\n  ...props\n}: LoadingBarProps) {\n  const determinate = value !== undefined;\n  const normalizedValue = determinate ? Math.min(100, Math.max(0, value)) : undefined;\n\n  return (\n    <div\n      data-slot=\"loading-bar\"\n      data-active={active ? \"\" : undefined}\n      data-state={active ? \"loading\" : \"idle\"}\n      data-mode={determinate ? \"determinate\" : \"indeterminate\"}\n      data-position={position}\n      role=\"progressbar\"\n      aria-label={active ? label : undefined}\n      aria-hidden={active ? undefined : true}\n      aria-valuemin={active && determinate ? 0 : undefined}\n      aria-valuemax={active && determinate ? 100 : undefined}\n      aria-valuenow={active ? normalizedValue : undefined}\n      className={cn(\n        \"pointer-events-none top-0 right-0 left-0 z-100 h-0.5 overflow-hidden opacity-0 transition-opacity duration-150 data-active:opacity-100 data-[position=absolute]:absolute data-[position=fixed]:fixed motion-reduce:transition-none\",\n        className,\n      )}\n      {...props}\n    >\n      <span\n        data-slot=\"loading-bar-indicator\"\n        className={cn(\n          \"block h-full bg-foreground\",\n          determinate\n            ? \"transition-[width] duration-200 ease-out motion-reduce:transition-none\"\n            : \"w-1/3 animate-[rivet-loading-bar_1.15s_ease-in-out_infinite] motion-reduce:w-full motion-reduce:animate-none\",\n        )}\n        style={determinate ? { width: `${normalizedValue}%` } : undefined}\n      />\n      <style>{`@keyframes rivet-loading-bar{0%{transform:translateX(-110%) scaleX(.55)}50%{transform:translateX(150%) scaleX(1)}100%{transform:translateX(410%) scaleX(.55)}}`}</style>\n    </div>\n  );\n}\n\nfunction LoadingBarProvider({\n  children,\n  className,\n  completionDuration = 200,\n  label = \"Loading page\",\n  position = \"fixed\",\n}: LoadingBarProviderProps) {\n  const [state, setState] = React.useState<LoadingBarState>({\n    active: false,\n    label: undefined,\n    value: undefined,\n  });\n  const completionTimerRef = React.useRef<number | undefined>(undefined);\n\n  const clearCompletionTimer = React.useCallback(() => {\n    if (completionTimerRef.current !== undefined) {\n      window.clearTimeout(completionTimerRef.current);\n      completionTimerRef.current = undefined;\n    }\n  }, []);\n\n  React.useEffect(() => clearCompletionTimer, [clearCompletionTimer]);\n\n  const start = React.useCallback(\n    (nextLabel?: string) => {\n      clearCompletionTimer();\n      setState({ active: true, label: nextLabel, value: undefined });\n    },\n    [clearCompletionTimer],\n  );\n\n  const setProgress = React.useCallback(\n    (value: number, nextLabel?: string) => {\n      clearCompletionTimer();\n      setState((currentState) => ({\n        active: true,\n        label: nextLabel ?? currentState.label,\n        value: Math.min(100, Math.max(0, value)),\n      }));\n    },\n    [clearCompletionTimer],\n  );\n\n  const complete = React.useCallback(() => {\n    clearCompletionTimer();\n    setState((currentState) => ({ ...currentState, active: true, value: 100 }));\n    completionTimerRef.current = window.setTimeout(\n      () => {\n        completionTimerRef.current = undefined;\n        setState({ active: false, label: undefined, value: undefined });\n      },\n      Math.max(0, completionDuration),\n    );\n  }, [clearCompletionTimer, completionDuration]);\n\n  const reset = React.useCallback(() => {\n    clearCompletionTimer();\n    setState({ active: false, label: undefined, value: undefined });\n  }, [clearCompletionTimer]);\n\n  const controller = React.useMemo<LoadingBarController>(\n    () => ({\n      active: state.active,\n      value: state.value,\n      start,\n      setProgress,\n      complete,\n      reset,\n    }),\n    [complete, reset, setProgress, start, state.active, state.value],\n  );\n\n  return (\n    <LoadingBarContext.Provider value={controller}>\n      {children}\n      <LoadingBar\n        active={state.active}\n        value={state.value}\n        position={position}\n        label={state.label ?? label}\n        className={className}\n      />\n    </LoadingBarContext.Provider>\n  );\n}\n\nfunction useLoadingBar() {\n  const context = React.useContext(LoadingBarContext);\n  if (!context) {\n    throw new Error(\"useLoadingBar must be used within a LoadingBarProvider.\");\n  }\n  return context;\n}\n\nexport type { LoadingBarController, LoadingBarPosition, LoadingBarProps, LoadingBarProviderProps };\nexport { LoadingBar, LoadingBarProvider, useLoadingBar };\n",
      "type": "registry:ui"
    }
  ],
  "type": "registry:ui"
}