{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "calculation",
  "type": "registry:ui",
  "files": [
    {
      "path": "registry/designali/ui/calculation.tsx",
      "content": "\"use client\"\n\nimport { cn } from \"@workspace/ui/lib/utils\"\nimport { useMemo, useState } from \"react\" \n \n\nexport type Operation =\n  | \"sum\"\n  | \"average\"\n  | \"min\"\n  | \"max\"\n  | \"count\"\n  | \"add\"\n  | \"subtract\"\n  | \"multiply\"\n  | \"divide\"\n  | \"percentage\"\n  | \"percentage-change\"\n  | \"remainder\"\n  | \"power\"\n  | \"sqrt\"\n  | \"absolute\"\n  | \"round\"\n  | \"floor\"\n  | \"ceil\"\n  | \"factorial\"\n  | \"gcd\"\n  | \"lcm\"\n\nexport interface CalculationProps extends React.HTMLAttributes<HTMLDivElement> {\n  defaultOperation?: Operation\n  defaultInput?: string\n}\n\nconst operations: {\n  label: string\n  value: Operation\n}[] = [\n  { label: \"Sum\", value: \"sum\" },\n  { label: \"Average\", value: \"average\" },\n  { label: \"Minimum\", value: \"min\" },\n  { label: \"Maximum\", value: \"max\" },\n  { label: \"Count\", value: \"count\" },\n  { label: \"Add\", value: \"add\" },\n  { label: \"Subtract\", value: \"subtract\" },\n  { label: \"Multiply\", value: \"multiply\" },\n  { label: \"Divide\", value: \"divide\" },\n  { label: \"Percentage\", value: \"percentage\" },\n  { label: \"Percentage Change\", value: \"percentage-change\" },\n  { label: \"Remainder\", value: \"remainder\" },\n  { label: \"Power\", value: \"power\" },\n  { label: \"Square Root\", value: \"sqrt\" },\n  { label: \"Absolute\", value: \"absolute\" },\n  { label: \"Round\", value: \"round\" },\n  { label: \"Floor\", value: \"floor\" },\n  { label: \"Ceiling\", value: \"ceil\" },\n  { label: \"Factorial\", value: \"factorial\" },\n  { label: \"GCD\", value: \"gcd\" },\n  { label: \"LCM\", value: \"lcm\" },\n]\n\nfunction gcd(a: number, b: number): number {\n  a = Math.abs(a)\n  b = Math.abs(b)\n  while (b) {\n    const temp = b\n    b = a % b\n    a = temp\n  }\n  return a\n}\n\nfunction factorial(n: number): number {\n  if (n < 0 || !Number.isInteger(n)) return NaN\n  let result = 1\n  for (let i = 2; i <= n; i++) {\n    result *= i\n  }\n  return result\n}\n\nfunction calculate(operation: Operation, values: number[]): number {\n  const [a = 0, b = 0] = values\n\n  switch (operation) {\n    case \"sum\":\n      return values.reduce((total, value) => total + value, 0)\n    case \"average\":\n      return values.length\n        ? values.reduce((total, value) => total + value, 0) / values.length\n        : 0\n    case \"min\":\n      return values.length ? Math.min(...values) : 0\n    case \"max\":\n      return values.length ? Math.max(...values) : 0\n    case \"count\":\n      return values.length\n    case \"add\":\n      return a + b\n    case \"subtract\":\n      return a - b\n    case \"multiply\":\n      return a * b\n    case \"divide\":\n      return b === 0 ? NaN : a / b\n    case \"percentage\":\n      return (a * b) / 100\n    case \"percentage-change\":\n      return a === 0 ? NaN : ((b - a) / a) * 100\n    case \"remainder\":\n      return b === 0 ? NaN : a % b\n    case \"power\":\n      return Math.pow(a, b)\n    case \"sqrt\":\n      return Math.sqrt(a)\n    case \"absolute\":\n      return Math.abs(a)\n    case \"round\":\n      return Math.round(a)\n    case \"floor\":\n      return Math.floor(a)\n    case \"ceil\":\n      return Math.ceil(a)\n    case \"factorial\":\n      return factorial(a)\n    case \"gcd\":\n      return gcd(a, b)\n    case \"lcm\":\n      return a && b ? Math.abs(a * b) / gcd(a, b) : 0\n    default:\n      return 0\n  }\n}\n\nexport function Calculation({\n  defaultOperation = \"sum\",\n  defaultInput = \"100, 200, 300\",\n  className,\n  ...props\n}: CalculationProps) {\n  const [operation, setOperation] = useState<Operation>(defaultOperation)\n  const [input, setInput] = useState(defaultInput)\n\n  const values = useMemo(\n    () =>\n      input\n        .split(\",\")\n        .map((value) => Number(value.trim()))\n        .filter((value) => !Number.isNaN(value)),\n    [input]\n  )\n\n  const result = calculate(operation, values)\n\n  const formattedResult = Number.isNaN(result)\n    ? \"Invalid calculation\"\n    : Number.isFinite(result)\n      ? Number(result.toFixed(6)).toLocaleString()\n      : \"Invalid calculation\"\n\n  return (\n    <div\n      className={cn(\n        \"w-full max-w-2xl rounded-xl border bg-background p-6 text-foreground shadow-sm\",\n        className\n      )}\n      {...props}\n    >\n       \n      <div className=\"mt-6 flex flex-wrap gap-2\">\n        {operations.map((item) => (\n          <button\n            key={item.value}\n            type=\"button\"\n            onClick={() => setOperation(item.value)}\n            className={cn(\n              \"rounded-md border px-3 py-1.5 text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring\",\n              operation === item.value\n                ? \"bg-primary text-primary-foreground shadow\"\n                : \"hover:bg-accent hover:text-accent-foreground\"\n            )}\n          >\n            {item.label}\n          </button>\n        ))}\n      </div>\n\n      <div className=\"mt-6 space-y-2\">\n        <label className=\"text-sm font-medium leading-none\">Values</label>\n        <input\n          value={input}\n          onChange={(event) => setInput(event.target.value)}\n          placeholder=\"100, 200, 300\"\n          className=\"flex h-9 w-full rounded-md border border-input bg-transparent px-3 py-1 text-sm shadow-sm transition-colors file:border-0 file:bg-transparent file:text-sm file:font-medium placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring\"\n        />\n        <p className=\"text-xs text-muted-foreground\">\n          Enter numbers separated by commas.\n        </p>\n      </div>\n\n      <div className=\"mt-6 rounded-lg bg-muted/50 p-5 border\">\n        <p className=\"text-sm font-medium text-muted-foreground\">\n          {operations.find((item) => item.value === operation)?.label}\n        </p>\n        <p className=\"mt-1 text-3xl font-bold tracking-tight\">\n          {formattedResult}\n        </p>\n      </div>\n    </div>\n  )\n}",
      "type": "registry:ui"
    }
  ]
}