Basic operations
Let us first compute the results of basic operations using eval, that is +, -, /, %, × and ÷.
Another thing, we will need to decouple result props from the variable rendered in AppScreen because at some point we will have to change the value, and child components cannot mutate prop bindings.

We will trigger eval using an emitter evalOps from the AppButtons component. Let us modify the buttonAction function to account for this:
// ...
const emit = defineEmits(['basicOps', 'evalOps'])
// ...
} else if (symbol == '='){
  emit('evalOps')
}
//...
In App.vue, we'll add a listener to the emitter that calls a function calculateScreen
<app-buttons
  @basic-ops="(n: string) => updateScreen(n)"
  @eval-ops="calculateScreen"
></app-buttons>
In calculateScreen, we'll check if result is defined, then replace × with * and ÷ with /. That's because, for display, we need × and ÷, but for eval, we need * and /, else eval will give an error.
Finally, we compute the result using eval and then assign it back as string, because the variable result is of type string.
const calculateScreen = () => {
  if (result.value) {
    const chars: Record<string, string> = { '×': '*', '÷': '/' }
    let temp = result.value.replace(/[×÷]/g, (m: string) => chars[m])
    result.value = `${eval(temp)}`
  }
}
Let us refine on something, if the result is immediately evaluated, then typing a digit will replace the result, else typing a basic operator will continue on as normal, so let's account for that in code.
// ...
if (/^\d+$/.test(_in)){ // check if digit
  result.value = _in
} else result.value += _in
// ...
We will introduce a boolean variable, immediate, as a flag to solve for this:
~ If the result is undefined, then it does not matter the state of immediate, we assign the result.
~ Result being defined, if immediate is true, call the above code snippet, otherwise, it is updated.
const updateScreen = (_in: string) => {
  if (result.value) {
    if (immediate.value) {
      // above snippet
      if (/^\d+$/.test(_in)){
        result.value = _in
      } else result.value += _in
      // end above snippet
    }
    else
      result.value += _in
  }
  else result.value = _in
  immediate.value = false
}
Advanced operations
Great! Now let's work on computing advanced operations such as sin, cos, tan, log, etc. First of all, we'll update the object that maps display values to compute values. We've given it a very unconventional name, chars. We can work with that, unless you want to change, by which you can.

Updates done
// src/components/AppButtons.vue
// add π and e in regex pattern matching
const basicMatch = /[+\-/()÷%×πe\d]/g
if (basicMatch.test(symbol)) {
   emit('basicOps', symbol)
}
/* add sqrt in "(" conditional 
in buttonAction function
*/
} else if (
    ['tan', 'cos', 'log', 'sin', 'ln', '√'].includes(symbol)
    ) {
In calculateScreen function, we not only replace x and ÷ now, but we do so for the advanced operators too
Let's expand the object for mapping.
const chars: Record<string, string> = { 
  '×': '*', 
  '÷': '/',
  'sin': 'Math.sin',
  'cos': 'Math.cos',
  'tan': 'Math.tan',
  'ln' : 'Math.log',
  'log': 'Math.log10',
  'π' : 'Math.PI',
  'e' : 'Math.exp(1)',
  '√' : 'Math.sqrt'
}
We create a regex dynamically using the "display" operators that will match all the available operators in the result variable
const pattern = new RegExp(Object.keys(chars).join('|'), 'ig')
We then match and replace the "display" operators to "compute" operators using the regex created dynamically
let temp = result.value.replace(pattern, (m: string) => chars[m])
The complete code for the calculateScreen is as below:
const calculateScreen = () => {
  if (result.value) {
    const chars: Record<string, string> = { 
      '×': '*', 
      '÷': '/',
      'sin': 'Math.sin',
      'cos': 'Math.cos',
      'tan': 'Math.tan',
      'ln' : 'Math.log',
      'log': 'Math.log10',
      'π' : 'Math.PI',
      'e' : 'Math.exp(1)',
      '√' : 'Math.sqrt'
    }
    const pattern = new RegExp(Object.keys(chars).join('|'), 'ig');
    let temp = result.value.replace(pattern, (m: string) => chars[m])
    result.value = `${eval(temp)}`    
    immediate.value = true
  }
}
Fixing a caveat
Note: Don't worry, we'll clear the screen soon enough! Let's just fix this caveat.
If you have a digit and an advanced operator, eval won't implicitly translate that as having a multiplier between the two, so we'll have to fix that ourselves. And that's what this part is all about.

Since we will need the array of symbols in App.vue for this, we'll move that reactive variable to a global scope, hence introducing the concept of composables

In the context of Vue applications, a "composable" is a function that leverages Vue's Composition API to encapsulate and reuse stateful logic.

Let's create a file, symbols.ts in the src folder, then create a function, useSymbols that returns us the reactive data.
import { reactive } from 'vue'

const buttons = reactive([
    'Rad', 'Deg', 'x!', '(', ')',
    '%', 'AC', 'Inv', 'sin', 'ln',
    '7', '8', '9', '÷', 'π', 
    'cos', 'log', '4', '5', '6', 
    '×', 'e', 'tan', '√', '1', 
    '2', '3', '-', 'Ans', 'EXP',
    'x<sup>y</sup>', '0', '.', '=', '+'])

export function useSymbols() {
    return buttons
}
Now, in our script setup, we can import buttons to our AppButtons component as follows
import { useSymbols } from '@/symbols'
const buttons = useSymbols()
Let's also import it in App.vue since it will be important in solving the above caveat.
In a function newly created to add a multiplier where necessary, we first break the result into its constituents. We will use regex (again!) for this.
First of all, we take all our elements and create a regex that will match all our symbols within our result value then we get its constituents.
Note: There are some characters that need to be escaped first while constructing a valid regex. The lambda function in map does exactly this.
const escaped = buttons.map(s => s.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')).join('|')
const allMatch = new RegExp(`(${escaped})`, 'g')
Now, let's introduce two assumptions, that,
1 ~ a multiplier only needs be added before advanced operators, not after
2 ~ only operators not affected by not there being a multiplier are +, -, *, /, and %

From these assumptions, we can safely say that we can check for the symbol just before these operators, and if the symbol is not part of the five basic operators, we add a multiplier.

Another regex comes into play!
const nonAdvancedMatch = /[+\-\./÷%×()\d]/g
The above regex helps us extract all non-advanced operators from our topic of interest.
By doing a subtraction operation of basic matches from all matches. We remain with only advanced operators.
// input_check is result value before replace 
// display with compute operators
// all matches
const all = input_check.match(allMatch)
// basics matches
const basics = input_check.match(nonAdvancedMatch)
// advanced matches
const subtraction = all?.filter(x => !basics?.includes(x))
Finally, with all the advanced matches, we can check for the value immediately before it and if not part of the five symbols in the assumptions, we add the multiplier. We see into consideration the fact that when a multiplier is added, we change the offset of index of the matches as we mutate the result to account for the new change.

The whole function for adding multiplier where necessary is as below:
const addMultiplier = (inputCheck: string): string => {
  const escaped = buttons.map(
    (s) => s.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')
    ).join('|')
  const allMatch = new RegExp(`(${escaped})`, 'g')
  const nonAdvancedMatch = /[+\-\./÷%×()\d]/g
  const fiveSymbolsMatch = /[+\-\./÷%×]/g

  const all = inputCheck.match(allMatch)
  const basics = inputCheck.match(nonAdvancedMatch)
  const subtraction = all?.filter((x) => !basics?.includes(x))
  // get all indeces, function definition in next snippet
  // @ts-ignore
  let indeces = subtraction?.flatMap((e) => getAllIndeces(inputCheck, e))
  indeces = [...new Set(indeces)] // remove duplicates

  let offset = 0
  indeces?.forEach((start: number) => {
    start = start + offset
    let immediatelyBefore = inputCheck.slice(start - 1, start)
    // the first part of the conditional is to avoid changing
    // advanced operators that start in the result value
    if (immediatelyBefore !== '' && !fiveSymbolsMatch.test(immediatelyBefore)) {
      inputCheck = inputCheck.slice(0, start) + '×' + inputCheck.slice(start)
      offset += 1
    }
  })
  return inputCheck
}
// gets indeces even for repeating advanced operators
// e.g. 8cos(6)cos(4) will not work without this functionality
const getAllIndeces = (str: string, subStr: string) => {
  var indices = []
  var index = -1
  while ((index = str.indexOf(subStr, index + 1)) !== -1) {
    indices.push(index)
  }
  return indices
}
Now, calling the addMultiplier in our calculateScreen, the codebase is modified as below:
// ...
const pattern = new RegExp(Object.keys(chars).join('|'), 'ig')
let temp = addMultiplier(result.value)
temp = temp.replace(pattern, (m: string) => chars[m])    
result.value = `${eval(temp)}`
// ...
Clearing screen
Let's do a basic screen clearing for now, in the next lesson, we'll do the advanced screen clearing.
Adding another emitter for screen clearing, at the beginning of script setup, we modify defineEmits to have clearOps.
In the buttonAction, we add one more conditionality...
// ...
const emit = defineEmits(['basicOps', 'evalOps', 'clearOps'])
// ...
} else if (symbol == "AC"){
  emit("clearOps")
}
// ...
In App.vue, we listen for the event, then we call a function, clearScreen, to set result to undefined.
<script setup lang="ts">
/*...*/
const clearScreen = () => {
  result.value = undefined
}
</script>
<template>
<!-- ... -->
<app-buttons
  @basic-ops="(n: string) => updateScreen(n)"
  @eval-ops="calculateScreen"
  @clearOps="clearScreen"
></app-buttons>
<!-- ... -->
In the next lesson...
Let's now head over to advanced clearing where we clear decrementally instead of everything at once. And, let's also work on superscript, or as mathematically known, powers