{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "meter",
  "title": "Meter",
  "description": "A meter component.",
  "dependencies": [
    "class-variance-authority"
  ],
  "files": [
    {
      "path": "registry/default/meter/meter.tsx",
      "content": "\"use client\";\r\n\r\nimport * as React from \"react\";\r\nimport { Meter as BaseMeter } from \"@base-ui/react/meter\";\r\nimport { cva, type VariantProps } from \"class-variance-authority\";\r\n\r\nimport { cn } from \"@/lib/utils\";\r\n\r\nconst meterRootVariants = cva(\"max-w-[300px] w-full flex flex-col\", {\r\n  variants: {\r\n    size: {\r\n      sm: \"gap-2\",\r\n      md: \"gap-2\",\r\n      lg: \"gap-2\",\r\n    },\r\n  },\r\n  defaultVariants: {\r\n    size: \"md\",\r\n  },\r\n});\r\n\r\ninterface MeterRootProps\r\n  extends React.ComponentProps<typeof BaseMeter.Root>,\r\n    VariantProps<typeof meterRootVariants> {\r\n  animated?: boolean;\r\n  low?: number;\r\n  high?: number;\r\n  optimumMin?: number;\r\n  optimumMax?: number;\r\n  showOptimumMarkers?: boolean;\r\n  showThresholdColors?: boolean;\r\n}\r\n\r\nfunction MeterRoot({\r\n  className,\r\n  children,\r\n  size = \"md\",\r\n  animated = false,\r\n  value = 0,\r\n  min = 0,\r\n  max = 100,\r\n  low,\r\n  high,\r\n  optimumMin,\r\n  optimumMax,\r\n  showOptimumMarkers = true,\r\n  showThresholdColors = true,\r\n  ...props\r\n}: MeterRootProps) {\r\n  const optimumStyles =\r\n    optimumMin !== undefined && optimumMax !== undefined\r\n      ? {\r\n          \"--meter-optimum-min-percent\": `${((optimumMin - min) / (max - min)) * 100}%`,\r\n          \"--meter-optimum-max-percent\": `${((optimumMax - min) / (max - min)) * 100}%`,\r\n          \"--meter-optimum-width-percent\": `${((optimumMax - optimumMin) / (max - min)) * 100}%`,\r\n        }\r\n      : {};\r\n\r\n  // Status from thresholds, most-specific config first:\r\n  const getStatus = () => {\r\n    // Range (optimumMin + optimumMax): in-range is optimal, low/high mark danger\r\n    if (optimumMin !== undefined && optimumMax !== undefined) {\r\n      if (low !== undefined && value < low) return \"danger\";\r\n      if (high !== undefined && value > high) return \"danger\";\r\n      if (value >= optimumMin && value <= optimumMax) return \"optimal\";\r\n      return \"suboptimal\";\r\n    }\r\n\r\n    // Directional three-tier, higher is better (e.g. battery: low=15, optimumMin=75)\r\n    if (optimumMin !== undefined && low !== undefined) {\r\n      if (value < low) return \"danger\";\r\n      if (value >= optimumMin) return \"optimal\";\r\n      return \"suboptimal\";\r\n    }\r\n\r\n    // Directional three-tier, lower is better (e.g. temp: optimumMax=60, high=80)\r\n    if (optimumMax !== undefined && high !== undefined) {\r\n      if (value > high) return \"danger\";\r\n      if (value <= optimumMax) return \"optimal\";\r\n      return \"suboptimal\";\r\n    }\r\n\r\n    // Two-tier: low only (higher is better)\r\n    if (low !== undefined && high === undefined) {\r\n      if (value < low) return \"danger\";\r\n      return \"optimal\";\r\n    }\r\n\r\n    // Two-tier: high only (lower is better)\r\n    if (high !== undefined && low === undefined) {\r\n      if (value > high) return \"danger\";\r\n      return \"optimal\";\r\n    }\r\n\r\n    // Two-tier: both (middle is best)\r\n    if (low !== undefined && high !== undefined) {\r\n      if (value < low || value > high) return \"danger\";\r\n      return \"optimal\";\r\n    }\r\n\r\n    return \"normal\";\r\n  };\r\n\r\n  return (\r\n    <BaseMeter.Root\r\n      value={value}\r\n      min={min}\r\n      max={max}\r\n      data-slot=\"meter\"\r\n      data-size={size}\r\n      data-animated={animated}\r\n      data-low={low}\r\n      data-high={high}\r\n      data-optimum-min={showOptimumMarkers ? optimumMin : undefined}\r\n      data-optimum-max={showOptimumMarkers ? optimumMax : undefined}\r\n      data-status={showThresholdColors ? getStatus() : \"normal\"}\r\n      className={cn(\"group/meter\", meterRootVariants({ size }), className)}\r\n      style={optimumStyles as React.CSSProperties}\r\n      {...props}\r\n    >\r\n      {children}\r\n    </BaseMeter.Root>\r\n  );\r\n}\r\n\r\ninterface MeterTrackProps extends React.ComponentProps<typeof BaseMeter.Track> {\r\n  segments?: number;\r\n  striped?: boolean;\r\n  gradient?: boolean;\r\n}\r\n\r\nfunction MeterTrack({\r\n  className,\r\n  children,\r\n  segments,\r\n  striped,\r\n  gradient,\r\n  ...props\r\n}: MeterTrackProps) {\r\n  return (\r\n    <div className=\"relative\">\r\n      <BaseMeter.Track\r\n        data-slot=\"meter-track\"\r\n        data-segments={segments}\r\n        data-striped={striped}\r\n        data-gradient={gradient}\r\n        className={cn(\r\n          \"bg-primary/20 relative w-full overflow-hidden rounded-md\",\r\n          \"group-data-[size=lg]/meter:h-3 group-data-[size=md]/meter:h-2 group-data-[size=sm]/meter:h-1.5\",\r\n          striped &&\r\n            \"from-primary/20 to-primary/30 bg-gradient-to-r bg-[length:1rem_1rem]\",\r\n          gradient &&\r\n            \"from-primary/10 via-primary/20 to-primary/10 bg-gradient-to-r\",\r\n          className,\r\n        )}\r\n        {...props}\r\n      >\r\n        {children}\r\n        {segments && segments > 1 && <MeterSegments segments={segments} />}\r\n        <MeterOptimumTicks />\r\n      </BaseMeter.Track>\r\n      <MeterOptimumRangeLine />\r\n    </div>\r\n  );\r\n}\r\n\r\nfunction MeterSegments({ segments }: { segments: number }) {\r\n  return (\r\n    <div className=\"absolute inset-0\">\r\n      {Array.from({ length: segments - 1 }).map((_, i) => (\r\n        <div\r\n          key={i}\r\n          className=\"bg-background/50 absolute top-0 bottom-0 w-px\"\r\n          style={{ left: `${((i + 1) / segments) * 100}%` }}\r\n        />\r\n      ))}\r\n    </div>\r\n  );\r\n}\r\n\r\n// Vertical tick markers above the track. Shown only when both optimumMin and\r\n// optimumMax are set (the doubled group-data selector).\r\nfunction MeterOptimumTicks() {\r\n  return (\r\n    <div className=\"pointer-events-none absolute inset-0 hidden group-data-[optimum-min]/meter:group-data-[optimum-max]/meter:block\">\r\n      {/* Start marker */}\r\n      <div\r\n        className=\"absolute -top-2 h-3 w-px\"\r\n        style={{ left: \"calc(var(--meter-optimum-min-percent) - 0.5px)\" }}\r\n      >\r\n        <div className=\"bg-foreground ring-background h-full w-full rounded-full ring-1\" />\r\n      </div>\r\n      {/* End marker */}\r\n      <div\r\n        className=\"absolute -top-2 h-3 w-px\"\r\n        style={{ left: \"calc(var(--meter-optimum-max-percent) - 0.5px)\" }}\r\n      >\r\n        <div className=\"bg-foreground ring-background h-full w-full rounded-full ring-1\" />\r\n      </div>\r\n    </div>\r\n  );\r\n}\r\n\r\n// Horizontal range line below the track. Same dual-optimum visibility gate.\r\nfunction MeterOptimumRangeLine() {\r\n  return (\r\n    <div className=\"pointer-events-none absolute inset-x-0 top-full hidden group-data-[optimum-min]/meter:group-data-[optimum-max]/meter:block\">\r\n      <div\r\n        className=\"absolute top-0.5 h-0.5\"\r\n        style={{\r\n          left: \"calc(var(--meter-optimum-min-percent) - 0.25px)\",\r\n          width: \"calc(var(--meter-optimum-width-percent) + 0.5px)\",\r\n        }}\r\n      >\r\n        <div className=\"bg-foreground/70 ring-background h-full w-full rounded-full ring-1\" />\r\n      </div>\r\n    </div>\r\n  );\r\n}\r\n\r\nfunction MeterIndicator({\r\n  className,\r\n  ...props\r\n}: React.ComponentProps<typeof BaseMeter.Indicator>) {\r\n  return (\r\n    <BaseMeter.Indicator\r\n      data-slot=\"meter-indicator\"\r\n      className={cn(\r\n        \"h-full\",\r\n        \"group-data-[animated=true]/meter:transition-all group-data-[animated=true]/meter:duration-300 group-data-[animated=true]/meter:ease-out\",\r\n        // Status-based colors using semantic theme colors\r\n        \"group-data-[status=normal]/meter:bg-primary\",\r\n        \"group-data-[status=optimal]/meter:bg-success\",\r\n        \"group-data-[status=suboptimal]/meter:bg-warning\",\r\n        \"group-data-[status=danger]/meter:bg-danger\",\r\n        className,\r\n      )}\r\n      {...props}\r\n    />\r\n  );\r\n}\r\n\r\nfunction MeterLabel({\r\n  className,\r\n  ...props\r\n}: React.ComponentProps<typeof BaseMeter.Label>) {\r\n  return (\r\n    <BaseMeter.Label\r\n      data-slot=\"meter-label\"\r\n      className={cn(\r\n        \"font-medium\",\r\n        \"group-data-[size=lg]/meter:text-base group-data-[size=md]/meter:text-sm group-data-[size=sm]/meter:text-xs\",\r\n        className,\r\n      )}\r\n      {...props}\r\n    />\r\n  );\r\n}\r\n\r\nfunction MeterValue({\r\n  className,\r\n  ...props\r\n}: React.ComponentProps<typeof BaseMeter.Value>) {\r\n  return (\r\n    <BaseMeter.Value\r\n      data-slot=\"meter-value\"\r\n      className={cn(\r\n        \"text-muted-foreground\",\r\n        \"group-data-[size=lg]/meter:text-base group-data-[size=md]/meter:text-sm group-data-[size=sm]/meter:text-xs\",\r\n        className,\r\n      )}\r\n      {...props}\r\n    />\r\n  );\r\n}\r\n\r\n// Legacy default export for backward compatibility\r\nfunction Meter({\r\n  className,\r\n  children,\r\n  low,\r\n  high,\r\n  optimumMin,\r\n  optimumMax,\r\n  ...props\r\n}: MeterRootProps) {\r\n  return (\r\n    <MeterRoot\r\n      className={className}\r\n      low={low}\r\n      high={high}\r\n      optimumMin={optimumMin}\r\n      optimumMax={optimumMax}\r\n      {...props}\r\n    >\r\n      {children}\r\n      <MeterTrack>\r\n        <MeterIndicator />\r\n      </MeterTrack>\r\n    </MeterRoot>\r\n  );\r\n}\r\n\r\nexport {\r\n  Meter,\r\n  MeterRoot,\r\n  MeterTrack,\r\n  MeterIndicator,\r\n  MeterLabel,\r\n  MeterValue,\r\n  type MeterRootProps,\r\n  type MeterTrackProps,\r\n};\r\n",
      "type": "registry:ui",
      "target": "components/ui/cubby-ui/meter.tsx"
    }
  ],
  "type": "registry:ui"
}