{"version":3,"file":"Calculator-CUPqFn-I.cjs","sources":["../lib/calculator.ts","../app/components/calculator/Calculator.tsx"],"sourcesContent":["export type OperatorSymbol = \"+\" | \"-\" | \"*\" | \"/\";\n\nexport function performOperation(\n  a: number,\n  b: number,\n  operator: OperatorSymbol\n): number {\n  switch (operator) {\n    case \"+\":\n      return a + b;\n    case \"-\":\n      return a - b;\n    case \"*\":\n      return a * b;\n    case \"/\":\n      return b === 0 ? NaN : a / b;\n  }\n}\n\nexport type CalculatorState = {\n  displayValue: string;\n  firstOperand: number | null;\n  waitingForSecondOperand: boolean;\n  operator: OperatorSymbol | null;\n};\n\nexport const initialCalculatorState: CalculatorState = {\n  displayValue: \"0\",\n  firstOperand: null,\n  waitingForSecondOperand: false,\n  operator: null,\n};\n\nexport function inputDigit(\n  state: CalculatorState,\n  digit: string\n): CalculatorState {\n  if (state.waitingForSecondOperand) {\n    return { ...state, displayValue: digit, waitingForSecondOperand: false };\n  }\n  return {\n    ...state,\n    displayValue:\n      state.displayValue === \"0\" ? digit : state.displayValue + digit,\n  };\n}\n\nexport function inputDecimal(state: CalculatorState): CalculatorState {\n  if (state.waitingForSecondOperand) {\n    return { ...state, displayValue: \"0.\", waitingForSecondOperand: false };\n  }\n  if (state.displayValue.includes(\".\")) return state;\n  return { ...state, displayValue: state.displayValue + \".\" };\n}\n\nexport function clearAll(): CalculatorState {\n  return { ...initialCalculatorState };\n}\n\nexport function applyOperator(\n  state: CalculatorState,\n  nextOperator: OperatorSymbol\n): CalculatorState {\n  const inputValue = parseFloat(state.displayValue);\n  if (Number.isNaN(inputValue)) return state;\n\n  if (state.operator && state.waitingForSecondOperand) {\n    return { ...state, operator: nextOperator };\n  }\n\n  if (state.firstOperand === null) {\n    return {\n      ...state,\n      firstOperand: inputValue,\n      waitingForSecondOperand: true,\n      operator: nextOperator,\n    };\n  }\n\n  if (state.operator) {\n    const result = performOperation(\n      state.firstOperand,\n      inputValue,\n      state.operator\n    );\n    return {\n      ...state,\n      displayValue: String(result),\n      firstOperand: result,\n      waitingForSecondOperand: true,\n      operator: nextOperator,\n    };\n  }\n\n  return { ...state, waitingForSecondOperand: true, operator: nextOperator };\n}\n\nexport function equals(state: CalculatorState): CalculatorState {\n  if (\n    state.operator === null ||\n    state.waitingForSecondOperand ||\n    state.firstOperand === null\n  ) {\n    return state;\n  }\n  const inputValue = parseFloat(state.displayValue);\n  const result = performOperation(\n    state.firstOperand,\n    inputValue,\n    state.operator\n  );\n  return {\n    ...state,\n    displayValue: String(result),\n    firstOperand: result,\n    operator: null,\n    waitingForSecondOperand: true,\n  };\n}\n","\"use client\";\n\nimport { useState, useCallback } from \"react\";\nimport {\n  initialCalculatorState,\n  inputDigit as logicInputDigit,\n  inputDecimal as logicInputDecimal,\n  clearAll as logicClearAll,\n  applyOperator as logicApplyOperator,\n  equals as logicEquals,\n  type OperatorSymbol,\n  type CalculatorState,\n} from \"@/lib/calculator\";\n\nexport default function Calculator() {\n  const [state, setState] = useState<CalculatorState>(initialCalculatorState);\n\n  const inputDigit = useCallback((digit: string) => {\n    setState((s) => logicInputDigit(s, digit));\n  }, []);\n\n  const inputDecimal = useCallback(() => {\n    setState((s) => logicInputDecimal(s));\n  }, []);\n\n  const clearAll = useCallback(() => {\n    setState(() => logicClearAll());\n  }, []);\n\n  const handleOperator = useCallback((nextOperator: OperatorSymbol) => {\n    setState((s) => logicApplyOperator(s, nextOperator));\n  }, []);\n\n  const handleEquals = useCallback(() => {\n    setState((s) => logicEquals(s));\n  }, []);\n\n  const toggleSign = useCallback(() => {\n    setState((s) => {\n      const dv = s.displayValue;\n      if (dv === \"0\") return s;\n      return {\n        ...s,\n        displayValue: dv.startsWith(\"-\") ? dv.slice(1) : `-${dv}`,\n      };\n    });\n  }, []);\n\n  const applyPercent = useCallback(() => {\n    setState((s) => {\n      const v = parseFloat(s.displayValue);\n      if (Number.isNaN(v)) return s;\n      return { ...s, displayValue: String(v / 100) };\n    });\n  }, []);\n\n  const handleKeyDown = useCallback(\n    (e: React.KeyboardEvent<HTMLDivElement>) => {\n      const { key } = e;\n      if (key >= \"0\" && key <= \"9\") {\n        e.preventDefault();\n        inputDigit(key);\n        return;\n      }\n      if (key === \".\") {\n        e.preventDefault();\n        inputDecimal();\n        return;\n      }\n      if (key === \"+\" || key === \"-\" || key === \"*\" || key === \"/\") {\n        e.preventDefault();\n        handleOperator(key as OperatorSymbol);\n        return;\n      }\n      if (key === \"Enter\" || key === \"=\") {\n        e.preventDefault();\n        handleEquals();\n        return;\n      }\n      if (key === \"Escape\" || key.toLowerCase() === \"c\") {\n        e.preventDefault();\n        clearAll();\n      }\n    },\n    [inputDigit, inputDecimal, handleOperator, handleEquals, clearAll]\n  );\n\n  return (\n    <div\n      className=\"w-full max-w-[320px] rounded-lg border border-border p-4 shadow-sm bg-card text-foreground\"\n      role=\"application\"\n      aria-label=\"Calculator\"\n      onKeyDown={handleKeyDown}\n      tabIndex={0}\n    >\n      <div\n        role=\"status\"\n        aria-live=\"polite\"\n        aria-atomic=\"true\"\n        className=\"w-full h-14 rounded-md border border-border flex items-center justify-end px-3 text-2xl font-mono bg-white/70 dark:bg-black/30 overflow-hidden\"\n      >\n        {state.displayValue}\n      </div>\n      <div className=\"mt-3 grid grid-cols-4 gap-2\">\n        <button\n          className=\"col-span-1 h-12 rounded-md bg-calc-func text-calc-func-foreground hover:opacity-90 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-accent\"\n          onClick={clearAll}\n          aria-label=\"Clear all\"\n        >\n          C\n        </button>\n        <button\n          className=\"col-span-1 h-12 rounded-md bg-calc-func text-calc-func-foreground hover:opacity-90 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-accent\"\n          onClick={toggleSign}\n          aria-label=\"Toggle sign\"\n        >\n          ±\n        </button>\n        <button\n          className=\"col-span-1 h-12 rounded-md bg-calc-func text-calc-func-foreground hover:opacity-90 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-accent\"\n          onClick={applyPercent}\n          aria-label=\"Percent\"\n        >\n          %\n        </button>\n        <button\n          className=\"col-span-1 h-12 rounded-md bg-calc-operator text-calc-operator-foreground hover:opacity-90 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-accent\"\n          onClick={() => handleOperator(\"/\" as OperatorSymbol)}\n          aria-label=\"Divide\"\n        >\n          ÷\n        </button>\n\n        {[\"7\", \"8\", \"9\"].map((d) => (\n          <button\n            key={d}\n            className=\"h-12 rounded-md bg-calc-key hover:opacity-90 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-accent\"\n            onClick={() => inputDigit(d)}\n            aria-label={`Digit ${d}`}\n          >\n            {d}\n          </button>\n        ))}\n        <button\n          className=\"h-12 rounded-md bg-calc-operator text-calc-operator-foreground hover:opacity-90 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-accent\"\n          onClick={() => handleOperator(\"*\" as OperatorSymbol)}\n          aria-label=\"Multiply\"\n        >\n          ×\n        </button>\n\n        {[\"4\", \"5\", \"6\"].map((d) => (\n          <button\n            key={d}\n            className=\"h-12 rounded-md bg-calc-key hover:opacity-90 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-accent\"\n            onClick={() => inputDigit(d)}\n            aria-label={`Digit ${d}`}\n          >\n            {d}\n          </button>\n        ))}\n        <button\n          className=\"h-12 rounded-md bg-calc-operator text-calc-operator-foreground hover:opacity-90 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-accent\"\n          onClick={() => handleOperator(\"-\" as OperatorSymbol)}\n          aria-label=\"Subtract\"\n        >\n          −\n        </button>\n\n        {[\"1\", \"2\", \"3\"].map((d) => (\n          <button\n            key={d}\n            className=\"h-12 rounded-md bg-calc-key hover:opacity-90 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-accent\"\n            onClick={() => inputDigit(d)}\n            aria-label={`Digit ${d}`}\n          >\n            {d}\n          </button>\n        ))}\n        <button\n          className=\"h-12 rounded-md bg-calc-operator text-calc-operator-foreground hover:opacity-90 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-accent\"\n          onClick={() => handleOperator(\"+\" as OperatorSymbol)}\n          aria-label=\"Add\"\n        >\n          +\n        </button>\n\n        <button\n          className=\"col-span-2 h-12 rounded-md bg-calc-key hover:opacity-90 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-accent\"\n          onClick={() => inputDigit(\"0\")}\n          aria-label=\"Digit 0\"\n        >\n          0\n        </button>\n        <button\n          className=\"h-12 rounded-md bg-calc-key hover:opacity-90 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-accent\"\n          onClick={inputDecimal}\n          aria-label=\"Decimal\"\n        >\n          .\n        </button>\n        <button\n          className=\"h-12 rounded-md bg-calc-operator text-calc-operator-foreground hover:opacity-90 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-accent\"\n          onClick={handleEquals}\n          aria-label=\"Equals\"\n        >\n          =\n        </button>\n      </div>\n    </div>\n  );\n}\n"],"names":["performOperation","a","b","operator","initialCalculatorState","inputDigit","state","digit","inputDecimal","clearAll","applyOperator","nextOperator","inputValue","result","equals","Calculator","setState","useState","useCallback","s","logicInputDigit","logicInputDecimal","logicClearAll","handleOperator","logicApplyOperator","handleEquals","logicEquals","toggleSign","dv","applyPercent","v","handleKeyDown","e","key","jsxs","jsx","d"],"mappings":"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"}