{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "spinner",
  "title": "Spinner",
  "description": "A thin, unhurried arc that says something is working.",
  "dependencies": [
    "@stylexjs/stylex"
  ],
  "registryDependencies": [
    "https://constella.aayush.cv/r/base.json"
  ],
  "files": [
    {
      "path": "src/components/primitives/spinner.tsx",
      "content": "\"use client\";\n\nimport * as stylex from \"@stylexjs/stylex\";\nimport type { ComponentProps } from \"react\";\n\nimport type { Sx } from \"@/lib/constella/styles\";\nimport {\n  colors,\n  durations,\n  radii,\n  sizes,\n  space,\n  strokes,\n} from \"@/lib/constella/tokens.stylex\";\n\ntype SpinnerProps = Omit<ComponentProps<\"output\">, \"className\" | \"style\"> & {\n  sx?: Sx;\n};\n\n// A badge sets its icons at `iconXs` (`iconSm` at lg), so its spinner steps down with them.\nconst inBadge = \":where([data-slot='badge']:not([data-size='lg']) *)\";\nconst inLgBadge = \":where([data-slot='badge'][data-size='lg'] *)\";\nconst badgeSpinner = `calc(${sizes.iconXs} - ${space.xxxs})`;\nconst lgBadgeSpinner = `calc(${sizes.iconSm} - ${space.xxxs})`;\n\n// An outline badge keeps its text neutral, so its spinner carries the color.\nconst inColor = (color: string) =>\n  `:where([data-slot='badge'][data-variant='outline'][data-color='${color}'] *)`;\n\nconst spin = stylex.keyframes({ to: { transform: \"rotate(360deg)\" } });\n\nconst styles = stylex.create({\n  // A step smaller than an icon, centered in an icon's box, so the two swap in place.\n  spinner: {\n    animationDuration: durations.spin,\n    animationIterationCount: \"infinite\",\n    animationName: spin,\n    animationTimingFunction: \"linear\",\n    borderBlockEndColor: colors.fillStrong,\n    borderBlockStartColor: \"currentColor\",\n    borderInlineEndColor: colors.fillStrong,\n    borderInlineStartColor: colors.fillStrong,\n    borderStartStartRadius: radii.full,\n    borderStartEndRadius: radii.full,\n    borderEndStartRadius: radii.full,\n    borderEndEndRadius: radii.full,\n    borderBlockStyle: \"solid\",\n    borderInlineStyle: \"solid\",\n    borderBlockWidth: strokes.spinner,\n    borderInlineWidth: strokes.spinner,\n    color: {\n      default: null,\n      [inColor(\"success\")]: colors.successText,\n      [inColor(\"info\")]: colors.infoText,\n      [inColor(\"warning\")]: colors.warningText,\n      [inColor(\"danger\")]: colors.dangerText,\n    },\n    display: \"inline-block\",\n    flexShrink: 0,\n    height: {\n      default: sizes.iconSm,\n      [inBadge]: badgeSpinner,\n      [inLgBadge]: lgBadgeSpinner,\n    },\n    marginBlock: {\n      default: `calc((${sizes.icon} - ${sizes.iconSm}) / 2)`,\n      [inBadge]: `calc((${sizes.iconXs} - ${badgeSpinner}) / 2)`,\n      [inLgBadge]: `calc((${sizes.iconSm} - ${lgBadgeSpinner}) / 2)`,\n    },\n    marginInline: {\n      default: `calc((${sizes.icon} - ${sizes.iconSm}) / 2)`,\n      [inBadge]: `calc((${sizes.iconXs} - ${badgeSpinner}) / 2)`,\n      [inLgBadge]: `calc((${sizes.iconSm} - ${lgBadgeSpinner}) / 2)`,\n    },\n    width: {\n      default: sizes.iconSm,\n      [inBadge]: badgeSpinner,\n      [inLgBadge]: lgBadgeSpinner,\n    },\n  },\n});\n\nfunction Spinner({ sx, ...props }: SpinnerProps) {\n  return (\n    <output\n      aria-label=\"Loading\"\n      data-slot=\"spinner\"\n      {...props}\n      {...stylex.props(styles.spinner, sx)}\n    />\n  );\n}\n\nexport { Spinner };\nexport type { SpinnerProps };\n",
      "type": "registry:component"
    }
  ],
  "docs": "Usage: https://constella.aayush.cv/docs/components/spinner/index.md",
  "type": "registry:ui"
}