{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "button-progress",
  "type": "registry:ui",
  "title": "Progress Button",
  "description": "Button with an integrated timed progress layer and completion callback.",
  "dependencies": [
    "@mantine/core@^9",
    "@mantine/hooks@^9"
  ],
  "docs": "Adapted from Mantine UI ButtonProgress at ffbf61c559f374a7ea28fcf00355e84dcbe9a908; labels, duration and completion are configurable.",
  "registryDependencies": [
    "@house/mantine-ui-license"
  ],
  "files": [
    {
      "path": "registry/mantine-ui/button-progress/button-progress.tsx",
      "type": "registry:ui",
      "content": "/**\n * Adapted from Mantine UI's ButtonProgress at\n * ffbf61c559f374a7ea28fcf00355e84dcbe9a908. MIT licensed; see\n * LICENSES/MANTINE-UI.txt after installation.\n */\n\nimport {\n  Button,\n  type ButtonProps,\n  type ButtonVariant,\n  type Factory,\n  factory,\n  Progress,\n  rgba,\n  type StylesApiProps,\n  useMantineTheme,\n  useProps,\n  useStyles,\n} from \"@mantine/core\";\nimport { useInterval } from \"@mantine/hooks\";\nimport { useState } from \"react\";\n\nimport classes from \"./button-progress.module.css\";\n\nexport type ButtonProgressStylesNames = \"root\" | \"label\";\n\nexport interface ButtonProgressProps\n  extends Omit<\n      ButtonProps,\n      | \"children\"\n      | \"onClick\"\n      | \"classNames\"\n      | \"styles\"\n      | \"vars\"\n      | \"unstyled\"\n      | \"attributes\"\n      | \"variant\"\n    >,\n    StylesApiProps<ButtonProgressFactory> {\n  /** Key of Button's variant, e.g. `\"filled\"` @default 'filled' */\n  variant?: ButtonVariant;\n  idleLabel?: string;\n  progressLabel?: string;\n  completeLabel?: string;\n  durationMs?: number;\n  onComplete?: () => void;\n}\n\nexport type ButtonProgressFactory = Factory<{\n  props: ButtonProgressProps;\n  ref: HTMLButtonElement;\n  stylesNames: ButtonProgressStylesNames;\n}>;\n\nconst TICK_MS = 20;\n\nexport const ButtonProgress = factory<ButtonProgressFactory>((_props) => {\n  const props = useProps(\"ButtonProgress\", null, _props);\n  const {\n    classNames,\n    className,\n    style,\n    styles,\n    unstyled,\n    vars,\n    attributes,\n    ref,\n    idleLabel = \"Upload files\",\n    progressLabel = \"Uploading files\",\n    completeLabel = \"Files uploaded\",\n    durationMs = 2000,\n    onComplete,\n    color,\n    ...others\n  } = props;\n\n  const theme = useMantineTheme();\n  const [progress, setProgress] = useState(0);\n  const [complete, setComplete] = useState(false);\n  const step = (TICK_MS / Math.max(durationMs, TICK_MS)) * 100;\n\n  const getStyles = useStyles<ButtonProgressFactory>({\n    name: \"ButtonProgress\",\n    classes,\n    props,\n    className,\n    style,\n    classNames,\n    styles,\n    unstyled,\n    attributes,\n    vars,\n  });\n\n  const interval = useInterval(() => {\n    setProgress((current) => {\n      const next = current + step;\n      if (next < 100) return next;\n\n      interval.stop();\n      setComplete(true);\n      onComplete?.();\n      return 0;\n    });\n  }, TICK_MS);\n\n  const start = () => {\n    if (complete) {\n      setComplete(false);\n      return;\n    }\n    if (!interval.active) interval.start();\n  };\n\n  return (\n    <Button\n      ref={ref}\n      fullWidth\n      unstyled={unstyled}\n      {...getStyles(\"root\")}\n      {...others}\n      onClick={start}\n      color={complete ? \"teal.9\" : (color ?? `${theme.primaryColor}.9`)}\n    >\n      <span {...getStyles(\"label\")} aria-live=\"polite\">\n        {progress > 0 ? progressLabel : complete ? completeLabel : idleLabel}\n      </span>\n      {progress > 0 && (\n        <Progress\n          value={progress}\n          className={classes.progress}\n          color={rgba(theme.colors.blue[2], 0.35)}\n          radius=\"sm\"\n        />\n      )}\n    </Button>\n  );\n});\n\nButtonProgress.classes = classes;\nButtonProgress.displayName = \"ButtonProgress\";\n\nexport namespace ButtonProgress {\n  export type Props = ButtonProgressProps;\n  export type StylesNames = ButtonProgressStylesNames;\n  export type Factory = ButtonProgressFactory;\n}\n"
    },
    {
      "path": "registry/mantine-ui/button-progress/button-progress.module.css",
      "type": "registry:file",
      "target": "@ui/button-progress.module.css",
      "content": "/*\n * Adapted from Mantine UI's ButtonProgress at\n * ffbf61c559f374a7ea28fcf00355e84dcbe9a908. MIT licensed; see\n * LICENSES/MANTINE-UI.txt after installation.\n */\n.root {\n  position: relative;\n  transition: background-color 150ms ease;\n}\n\n.progress {\n  position: absolute;\n  z-index: 0;\n  inset: -1px;\n  height: auto;\n  background-color: transparent;\n}\n\n.label {\n  position: relative;\n  z-index: 1;\n}\n"
    }
  ],
  "meta": {
    "mantine": {
      "requires": ">=9",
      "provider": "MantineProvider",
      "stylesApi": {
        "ButtonProgress": [
          "root",
          "label"
        ]
      },
      "props": {
        "ButtonProgress": [
          {
            "name": "idleLabel",
            "type": "string",
            "required": false,
            "default": "\"Upload files\"",
            "description": "Sets the label shown before the action has started."
          },
          {
            "name": "progressLabel",
            "type": "string",
            "required": false,
            "default": "\"Uploading files\"",
            "description": "Sets the label shown while progress is animating toward completion."
          },
          {
            "name": "completeLabel",
            "type": "string",
            "required": false,
            "default": "\"Files uploaded\"",
            "description": "Sets the label shown once the progress run has finished."
          },
          {
            "name": "durationMs",
            "type": "number",
            "required": false,
            "default": "2000",
            "description": "Controls how long the simulated progress run takes to reach completion."
          },
          {
            "name": "onComplete",
            "type": "() => void",
            "required": false,
            "description": "Fires once the progress bar reaches 100% and the button switches to its complete state."
          },
          {
            "name": "...others",
            "type": "Omit<ButtonProps, \"children\" | \"onClick\" | \"classNames\" | \"styles\" | \"vars\" | \"unstyled\" | \"attributes\" | \"variant\">",
            "description": "All other props are forwarded to the root <Button>, after its own fullWidth, so both can be overridden; onClick and color are controlled by the component's internal progress/complete state and always win. Mantine Styles API props (classNames, styles, unstyled) are also accepted."
          }
        ]
      },
      "usage": {
        "path": "registry/mantine-ui/button-progress/button-progress.usage.tsx",
        "content": "import { ButtonProgress } from \"@/components/ui/button-progress\";\n\nexport function UploadFilesButton() {\n  return (\n    <ButtonProgress\n      idleLabel=\"Upload files\"\n      progressLabel=\"Uploading files\"\n      completeLabel=\"Files uploaded\"\n      durationMs={2500}\n      onComplete={() => console.log(\"upload complete\")}\n    />\n  );\n}\n"
      }
    }
  }
}
