diff --git a/dist/css/app.daed5fa9.css b/dist/css/app.daed5fa9.css
deleted file mode 100644
index 3747768..0000000
--- a/dist/css/app.daed5fa9.css
+++ /dev/null
@@ -1 +0,0 @@
-.inputs{opacity:0;height:20px}brack,unexpected{color:red}.depth0{color:orange}.depth1{color:#ff0}.depth2{color:green}op{color:#df6874}func{color:#779de9}comm{color:#535353}comm space,space{width:10px;color:transparent}.answer{cursor:pointer;transition:all .2s}.answer:hover{scale:1.2}.answer:active{scale:1.05}crs{background:none;width:0;margin:0;padding:0}.lastSpace{margin-left:12px}sup{color:inherit}button{border:none}#settings{position:fixed;padding:10px;border-radius:20px;border:2px solid #df6874;transition:all .4s}#settings input,#settings table,#settings td,#settings tr{border:none}#settings input:focus{border:none;outline:none}.closed{right:-100vw}.closed,.open{top:20px;bottom:20px}.open{right:20px}#settingsButton{border:none;position:fixed;top:30px;right:30px;z-index:5;transition:all .4s}.openButton{rotate:1turn}.closedButton{rotate:0deg}#cursor{height:23px;width:2px;position:fixed;transition:all .1s}.cursor{border-radius:1px;background-color:#fff}.selection{border-radius:5px;background-color:rgba(0,145,255,.409)}*{color:#fff;font-optical-sizing:auto;font-weight:500;font-style:normal;font-variation-settings:"wdth" 100;font-size:20px}#app,*{background-color:#0c1118;font-family:Inconsolata,monospace}#app{font-optical-sizing:auto;font-weight:200;font-style:normal;font-variation-settings:"wdth" 100;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;color:#2c3e50;margin-top:60px}
\ No newline at end of file
diff --git a/dist/css/app.f6d0b9de.css b/dist/css/app.f6d0b9de.css
new file mode 100644
index 0000000..0115b2c
--- /dev/null
+++ b/dist/css/app.f6d0b9de.css
@@ -0,0 +1 @@
+.inputs{opacity:0;width:0;height:0}.calcRow{height:20px;vertical-align:top}.dispRow{min-width:180px}brack,unexpected{color:red}.depth0{color:orange}.depth1{color:#ff0}.depth2{color:green}op{color:#df6874}func{color:#779de9}comm{color:#535353}comm space,space{width:10px;color:transparent}.answer{cursor:pointer;transition:all .2s;height:20px;overflow:scroll}.answer:hover{scale:1.2}.answer:active{scale:1.05}crs{background:none;width:0;margin:0;padding:0}.lastSpace{margin-left:12px}sup{color:inherit}button{border:none}#settings{position:fixed;padding:10px;border-radius:20px;border:2px solid #df6874;transition:all .4s}#settings input,#settings table,#settings td,#settings tr{border:none}#settings input:focus{border:none;outline:none}.closed{right:-100vw}.closed,.open{top:20px;bottom:20px}.open{right:20px}#settingsButton{border:none;position:fixed;top:30px;right:30px;z-index:5;transition:all .4s}.openButton{rotate:1turn}.closedButton{rotate:0deg}#cursor{height:23px;width:2px;position:fixed;transition:all .1s}.cursor{border-radius:1px;background-color:#fff}.selection{border-radius:5px;background-color:rgba(0,145,255,.409)}*{color:#fff;font-optical-sizing:auto;font-weight:500;font-style:normal;font-variation-settings:"wdth" 100;font-size:20px}#app,*{background-color:#0c1118;font-family:Inconsolata,monospace}#app{font-optical-sizing:auto;font-weight:200;font-style:normal;font-variation-settings:"wdth" 100;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;color:#2c3e50;margin-top:60px}
\ No newline at end of file
diff --git a/dist/index.html b/dist/index.html
index bceb8bf..affa262 100644
--- a/dist/index.html
+++ b/dist/index.html
@@ -1 +1 @@
-
Calc
\ No newline at end of file
+Calc
\ No newline at end of file
diff --git a/dist/js/app.8e5a5583.js b/dist/js/app.8e5a5583.js
new file mode 100644
index 0000000..97f20ab
--- /dev/null
+++ b/dist/js/app.8e5a5583.js
@@ -0,0 +1,2 @@
+(function(){var e={7472:function(e,t,n){"use strict";var o=n(5130),r=n(6768);function l(e,t,n,o,l,i){const s=(0,r.g2)("CalcSettings"),u=(0,r.g2)("CalcTable"),c=(0,r.g2)("TransitionCursor");return(0,r.uX)(),(0,r.CE)(r.FK,null,[(0,r.bF)(s),(0,r.bF)(u),(0,r.bF)(c)],64)}var i=n(144),s=n(4232),u=(n(4114),n(8490)),c=n(3229),a=256,d="rad";const g={number:"BigNumber",precision:a,angles:d},f=(0,u.v)(c.Q,g);function p(e){return e.replaceAll("pi","π")}function h(e,t){return null==t&&(t="1"),e.replaceAll("ans",`(${t})`)}function w(e){let t="";for(var n=0;n{r.push(e[0])}));let l=b(e,r,!0),i=/[a-zA-Z]/g;if(i.test(l))return"Syntax error, undefined letters";console.log(n);while(n.includes("("))n=y(n);n=n.replaceAll("[","("),n=n.replaceAll("]",")"),n=w(n),d=document.getElementById("angleInput").innerText;let s=[[/sin\((.*?)\)/g,`sin($1 ${d})`],[/cos\((.*?)\)/g,`cos($1 ${d})`],[/tan\((.*?)\)/g,`tan($1 ${d}`],[/cot\((.*?)\)/g,`cot($1 ${d})`],[/sec\((.*?)\)/g,`sec($1 ${d})`],[/csc\((.*?)\)/g,`csc($1 ${d})`]];for(let c=0;cn)return[!0,"Syntax error, close powers using ;"];if(tt[0].length-e[0].length)));for(let[o,r]of n)e=e.replaceAll(o,`(${r})`);return e}class A{constructor(e,t){this.equation=null!==e?e:"",this.dispEquation=q(this.equation),this.answer=0,this.index=t}calculate(){let e;O&&(e=O.getRow(this.index-1));const t=e?e.getAnswer():0;this.equation=p(this.equation),this.answer=m(h(this.equation,t),this.index),this.dispEquation=q(this.equation,this.index)}setEquation(e){this.equation=e,O.calculateAllRows()}setIndex(e){this.index=e}getEquation(){return this.equation}getDispEquation(){return q(this.equation,this.index)}getAnswer(){return this.answer}getIndex(){return this.index}}function C(e){let t=0,n="",o=[],r={"{":"}","(":")","[":"]"};for(let l=0;l${e[l]}`;else if(")}]".includes(e[l])){t--;let i=e[l]==r[o.pop()]?t:-1;n+=`${e[l]}`}else n+=e[l];return n}function q(e,t){if(""==e)return"type equation here";let n=!1;if("//"==e.substring(0,2)&&(n=!0),O){let n=document.getElementById("row"+O.getFocusRowIndex());if(n&&t===O.getFocusRowIndex()){var o=n.selectionStart,r=n.selectionEnd;e=$(e,o,r)}}if(e=B(e),e=e.replaceAll(" ","_"),n)return`${e}`;let l=[["+"," + "],["-"," - "],["*"," × "],["="," = "],["sin(","sin("],["cos(","cos("],["tan(","tan("],["log(","log("],["ln(","ln("],["cosec(","cosec("],["sec(","sec("],["csc(","csc("],["cot(","cot("],["pow(","pow("],["abs(","abs("]];for(let i=0;i"):";"==e[r]?(n++,n>t?(o+=";",n=0,t=0):o+=""):o+=e[r];return o}function $(e,t,n){return e=t==n?e.substring(0,t)+""+e.substring(t,e.length):e.substring(0,t)+""+e.substring(t,n)+""+e.substring(n,e.length),e}class S{constructor(){if(R)throw new Error("RowManager is already initialized");this.rows=(0,i.KR)([new A("",0)]),this.focusRowIndex=(0,i.KR)(0),R=this}getRows(){return this.rows.value}getRow(e){return this.rows.value[e]}setRow(e,t){this.rows.value[e]=t}addRowAt(e){if(""==this.getRow(e).getEquation())return;let t=this.getRow(e).getEquation(),n=document.getElementById(`row${e}`),o=n.selectionStart,r=n.selectionEnd,l=[t.substring(0,o),t.substring(r,t.length)];this.setRow(e,new A(l[0],e)),this.focusRowIndex.value=e+1;let i=this.rows.value;this.rows.value=null,setTimeout((()=>{this.rows.value=i,this.rows.value.splice(e+1,0,new A(l[1],e+1));for(let e=0;e{this.rows.value=i,this.rows.value.splice(e,1);for(let e=0;e{document.getElementById(`row${this.focusRowIndex.value}`).setSelectionRange(l,l),this.calculateAllRows()}),1)}}calculateAllRows(){setTimeout((()=>{if(this.rows.value){this.rows.value.forEach((e=>e.calculate()));for(let e=0;e=0){this.focusRowIndex.value=n;let e=document.getElementById(`row${t}`).selectionStart,o=document.getElementById(`row${this.focusRowIndex.value}`);o.focus(),requestAnimationFrame((()=>{o.setSelectionRange(e,e),this.calculateAllRows()}))}}updateSmoothCursorPosition(){let e=document.getElementById("cursor"),t=document.getElementsByTagName("crs")[0];if(null==e||null==t)return void requestAnimationFrame(j);if("inputs"!==document.activeElement.className)return e.style.opacity=0,void requestAnimationFrame(j);let n=document.getElementsByTagName("crs")[1];if(null!=n){e.className="selection";let o=t.getBoundingClientRect(),r=n.getBoundingClientRect(),l=Math.abs(o.left-r.left);e.style.width=l+"px"}else e.className="cursor",e.style.width="2px";let o=t.getBoundingClientRect();e.style.top=o.top+"px",e.style.left=o.left+"px",e.style.opacity=1,requestAnimationFrame(j)}}const L=Object.freeze(new S);function T(e){"Enter"!==e.key&&"38"!=e.keyCode&&"40"!=e.keyCode&&L.calculateAllRows()}function F(e){e=e||window.event,"38"==e.keyCode?L.adjustFocusRowIndex(-1):"40"==e.keyCode&&L.adjustFocusRowIndex(1)}function j(){L.updateSmoothCursorPosition()}L.updateSmoothCursorPosition(),document.onkeydown=F,document.addEventListener("keyup",T),document.addEventListener("keydown",T),document.addEventListener("click",T);var O=L;const M=["id"],_={class:"calcRow"},K=["id","innerHTML"],N=["id","innerHTML"];var P={__name:"CalcRow",props:{index:{type:Number,required:!0}},setup(e){const t=e;var n=!1;const l=(0,i.KR)();function u(){O.getRow(t.index).setEquation(l.value),l.value=O.getRow(t.index).getEquation()}function c(){O.addRowAt(t.index)}function a(){O.removeRowAt(t.index)}function d(){n&&(document.getElementById(`row${t.index}`).focus(),O.setFocusRowIndex(t.index))}function g(e){return"//"==O.getRow(e).getEquation().substring(0,2)?"":" = "}function f(){navigator.clipboard.writeText(O.getRow(t.index).getAnswer())}return(0,r.sV)((()=>{l.value=O.getRow(t.index).getEquation(),t.index==O.focusRowIndex.value&&document.getElementById(`row${t.index}`).focus(),n=!0,O.updateSmoothCursorPosition()})),d(),(e,n)=>((0,r.uX)(),(0,r.CE)(r.FK,null,[(0,r.Lk)("tr",null,[(0,r.Lk)("td",null,[(0,r.bo)((0,r.Lk)("input",{class:"inputs",id:"row"+t.index,type:"text","onUpdate:modelValue":n[0]||(n[0]=e=>l.value=e),onInput:u,onKeyup:[(0,o.jR)(c,["enter"]),(0,o.jR)(a,["backspace"])],onKeypress:(0,o.jR)(a,["backspace"]),onKeydown:(0,o.jR)(a,["backspace"])},null,40,M),[[o.Jo,l.value]])])]),(0,r.Lk)("tr",_,[(0,r.Lk)("td",{onClick:d,class:"dispRow",id:"dispRow"+t.index,innerHTML:(0,i.R1)(O).getRow(t.index).getDispEquation()},null,8,K),(0,r.Lk)("td",{id:"equal"+t.index,innerHTML:g(t.index)},null,8,N),(0,r.Lk)("td",{onClick:f,class:"answer"},(0,s.v_)((0,i.R1)(O).getRow(t.index).getAnswer()),1)])],64))}};const X=P;var U=X;const H={id:"calcTable",ref:"calcTable"};var V={__name:"CalcTable",setup(e){return(e,t)=>((0,r.uX)(),(0,r.CE)("table",H,[((0,r.uX)(!0),(0,r.CE)(r.FK,null,(0,r.pI)((0,i.R1)(O).getRows(),(e=>((0,r.uX)(),(0,r.Wv)(U,{key:e.getIndex(),index:e.getIndex()},null,8,["index"])))),128))],512))}};const z=V;var D=z;const J=(0,r.Lk)("i",{class:"fa-solid fa-gear"},null,-1),Q=[J],W=(0,r.Lk)("tr",null,[(0,r.Lk)("td",null,"Precision: "),(0,r.Lk)("td",null,[(0,r.Lk)("input",{id:"precisionInput",type:"number"})])],-1),Z=(0,r.Lk)("td",null,"Angle Mode: ",-1);var G={__name:"CalcSettings",setup(e){var t=!0;function n(){t=!t,document.getElementById("settings").className=t?"open":"closed",document.getElementById("settingsButton").className=t?"openButton":"closedButton"}function o(){let e=["rad","deg","grad"],t=document.getElementById("angleInput"),n=e.indexOf(t.innerText)+1;n=n>2?0:n,t.innerText=e[n]}return(0,r.sV)((()=>{document.getElementById("precisionInput").value=10,document.getElementById("angleInput").value="rad"})),(e,t)=>((0,r.uX)(),(0,r.CE)(r.FK,null,[(0,r.Lk)("button",{id:"settingsButton",onClick:n},Q),(0,r.Lk)("div",{id:"settings",class:"closed"},[(0,r.Lk)("table",null,[W,(0,r.Lk)("tr",null,[Z,(0,r.Lk)("td",null,[(0,r.Lk)("button",{id:"angleInput",type:"text",onClick:o},"rad")])])])])],64))}};const Y=G;var ee=Y;const te={id:"cursor"};function ne(e,t){return(0,r.uX)(),(0,r.CE)("div",te)}var oe=n(1241);const re={},le=(0,oe.A)(re,[["render",ne]]);var ie=le,se={name:"App",components:{CalcTable:D,CalcSettings:ee,TransitionCursor:ie}};const ue=(0,oe.A)(se,[["render",l]]);var ce=ue;(0,o.Ef)(ce).mount("#app")},1234:function(){}},t={};function n(o){var r=t[o];if(void 0!==r)return r.exports;var l=t[o]={id:o,loaded:!1,exports:{}};return e[o].call(l.exports,l,l.exports,n),l.loaded=!0,l.exports}n.m=e,function(){n.amdD=function(){throw new Error("define cannot be used indirect")}}(),function(){n.amdO={}}(),function(){var e=[];n.O=function(t,o,r,l){if(!o){var i=1/0;for(a=0;a=l)&&Object.keys(n.O).every((function(e){return n.O[e](o[u])}))?o.splice(u--,1):(s=!1,l0&&e[a-1][2]>l;a--)e[a]=e[a-1];e[a]=[o,r,l]}}(),function(){n.n=function(e){var t=e&&e.__esModule?function(){return e["default"]}:function(){return e};return n.d(t,{a:t}),t}}(),function(){n.d=function(e,t){for(var o in t)n.o(t,o)&&!n.o(e,o)&&Object.defineProperty(e,o,{enumerable:!0,get:t[o]})}}(),function(){n.g=function(){if("object"===typeof globalThis)return globalThis;try{return this||new Function("return this")()}catch(e){if("object"===typeof window)return window}}()}(),function(){n.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)}}(),function(){n.r=function(e){"undefined"!==typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})}}(),function(){n.nmd=function(e){return e.paths=[],e.children||(e.children=[]),e}}(),function(){var e={524:0};n.O.j=function(t){return 0===e[t]};var t=function(t,o){var r,l,i=o[0],s=o[1],u=o[2],c=0;if(i.some((function(t){return 0!==e[t]}))){for(r in s)n.o(s,r)&&(n.m[r]=s[r]);if(u)var a=u(n)}for(t&&t(o);c\n\n\n\n\n\n\n\n\n\n\n","// library to be used for calculations\nimport { create, all } from 'mathjs'\n\n\n// the precision of the calculations, this is then rounded using the number that is inputted by the user in settings.\nvar prec = 256;\n\n// the unit of angles, can be changed to deg or grad in settings\nvar angleUnit = 'rad';\n\n// configure the default type of numbers as BigNumbers\nconst config = {\n // Default type of number\n // Available options: 'number' (default), 'BigNumber', or 'Fraction'\n number: 'BigNumber',\n\n // Number of significant digits for BigNumbers\n precision: prec,\n angles: angleUnit\n}\n\n// set up the library\nconst math = create(all, config);\n\n\n// used externally to replace pi with the symbol pi when the equation is displayed\nexport function replaceSpecialCharacters(e) {\n return e.replaceAll(\"pi\", \"π\");\n}\n\n// used externally to replace when the user types \"ans\", with the previous answer.\nexport function replaceAns(e, prev) {\n if (prev == null) prev = \"1\";\n return e.replaceAll(\"ans\", `(${prev})`); \n}\n\n// makes sure that brackets are dealt with properly, for example, two brackets next to each other should be multiplied by each other.\n// or other example, a number then a bracket should multiply together. \nfunction surroundFunction(e) {\n let q = \"\";\n for (var i = 0; i < e.length; i++) {\n q += e[i];\n \n if (/^\\d+$/.test(e[i]) && e[i + 1] == \"(\") {\n q += \"*\";\n }\n\n if (e[i] == \")\" && /^\\d+$/.test(e[i + 1])) {\n q += \"*\";\n }\n }\n q = q.replaceAll(\")(\", \")*(\");\n q = q.replaceAll(\"log10*\", \"log10\");\n return q;\n}\n\n// used externally to return the answer to an equation in string form\nexport function newCalculateAnswer(e, index) {\n if (index == 0) {\n variables = new Map();\n }\n\n // if a line is commented out using \"//\", then an answer should not be returned. This can be used by the user to annotate their calculations as they wish\n if (e.substring(0, 2) == \"//\") {\n return \"\"\n }\n if (e.includes(\"=\") && /\\d/.test(e.split(\"=\")[0])) {\n return \"Variable names can't contain numbers\"\n }\n\n if (e.includes(\"=\")) {\n setVariable(e);\n return newCalculateAnswer(e.split(\"=\")[1]);\n }\n\n e = replaceVariables(e, variables);\n\n // remove all white space\n e = e.replaceAll(/\\s/g, \"\");\n\n if (initialErrorChecks(e)[0]) {\n return initialErrorChecks(e)[1];\n }\n\n // replace superscript opening and closing with opening and closing brackets, so that they are handled correctly\n e = e.replaceAll(\";\", \")\");\n e = e.replaceAll(\"^\", \"^(\");\n\n // replace all brackets with regular brackets for calculation\n e = e.replaceAll(\"{\", \"(\");\n e = e.replaceAll(\"}\", \")\");\n e = e.replaceAll(\"[\", \"(\");\n e = e.replaceAll(\"]\", \")\");\n // if the equation is blank, return 0\n if (e == \"\") {\n return \"0\"\n }\n\n // functions replaced with proper syntax to be used in math.js library\n let re = e;\n\n // array of what will be displayed in the equations, and what they need to be replaced with before parsing the equation.\n let replacements = [\n [\"π\", \"(pi)\"],\n [\"cosec(\", \"csc(\"],\n [\"log(\", \"log10(\"],\n [\"ln(\", \"log(\"]\n ];\n re = replaceExpressions(re, replacements, false);\n\n let definedFunctions = [\n \"sin(\",\n \"cos(\",\n \"cot(\",\n \"tan(\",\n \"csc(\",\n \"sec(\",\n \"i\",\n \"abs(\"\n ];\n\n replacements.forEach((replacement) => {\n definedFunctions.push(replacement[0]);\n });\n\n\n // all defined functions will be replaced out for blank, after that, if there is any undefined text remaining, an error will be returned.\n let ne = replaceExpressions(e, definedFunctions, true);\n\n // checking if for any undefined characters, return an error if there are.\n let regex = /[a-zA-Z]/g;\n if (regex.test(ne)) {\n return \"Syntax error, undefined letters\"\n }\n\n // evaluating brackets so that no errors are encountered. For example, previously if you had a power within a trig function, an error would occur\n // this function avoids this error.\n console.log(re);\n while (re.includes(\"(\")) {\n re = evaluateBrack(re);\n }\n\n // the previous function replaces brackets with square brackets so that it knows what brackets it has already evaluated, just replacing them back to normal brackets.\n re = re.replaceAll(\"[\", \"(\");\n re = re.replaceAll(\"]\", \")\");\n\n\n // makes sure that brackets are handled correctly, notably making sure that they multiply with eacher other.\n re = surroundFunction(re);\n\n // grab the unit for angles from settings\n angleUnit = document.getElementById(\"angleInput\").innerText;\n\n let trigFunctionsReplacements = [\n [/sin\\((.*?)\\)/g, `sin($1 ${angleUnit})`],\n [/cos\\((.*?)\\)/g, `cos($1 ${angleUnit})`],\n [/tan\\((.*?)\\)/g, `tan($1 ${angleUnit}`],\n [/cot\\((.*?)\\)/g, `cot($1 ${angleUnit})`],\n [/sec\\((.*?)\\)/g, `sec($1 ${angleUnit})`],\n [/csc\\((.*?)\\)/g, `csc($1 ${angleUnit})`]\n ];\n\n for (let i = 0; i < trigFunctionsReplacements.length; i++) {\n re = re.replace(trigFunctionsReplacements[i][0], trigFunctionsReplacements[i][1]);\n }\n\n try {\n // evaluates the answer, then rounds to the accuracy that the user entered into settings\n let answer = math.evaluate(re).toFixed(Number(document.getElementById(\"precisionInput\").value));\n\n // makes sure that the answer ends at the last significant figure, rather than displaying a bunch of zeros, for example 5.0000000 would be displayed as 5\n let lastSigFig = 0;\n for (let i = 0; i < answer.length; i++) {\n if (answer[i] != \"0\") {\n lastSigFig = i;\n }\n }\n\n // makes sure that there are no unnescessary decimal places, for example 5. would be displayed as 5\n answer = answer.substring(0, 1+lastSigFig);\n if (answer[answer.length - 1] == \".\") {\n answer = answer.substring(0, answer.length - 1);\n }\n\n // then returns the answer to be dispayed if there were no errors\n return answer;\n } catch (error) {\n // if there was an error which was not caught in the try method, just return \n // if it could be due to a negative log, then returns a preset error message\n if (error.message == \"math.evaluate(...).toFixed is not a function\") {\n return \"Math error, could be a negative log.\";\n } else {\n // otherwise, the math.js error message is returned\n return error.message;\n }\n }\n}\n\n// checks for any errors in calculation. Returns array [error?, message]\nfunction initialErrorChecks(e) {\n // iterates through e, checking for unexpected semicolons\n if (checkNegativeDepth(e, \"^\", \";\")) {\n return [true, \"Unexpected power closing (;).\"];\n }\n\n // double checks for any power errors that the previous check may have missed\n let supOp = e.replace(/[^^]/g, \"\").length;\n let supCl = e.replace(/[^;]/g, \"\").length;\n\n if (supOp > supCl) {\n return [true, \"Syntax error, close powers using ;\"]\n }\n \n if (supOp < supCl) {\n return [true, \"Syntax error, more power closings than openings\"]\n }\n\n // check if precison is set to a positive number, more than one\n if (document.getElementById(\"precisionInput\").value < 1) {\n return \"set precision to a number greater than 1\"\n }\n\n // make sure that only integers are entered into precision\n document.getElementById(\"precisionInput\").value = document.getElementById(\"precisionInput\").value.toString().replaceAll(\".\", \"\");\n\n // pow not supported, show the user how to use powers properly\n if (e.includes(\"pow\")) {\n return [true, \"Use ^ for powers. e.g. 5^2;=25. Close a power using ';'\"]\n }\n\n // makes sure that the equation does not end unexpectedly\n if (\"+-*/^(\".includes(e[e.length - 1])) {\n return [true, \"Syntax error, can't end with an operator, or opening bracket\"]\n }\n\n // makes sure that the equation does not begin unexpectedly\n if (\"+*/^)\".includes(e[0])) {\n return [true, \"Syntax error, can't begin with an operator, or closing bracket\"]\n }\n\n // checks for any unexpected closing brackets\n if (checkNegativeDepth(e, \"(\", \")\")) {\n return [true, \"Unexpected closing bracket (')').\"];\n }\n if (checkNegativeDepth(e, \"{\", \"}\")) {\n return [true, \"Unexpected closing curly bracket ('}').\"];\n }\n if (checkNegativeDepth(e, \"[\", \"]\")) {\n return [true, \"Unexpected closing square bracket (']').\"];\n }\n\n // makes sure that the number of closing brackets is the same as the number of opening brackets\n let numOfOpenings = e.replace(/[^(]/g, \"\").length;\n let numOfClosings = e.replace(/[^)]/g, \"\").length;\n if (numOfOpenings != numOfClosings) {\n return [true, \"Syntax error, must have equal number of opening and closing brackets\"]\n }\n\n // makes sure that the equation does not have empty brackets\n if (e.includes(\"()\")) {\n return [true, \"Syntax error, can't have empty brackets.\"]\n }\n\n // unexpected character\n if (e.includes(\"#\")) {\n return [true, \"Syntax error, remove #\"]\n }\n\n // if the equation is blank, return 0\n if (e == \"\") {\n return [true, \"0\"]\n }\n return [false]\n}\n\nfunction checkNegativeDepth(e, op, cl) {\n let depth = 0;\n for (let i = 0; i < e.length; i++) {\n if (e[i] == op) {\n depth++;\n } else if (e[i] == cl) {\n depth--;\n if (depth < 0) {\n return true;\n }\n }\n }\n return false;\n}\n\nfunction replaceExpressions(e, replacements, replaceWithBlank) {\n for (let i = 0; i < replacements.length; i++) {\n e = replaceWithBlank ? e.replaceAll(replacements[i], \"\") : e.replaceAll(replacements[i][0], replacements[i][1]);\n }\n return e;\n}\n\n// used to evaluate complex brackets before putting the equation into math.js. Avoids erros that occur when you have pwoers iwthin a trig function\nfunction evaluateBrack(e) {\n // depth of nested brackets\n let depth = 0;\n // the index of the first opening bracket\n let startOfBrackets;\n // iterating through to find the index of the corresponding closing bracket\n for (let i = 0; i < e.length; i++) {\n if (e[i] == \"(\") {\n depth ++;\n if (depth == 1) {\n startOfBrackets = i;\n }\n } else if (e[i] == \")\") {\n depth --;\n // when the corresponding closing bracket is found, return the equation with that brakcet evaluated, replacing the brackets with square brackets. This function will repeat until all brackets are replaced with square brackets. The square brackets tell the computer that it has already evaluated that bracket.\n if (depth == 0) {\n return e.substring(0, startOfBrackets) + \"[\" + math.evaluate(e.substring(startOfBrackets + 1, i)) + \"]\" + e.substring(i + 1, e.length);\n }\n }\n }\n}\n\nlet variables = new Map();\n\nfunction setVariable(equation) {\n let calculation = equation.split(\"=\")[1];\n if (calculation != \"\") {\n variables.set(equation.split(\"=\")[0], newCalculateAnswer(equation.split(\"=\")[1]));\n }\n}\n\nfunction replaceVariables(equation, variables) {\n let sortedVariables = new Map(\n Array.from(variables).sort((a, b) => b[0].length - a[0].length)\n );\n\n for (let [key,value] of sortedVariables) {\n equation = equation.replaceAll(key, `(${value})`);\n }\n return equation;\n}","import { ref } from 'vue';\nimport { Row } from '../utils/row';\n\nlet instance;\n\nclass RowManager {\n constructor() {\n // ensures that there is only one row manager, singleton\n if (instance) { throw new Error(\"RowManager is already initialized\"); }\n\n // sets up the rows array to be only a blank row, and makes sets the focusRowIndex to 0\n this.rows = ref([new Row(\"\", 0)]);\n this.focusRowIndex = ref(0);\n instance = this;\n }\n\n // returns an array of all the rows\n getRows() { return this.rows.value; }\n\n // returns the row class based on the index\n getRow(index) { return this.rows.value[index]; }\n\n // change the value of a row class\n setRow(index, value) { this.rows.value[index] = value; }\n\n // add a new row based on current index.\n addRowAt(index) {\n if (this.getRow(index).getEquation() == \"\") {\n return;\n }\n // gets the value of the current row\n let currentRow = this.getRow(index).getEquation();\n\n // gets the current row's input field\n let htmlCurrentRow = document.getElementById(`row${index}`);\n\n // gets the current selection within the input field\n let start = htmlCurrentRow.selectionStart;\n let end = htmlCurrentRow.selectionEnd;\n\n // deletes whatever is selected, and puts whatever is after the selection into a different element in the array. These are the new values for the current row, and the new row.\n let currentRowSplit = [currentRow.substring(0, start), currentRow.substring(end, currentRow.length)];\n\n // sets the current row class to a new row, with the first part of the previous array as the equation, and inputs the index\n this.setRow(index, new Row(currentRowSplit[0], index));\n\n // sets the focus row index to the new row\n this.focusRowIndex.value = index + 1;\n\n // resets the rows array\n let temp = this.rows.value;\n this.rows.value = null;\n setTimeout(() => {\n this.rows.value = temp;\n this.rows.value.splice(index + 1, 0, new Row(currentRowSplit[1], index+1));\n\n // makes sure the indexes are all correct\n for (let i = 0; i < this.rows.value.length; i++) {\n this.rows.value[i].setIndex(i);\n }\n\n // recalculates all rows\n this.calculateAllRows();\n }, 1);\n }\n removeRowAt(index) {\n let htmlRow = document.getElementById(`row${index}`);\n let start = htmlRow.selectionStart;\n let end = htmlRow.selectionEnd;\n // if (this.rows.value.length != 1) {\n if ((start == 0 || end == 0) && this.rows.value.length != 1) {\n let equation = this.getRow(index).getEquation();\n let remainingText = equation.substring(end, equation.length);\n let newEquation = this.getRow(index - 1).getEquation() + remainingText;\n let cursorPos = newEquation.length - remainingText.length;\n this.setRow(index - 1, new Row(newEquation, index - 1));\n this.focusRowIndex.value = index != 0 ? index - 1 : 0;\n let temp = this.rows.value;\n this.rows.value = null;\n setTimeout(() => {\n this.rows.value = temp;\n this.rows.value.splice(index, 1);\n\n for (let i = 0; i < this.rows.value.length; i++) {\n this.rows.value[i].setIndex(i);\n }\n }, 1);\n\n setTimeout(() => {\n document.getElementById(`row${this.focusRowIndex.value}`).setSelectionRange(cursorPos, cursorPos);\n this.calculateAllRows();\n }, 1);\n }\n }\n calculateAllRows() {\n setTimeout(() => {\n if (this.rows.value) {\n this.rows.value.forEach(row => row.calculate());\n\n for (let i = 0; i < this.rows.value.length; i++) {\n this.rows.value[i].calculate();\n }\n }\n }, 1);\n }\n getFocusRowIndex() { return this.focusRowIndex.value; }\n setFocusRowIndex(index) { this.focusRowIndex.value = index; }\n adjustFocusRowIndex(direction) {\n let oldIndex = this.focusRowIndex.value;\n let newIndex = oldIndex + direction;\n\n if (newIndex < (this.rows.value.length) && newIndex >= 0) {\n this.focusRowIndex.value = newIndex;\n let cursorPos = document.getElementById(`row${oldIndex}`).selectionStart;\n let newHtmlRow = document.getElementById(`row${this.focusRowIndex.value}`);\n newHtmlRow.focus();\n\n requestAnimationFrame(() => {\n newHtmlRow.setSelectionRange(cursorPos, cursorPos);\n this.calculateAllRows();\n });\n }\n }\n updateSmoothCursorPosition() {\n // cursor is a floating div, with position set to fixed. It's position is dependent on the screen position of inlineCursor\n let cursor = document.getElementById(\"cursor\");\n\n // inline Cursor is a div that is injected into the display equations in the getDisplayEquation function based on where the user's type cursor is.\n let start = document.getElementsByTagName(\"crs\")[0];\n\n if (cursor == null || start == null) {\n requestAnimationFrame(update);\n return\n }\n\n if (document.activeElement.className !== 'inputs') {\n cursor.style.opacity = 0;\n requestAnimationFrame(update);\n return\n }\n\n let end = document.getElementsByTagName(\"crs\")[1];\n \n if (end != null) {\n cursor.className = \"selection\";\n let startPos = start.getBoundingClientRect();\n let endPos = end.getBoundingClientRect();\n\n let width = Math.abs(startPos.left - endPos.left);\n cursor.style.width = width + \"px\";\n }\n else {\n cursor.className = \"cursor\";\n cursor.style.width = \"2px\";\n }\n\n // gets the screen location of the inline cursor\n let rect = start.getBoundingClientRect();\n\n // update position of the cursor\n cursor.style.top = rect.top + \"px\";\n cursor.style.left = rect.left + \"px\";\n\n // make sure that it is visible\n cursor.style.opacity = 1;\n\n // continue the loop\n requestAnimationFrame(update);\n }\n}\n\nconst rowManager = Object.freeze(new RowManager());\n\nrowManager.updateSmoothCursorPosition();\n\nfunction handleEvent(event) {\n if (event.key !== \"Enter\" && event.keyCode != \"38\" && event.keyCode != \"40\") {\n rowManager.calculateAllRows();\n }\n}\n\ndocument.onkeydown = checkKey;\n\nfunction checkKey(e) {\n e = e || window.event;\n if (e.keyCode == \"38\") {\n rowManager.adjustFocusRowIndex(-1);\n }\n else if (e.keyCode == \"40\") {\n rowManager.adjustFocusRowIndex(1);\n }\n}\n\nfunction update() {\n rowManager.updateSmoothCursorPosition();\n}\n\n\ndocument.addEventListener('keyup', handleEvent);\ndocument.addEventListener('keydown', handleEvent);\ndocument.addEventListener('click', handleEvent);\n\nexport default rowManager;","import { replaceSpecialCharacters, newCalculateAnswer, replaceAns } from './calculation';\nimport rowManager from './rowManager';\n\nexport class Row {\n // Row class is a class that is found in the rowManager's rows array. It contains a Row class for each calculation row.\n constructor(e, i) {\n this.equation = e !== null ? e : '';\n this.dispEquation = displayEquation(this.equation);\n this.answer = 0;\n this.index = i;\n }\n\n calculate() {\n let prevRow;\n // if the row manager exists, then set prevRow to the previous row\n if (rowManager) \n prevRow = rowManager.getRow(this.index - 1);\n \n // if prevRow is not null, then prevAnswer is set to prevRow.getAnswer(), otherwise it defaults to 0\n const prevAnswer = prevRow ? prevRow.getAnswer() : 0;\n\n // replaces pi with the pi symbol\n this.equation = replaceSpecialCharacters(this.equation);\n\n // sets the answer to the function, replacing ans with previous answer first.\n this.answer = newCalculateAnswer(replaceAns(this.equation, prevAnswer), this.index);\n\n // this.equation += \" \";\n // this.equation = this.equation.substring(0, this.equation.length - 1);\n\n // displays the equation\n this.dispEquation = displayEquation(this.equation, this.index);\n }\n\n setEquation(e) {\n // sets the equation to e, and calculates all rows, so that variables and ans update\n this.equation = e;\n rowManager.calculateAllRows();\n }\n\n // sets the index of the row to the parameter\n setIndex(i) { this.index = i; }\n\n // returns the equation\n getEquation() { return this.equation; }\n // returns the display equation\n getDispEquation() { return displayEquation(this.equation, this.index); }\n // returns the answer to the equation\n getAnswer() { return this.answer; }\n // returns the index of the row\n getIndex() { return this.index; }\n}\n\n// returns the equation with bracket pair highlighting\nfunction colouredBrackets(e) {\n let depth = 0;\n let nc = \"\";\n let opBrackTypes = [];\n let brackTypes = {\n \"{\" : \"}\",\n \"(\" : \")\",\n \"[\" : \"]\"\n };\n // iterates through each character in e, implementing coloured brackets\n for (let i = 0; i < e.length; i++) {\n // if the character is any type of opening bracket, surround it with a brack tag, with a class indication it's depth, while increasing the depth by 1\n if (\"({[\".includes(e[i])) {\n opBrackTypes.push(e[i]);\n nc += `${e[i]}`;\n // if the character is any type of closing bracket, surround it with a brack tag, with a class indication it's depth, while decreasing the depth by 1\n } else if (\")}]\".includes(e[i])) {\n depth--;\n let dDepth = e[i] == brackTypes[opBrackTypes.pop()] ? depth : -1;\n nc += `${e[i]}`;\n // if the character is not a bracket, just add the character to the string\n } else {\n nc += e[i];\n }\n }\n return nc;\n}\n\nfunction displayEquation(e, index) {\n if (e == \"\") {\n return `type equation here`;\n }\n let commented = false;\n \n // check if the equation is a comment\n if (e.substring(0, 2) == \"//\") {\n commented = true;\n }\n // check that rowManager is not null\n if (rowManager) {\n // get the input field of the row\n let row = document.getElementById(\"row\" + rowManager.getFocusRowIndex());\n // check that row is not null, and that the row is focussed on\n if (row && index === rowManager.getFocusRowIndex()) {\n // get the start and end of the cursor selection in the input field\n var start = row.selectionStart;\n var end = row.selectionEnd;\n\n // add crs tags to display the cursor\n e = insertCursor(e, start, end);\n }\n }\n\n // converts ^ and ; to sup tag opening and closings, also accounts for unexpected;\n e = convertToSuperscript(e);\n\n // ensures that spaces are displayed correctly\n e = e.replaceAll(\" \", \"_\");\n // now that all the necessary formatting has been done, if the row is commented, it is displayed as a comment\n if (commented) {\n return `${e}`;\n }\n\n // an array of strings, and what they will be replaced with when displayed.\n let operands = [\n [\"+\", \" + \"],\n [\"-\", \" - \"],\n [\"*\", \" × \"],\n [\"=\", \" = \"],\n [\"sin(\", \"sin(\"],\n [\"cos(\", \"cos(\"],\n [\"tan(\", \"tan(\"],\n [\"log(\", \"log(\"],\n [\"ln(\", \"ln(\"],\n [\"cosec(\", \"cosec(\"],\n [\"sec(\", \"sec(\"],\n [\"csc(\", \"csc(\"],\n [\"cot(\", \"cot(\"],\n [\"pow(\", \"pow(\"],\n [\"abs(\", \"abs(\"]\n ];\n\n // doing replacements based on operands array\n for (let i = 0; i < operands.length; i++) {\n e = e.replaceAll(operands[i][0], operands[i][1]);\n }\n\n // if there were any uncaught errors that lead to the e being undefined, it is displayed as blank\n if (e == \"undefined\") {\n return \"\";\n }\n\n // implements bracket pair highlighting\n e = colouredBrackets(e);\n\n return e;\n}\n\nfunction convertToSuperscript(e) {\n // number of opening \"^\"`\n let op = 0;\n // number of closings \";\"\n let cl = 0;\n // the string that will be returned\n let q = \"\";\n // iterate through each character in e\n for (let i = 0; i < e.length; i++) {\n if (e[i] == \"^\") {\n // if the character is ^, then add an opening, and add sup tag opening to the string\n op++;\n q += \"\";\n } else if (e[i] == \";\") {\n // otherwise add a closing\n cl++;\n if (cl > op) {\n // if there are more closings than openings, add a semicolon, marked as unexpected\n q += \";\";\n // reset the number of closings and openings, so that the rest of the equation is displayed as if the unexpected semicolon was ignored\n cl = 0;\n op = 0;\n } else {\n // if the semicolon was espected, then add a sup tag closing to the string\n q += \"\";\n }\n } else {\n // if the character is neither ^ or ;, then just add the character to the string\n q += e[i];\n }\n }\n\n return q;\n}\n\nfunction insertCursor(e, start, end) {\n if (start == end)\n // if the cursor is not a selection, and just a cursor then add the crs tag to where the cursor is.\n e = e.substring(0, start) + \"\" + e.substring(start, e.length);\n else {\n // if it is a selection, then add crs tags at the start and end of the selection\n e = e.substring(0, start) + \"\" + e.substring(start, end) + \"\" + e.substring(end, e.length);\n }\n return e\n}","\n\n\n
\n
\n \n
\n
\n
\n
\n
\n
{{ rowManager.getRow(props.index).getAnswer() }}
\n
\n\n\n\n","import script from \"./CalcRow.vue?vue&type=script&setup=true&lang=js\"\nexport * from \"./CalcRow.vue?vue&type=script&setup=true&lang=js\"\n\nimport \"./CalcRow.vue?vue&type=style&index=0&id=7b4dacf4&lang=css\"\n\nconst __exports__ = script;\n\nexport default __exports__","import script from \"./CalcTable.vue?vue&type=script&setup=true&lang=js\"\nexport * from \"./CalcTable.vue?vue&type=script&setup=true&lang=js\"\n\nconst __exports__ = script;\n\nexport default __exports__","\n\n \n
\n
\n
\n
Precision:
\n
\n
\n
\n
Angle Mode:
\n
\n
\n
\n
\n\n","import script from \"./CalcSettings.vue?vue&type=script&setup=true&lang=js\"\nexport * from \"./CalcSettings.vue?vue&type=script&setup=true&lang=js\"\n\nimport \"./CalcSettings.vue?vue&type=style&index=0&id=30d73f64&lang=css\"\n\nconst __exports__ = script;\n\nexport default __exports__","\n \n\n\n","import { render } from \"./TransitionCursor.vue?vue&type=template&id=9bdc2342\"\nconst script = {}\n\nimport \"./TransitionCursor.vue?vue&type=style&index=0&id=9bdc2342&lang=css\"\n\nimport exportComponent from \"../../node_modules/vue-loader/dist/exportHelper.js\"\nconst __exports__ = /*#__PURE__*/exportComponent(script, [['render',render]])\n\nexport default __exports__","import { render } from \"./App.vue?vue&type=template&id=0784ac70\"\nimport script from \"./App.vue?vue&type=script&lang=js\"\nexport * from \"./App.vue?vue&type=script&lang=js\"\n\nimport \"./App.vue?vue&type=style&index=0&id=0784ac70&lang=css\"\n\nimport exportComponent from \"../node_modules/vue-loader/dist/exportHelper.js\"\nconst __exports__ = /*#__PURE__*/exportComponent(script, [['render',render]])\n\nexport default __exports__","import { createApp } from 'vue'\nimport App from './App.vue'\n\ncreateApp(App).mount('#app')\n","// The module cache\nvar __webpack_module_cache__ = {};\n\n// The require function\nfunction __webpack_require__(moduleId) {\n\t// Check if module is in cache\n\tvar cachedModule = __webpack_module_cache__[moduleId];\n\tif (cachedModule !== undefined) {\n\t\treturn cachedModule.exports;\n\t}\n\t// Create a new module (and put it into the cache)\n\tvar module = __webpack_module_cache__[moduleId] = {\n\t\tid: moduleId,\n\t\tloaded: false,\n\t\texports: {}\n\t};\n\n\t// Execute the module function\n\t__webpack_modules__[moduleId].call(module.exports, module, module.exports, __webpack_require__);\n\n\t// Flag the module as loaded\n\tmodule.loaded = true;\n\n\t// Return the exports of the module\n\treturn module.exports;\n}\n\n// expose the modules object (__webpack_modules__)\n__webpack_require__.m = __webpack_modules__;\n\n","__webpack_require__.amdD = function () {\n\tthrow new Error('define cannot be used indirect');\n};","__webpack_require__.amdO = {};","var deferred = [];\n__webpack_require__.O = function(result, chunkIds, fn, priority) {\n\tif(chunkIds) {\n\t\tpriority = priority || 0;\n\t\tfor(var i = deferred.length; i > 0 && deferred[i - 1][2] > priority; i--) deferred[i] = deferred[i - 1];\n\t\tdeferred[i] = [chunkIds, fn, priority];\n\t\treturn;\n\t}\n\tvar notFulfilled = Infinity;\n\tfor (var i = 0; i < deferred.length; i++) {\n\t\tvar chunkIds = deferred[i][0];\n\t\tvar fn = deferred[i][1];\n\t\tvar priority = deferred[i][2];\n\t\tvar fulfilled = true;\n\t\tfor (var j = 0; j < chunkIds.length; j++) {\n\t\t\tif ((priority & 1 === 0 || notFulfilled >= priority) && Object.keys(__webpack_require__.O).every(function(key) { return __webpack_require__.O[key](chunkIds[j]); })) {\n\t\t\t\tchunkIds.splice(j--, 1);\n\t\t\t} else {\n\t\t\t\tfulfilled = false;\n\t\t\t\tif(priority < notFulfilled) notFulfilled = priority;\n\t\t\t}\n\t\t}\n\t\tif(fulfilled) {\n\t\t\tdeferred.splice(i--, 1)\n\t\t\tvar r = fn();\n\t\t\tif (r !== undefined) result = r;\n\t\t}\n\t}\n\treturn result;\n};","// getDefaultExport function for compatibility with non-harmony modules\n__webpack_require__.n = function(module) {\n\tvar getter = module && module.__esModule ?\n\t\tfunction() { return module['default']; } :\n\t\tfunction() { return module; };\n\t__webpack_require__.d(getter, { a: getter });\n\treturn getter;\n};","// define getter functions for harmony exports\n__webpack_require__.d = function(exports, definition) {\n\tfor(var key in definition) {\n\t\tif(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {\n\t\t\tObject.defineProperty(exports, key, { enumerable: true, get: definition[key] });\n\t\t}\n\t}\n};","__webpack_require__.g = (function() {\n\tif (typeof globalThis === 'object') return globalThis;\n\ttry {\n\t\treturn this || new Function('return this')();\n\t} catch (e) {\n\t\tif (typeof window === 'object') return window;\n\t}\n})();","__webpack_require__.o = function(obj, prop) { return Object.prototype.hasOwnProperty.call(obj, prop); }","// define __esModule on exports\n__webpack_require__.r = function(exports) {\n\tif(typeof Symbol !== 'undefined' && Symbol.toStringTag) {\n\t\tObject.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });\n\t}\n\tObject.defineProperty(exports, '__esModule', { value: true });\n};","__webpack_require__.nmd = function(module) {\n\tmodule.paths = [];\n\tif (!module.children) module.children = [];\n\treturn module;\n};","// no baseURI\n\n// object to store loaded and loading chunks\n// undefined = chunk not loaded, null = chunk preloaded/prefetched\n// [resolve, reject, Promise] = chunk loading, 0 = chunk loaded\nvar installedChunks = {\n\t524: 0\n};\n\n// no chunk on demand loading\n\n// no prefetching\n\n// no preloaded\n\n// no HMR\n\n// no HMR manifest\n\n__webpack_require__.O.j = function(chunkId) { return installedChunks[chunkId] === 0; };\n\n// install a JSONP callback for chunk loading\nvar webpackJsonpCallback = function(parentChunkLoadingFunction, data) {\n\tvar chunkIds = data[0];\n\tvar moreModules = data[1];\n\tvar runtime = data[2];\n\t// add \"moreModules\" to the modules object,\n\t// then flag all \"chunkIds\" as loaded and fire callback\n\tvar moduleId, chunkId, i = 0;\n\tif(chunkIds.some(function(id) { return installedChunks[id] !== 0; })) {\n\t\tfor(moduleId in moreModules) {\n\t\t\tif(__webpack_require__.o(moreModules, moduleId)) {\n\t\t\t\t__webpack_require__.m[moduleId] = moreModules[moduleId];\n\t\t\t}\n\t\t}\n\t\tif(runtime) var result = runtime(__webpack_require__);\n\t}\n\tif(parentChunkLoadingFunction) parentChunkLoadingFunction(data);\n\tfor(;i < chunkIds.length; i++) {\n\t\tchunkId = chunkIds[i];\n\t\tif(__webpack_require__.o(installedChunks, chunkId) && installedChunks[chunkId]) {\n\t\t\tinstalledChunks[chunkId][0]();\n\t\t}\n\t\tinstalledChunks[chunkId] = 0;\n\t}\n\treturn __webpack_require__.O(result);\n}\n\nvar chunkLoadingGlobal = self[\"webpackChunkvue_calculator\"] = self[\"webpackChunkvue_calculator\"] || [];\nchunkLoadingGlobal.forEach(webpackJsonpCallback.bind(null, 0));\nchunkLoadingGlobal.push = webpackJsonpCallback.bind(null, chunkLoadingGlobal.push.bind(chunkLoadingGlobal));","// startup\n// Load entry module and return exports\n// This entry module depends on other loaded chunks and execution need to be delayed\nvar __webpack_exports__ = __webpack_require__.O(undefined, [504], function() { return __webpack_require__(7472); })\n__webpack_exports__ = __webpack_require__.O(__webpack_exports__);\n"],"names":["_createElementBlock","_Fragment","_createVNode","_component_CalcSettings","_component_CalcTable","_component_TransitionCursor","prec","angleUnit","config","number","precision","angles","math","create","all","replaceSpecialCharacters","e","replaceAll","replaceAns","prev","surroundFunction","q","i","length","test","newCalculateAnswer","index","variables","Map","substring","includes","split","setVariable","replaceVariables","initialErrorChecks","re","replacements","replaceExpressions","definedFunctions","forEach","replacement","push","ne","regex","console","log","evaluateBrack","document","getElementById","innerText","trigFunctionsReplacements","replace","answer","evaluate","toFixed","Number","value","lastSigFig","error","message","checkNegativeDepth","supOp","supCl","toString","numOfOpenings","numOfClosings","op","cl","depth","replaceWithBlank","startOfBrackets","instance","equation","calculation","set","sortedVariables","Array","from","sort","a","b","key","Row","constructor","this","dispEquation","displayEquation","calculate","prevRow","rowManager","getRow","prevAnswer","getAnswer","setEquation","calculateAllRows","setIndex","getEquation","getDispEquation","getIndex","colouredBrackets","nc","opBrackTypes","brackTypes","dDepth","pop","commented","row","getFocusRowIndex","start","selectionStart","end","selectionEnd","insertCursor","convertToSuperscript","operands","RowManager","Error","rows","ref","focusRowIndex","getRows","setRow","addRowAt","currentRow","htmlCurrentRow","currentRowSplit","temp","setTimeout","splice","removeRowAt","htmlRow","remainingText","newEquation","cursorPos","setSelectionRange","setFocusRowIndex","adjustFocusRowIndex","direction","oldIndex","newIndex","newHtmlRow","focus","requestAnimationFrame","updateSmoothCursorPosition","cursor","getElementsByTagName","update","activeElement","className","style","opacity","startPos","getBoundingClientRect","endPos","width","Math","abs","left","rect","top","Object","freeze","handleEvent","event","keyCode","checkKey","window","onkeydown","addEventListener","props","__props","mounted","rowInput","handleInput","handleEnter","handleBackspace","focusOnRow","getEquals","copyAnswer","navigator","clipboard","writeText","onMounted","__exports__","open","openCloseSettings","changeAngleUnit","units","curUnit","indexOf","id","_hoisted_1","script","name","components","CalcTable","CalcSettings","TransitionCursor","render","createApp","App","mount","__webpack_module_cache__","__webpack_require__","moduleId","cachedModule","undefined","exports","module","loaded","__webpack_modules__","call","m","amdD","amdO","deferred","O","result","chunkIds","fn","priority","notFulfilled","Infinity","fulfilled","j","keys","every","r","n","getter","__esModule","d","definition","o","defineProperty","enumerable","get","g","globalThis","Function","obj","prop","prototype","hasOwnProperty","Symbol","toStringTag","nmd","paths","children","installedChunks","chunkId","webpackJsonpCallback","parentChunkLoadingFunction","data","moreModules","runtime","some","chunkLoadingGlobal","self","bind","__webpack_exports__"],"sourceRoot":""}
\ No newline at end of file
diff --git a/dist/js/app.c80f9199.js b/dist/js/app.c80f9199.js
deleted file mode 100644
index 560328a..0000000
--- a/dist/js/app.c80f9199.js
+++ /dev/null
@@ -1,2 +0,0 @@
-(function(){var e={9083:function(e,t,n){"use strict";var o=n(5130),r=n(6768);function l(e,t,n,o,l,i){const s=(0,r.g2)("CalcSettings"),u=(0,r.g2)("CalcTable"),c=(0,r.g2)("TransitionCursor");return(0,r.uX)(),(0,r.CE)(r.FK,null,[(0,r.bF)(s),(0,r.bF)(u),(0,r.bF)(c)],64)}var i=n(144),s=n(4232),u=(n(4114),n(8490)),c=n(3229),a=256,d="rad";const g={number:"BigNumber",precision:a,angles:d},f=(0,u.v)(c.Q,g);function p(e){return e.replaceAll("pi","π")}function h(e,t){return null==t&&(t="1"),e.replaceAll("ans",`(${t})`)}function w(e){let t="";for(var n=0;n{r.push(e[0])}));let l=x(e,r,!0),i=/[a-zA-Z]/g;if(i.test(l))return"Syntax error, undefined letters";console.log(n);while(n.includes("("))n=b(n);n=n.replaceAll("[","("),n=n.replaceAll("]",")"),n=w(n),d=document.getElementById("angleInput").innerText;let s=[[/sin\((.*?)\)/g,`sin($1 ${d})`],[/cos\((.*?)\)/g,`cos($1 ${d})`],[/tan\((.*?)\)/g,`tan($1 ${d}`],[/cot\((.*?)\)/g,`cot($1 ${d})`],[/sec\((.*?)\)/g,`sec($1 ${d})`],[/csc\((.*?)\)/g,`csc($1 ${d})`]];for(let c=0;cn)return[!0,"Syntax error, close powers using ;"];if(tt[0].length-e[0].length)));for(let[o,r]of n)e=e.replaceAll(o,`(${r})`);return e}class k{constructor(e,t){this.equation=null!==e?e:"",this.dispEquation=q(this.equation),this.answer=0,this.index=t}calculate(){let e;F&&(e=F.getRow(this.index-1));const t=e?e.getAnswer():0;this.equation=p(this.equation),this.answer=m(h(this.equation,t),this.index),this.equation+=" ",this.equation=this.equation.substring(0,this.equation.length-1),this.dispEquation=q(this.equation,this.index)}setEquation(e){this.equation=e,F.calculateAllRows()}setIndex(e){this.index=e}getEquation(){return this.equation}getDispEquation(){return q(this.equation,this.index)}getAnswer(){return this.answer}getIndex(){return this.index}}function A(e){let t=0,n="";for(let o=0;o${e[o]}`:")}]".includes(e[o])?n+=`${e[o]}`:n+=e[o];return n}function q(e,t){let n=!1;if("//"==e.substring(0,2)&&(n=!0),F){let n=document.getElementById("row"+F.getFocusRowIndex());if(n&&t==F.getFocusRowIndex()){var o=n.selectionStart,r=n.selectionEnd;if(o==r)e=e.substring(0,o)+""+e.substring(o,e.length);else{let t=Math.min(o,r),n=Math.max(o,r);e=e.substring(0,t)+""+e.substring(t,n)+""+e.substring(n,e.length)}}}if(e=C(e),e=e.replaceAll(" ","_"),n)return`${e}`;let l=[["+"," + "],["-"," - "],["*"," × "],["="," = "],["sin(","sin("],["cos(","cos("],["tan(","tan("],["log(","log("],["ln(","ln("],["cosec(","cosec("],["sec(","sec("],["csc(","csc("],["cot(","cot("],["pow(","pow("],["abs(","abs("]];for(let i=0;i"):";"==e[r]?(n++,n>t?(o+=";",n=t):o+=""):o+=e[r];return o}class B{constructor(){if(y)throw new Error("RowManager is already initialized");this.rows=(0,i.KR)([new k("",0)]),this.focusRowIndex=(0,i.KR)(0),y=this}getRows(){return this.rows.value}getRow(e){return this.rows.value[e]}setRow(e,t){this.rows.value[e]=t}addRowAt(e){let t=this.getRow(e).getEquation(),n=document.getElementById(`row${e}`),o=n.selectionStart,r=n.selectionEnd,l=[t.substring(0,o),t.substring(r,t.length)];this.setRow(e,new k(l[0],e)),this.focusRowIndex.value=e+1;let i=this.rows.value;this.rows.value=null,setTimeout((()=>{this.rows.value=i,this.rows.value.splice(e+1,0,new k(l[1],e+1));for(let e=0;e{this.rows.value=i,this.rows.value.splice(e,1);for(let e=0;e{document.getElementById(`row${this.focusRowIndex.value}`).setSelectionRange(l,l),this.calculateAllRows()}),1)}}calculateAllRows(){setTimeout((()=>{if(this.rows.value){this.rows.value.forEach((e=>e.calculate()));for(let e=0;e=0){this.focusRowIndex.value=n;let e=document.getElementById(`row${t}`).selectionStart,o=document.getElementById(`row${this.focusRowIndex.value}`);o.focus(),requestAnimationFrame((()=>{o.setSelectionRange(e,e),this.calculateAllRows()}))}}updateSmoothCursorPosition(){let e=document.getElementById("cursor"),t=document.getElementsByTagName("crs")[0];if(null==e||null==t)return void requestAnimationFrame(T);if("inputs"!==document.activeElement.className)return e.style.opacity=0,void requestAnimationFrame(T);let n=document.getElementsByTagName("crs")[1];if(null!=n){e.className="selection";let o=t.getBoundingClientRect(),r=n.getBoundingClientRect(),l=Math.abs(o.left-r.left);e.style.width=l+"px"}else e.className="cursor",e.style.width="2px";let o=t.getBoundingClientRect();e.style.top=o.top+"px",e.style.left=o.left+"px",e.style.opacity=1,requestAnimationFrame(T)}}const $=Object.freeze(new B);function S(e){"Enter"!==e.key&&"38"!=e.keyCode&&"40"!=e.keyCode&&$.calculateAllRows()}function L(e){e=e||window.event,"38"==e.keyCode?$.adjustFocusRowIndex(-1):"40"==e.keyCode&&$.adjustFocusRowIndex(1)}function T(){$.updateSmoothCursorPosition()}$.updateSmoothCursorPosition(),document.onkeydown=L,document.addEventListener("keyup",S),document.addEventListener("keydown",S),document.addEventListener("click",S);var F=$;const j=["id"],M=["id","innerHTML"],O=["id","innerHTML"];var _={__name:"CalcRow",props:{index:{type:Number,required:!0}},setup(e){const t=e;var n=!1;const l=(0,i.KR)();function u(){F.getRow(t.index).setEquation(l.value),l.value=F.getRow(t.index).getEquation()}function c(){F.addRowAt(t.index)}function a(){F.removeRowAt(t.index)}function d(){n&&(document.getElementById(`row${t.index}`).focus(),F.setFocusRowIndex(t.index))}function g(e){return"//"==F.getRow(e).getEquation().substring(0,2)?"":" = "}function f(){navigator.clipboard.writeText(F.getRow(t.index).getAnswer())}return(0,r.sV)((()=>{l.value=F.getRow(t.index).getEquation(),t.index==F.focusRowIndex.value&&document.getElementById(`row${t.index}`).focus(),n=!0,F.updateSmoothCursorPosition()})),d(),(e,n)=>((0,r.uX)(),(0,r.CE)(r.FK,null,[(0,r.Lk)("tr",null,[(0,r.Lk)("td",null,[(0,r.bo)((0,r.Lk)("input",{class:"inputs",id:"row"+t.index,type:"text","onUpdate:modelValue":n[0]||(n[0]=e=>l.value=e),onInput:u,onKeyup:[(0,o.jR)(c,["enter"]),(0,o.jR)(a,["backspace"])],onKeypress:(0,o.jR)(a,["backspace"]),onKeydown:(0,o.jR)(a,["backspace"])},null,40,j),[[o.Jo,l.value]])])]),(0,r.Lk)("tr",null,[(0,r.Lk)("td",{onClick:d,id:"dispRow"+t.index,innerHTML:(0,i.R1)(F).getRow(t.index).getDispEquation()},null,8,M),(0,r.Lk)("td",{id:"equal"+t.index,innerHTML:g(t.index)},null,8,O),(0,r.Lk)("td",{onClick:f,class:"answer"},(0,s.v_)((0,i.R1)(F).getRow(t.index).getAnswer()),1)])],64))}};const K=_;var N=K;const P={id:"calcTable",ref:"calcTable"};var X={__name:"CalcTable",setup(e){return(e,t)=>((0,r.uX)(),(0,r.CE)("table",P,[((0,r.uX)(!0),(0,r.CE)(r.FK,null,(0,r.pI)((0,i.R1)(F).getRows(),(e=>((0,r.uX)(),(0,r.Wv)(N,{key:e.getIndex(),index:e.getIndex()},null,8,["index"])))),128))],512))}};const H=X;var V=H;const z=(0,r.Lk)("i",{class:"fa-solid fa-gear"},null,-1),D=[z],U=(0,r.Lk)("tr",null,[(0,r.Lk)("td",null,"Precision: "),(0,r.Lk)("td",null,[(0,r.Lk)("input",{id:"precisionInput",type:"number"})])],-1),J=(0,r.Lk)("td",null,"Angle Mode: ",-1);var Q={__name:"CalcSettings",setup(e){var t=!0;function n(){t=!t,document.getElementById("settings").className=t?"open":"closed",document.getElementById("settingsButton").className=t?"openButton":"closedButton"}function o(){let e=["rad","deg","grad"],t=document.getElementById("angleInput"),n=e.indexOf(t.innerText)+1;n=n>2?0:n,t.innerText=e[n]}return(0,r.sV)((()=>{document.getElementById("precisionInput").value=10,document.getElementById("angleInput").value="rad"})),(e,t)=>((0,r.uX)(),(0,r.CE)(r.FK,null,[(0,r.Lk)("button",{id:"settingsButton",onClick:n},D),(0,r.Lk)("div",{id:"settings",class:"closed"},[(0,r.Lk)("table",null,[U,(0,r.Lk)("tr",null,[J,(0,r.Lk)("td",null,[(0,r.Lk)("button",{id:"angleInput",type:"text",onClick:o},"rad")])])])])],64))}};const W=Q;var Z=W;const G={id:"cursor"};function Y(e,t){return(0,r.uX)(),(0,r.CE)("div",G)}var ee=n(1241);const te={},ne=(0,ee.A)(te,[["render",Y]]);var oe=ne,re={name:"App",components:{CalcTable:V,CalcSettings:Z,TransitionCursor:oe}};const le=(0,ee.A)(re,[["render",l]]);var ie=le;(0,o.Ef)(ie).mount("#app")},1234:function(){}},t={};function n(o){var r=t[o];if(void 0!==r)return r.exports;var l=t[o]={id:o,loaded:!1,exports:{}};return e[o].call(l.exports,l,l.exports,n),l.loaded=!0,l.exports}n.m=e,function(){n.amdD=function(){throw new Error("define cannot be used indirect")}}(),function(){n.amdO={}}(),function(){var e=[];n.O=function(t,o,r,l){if(!o){var i=1/0;for(a=0;a=l)&&Object.keys(n.O).every((function(e){return n.O[e](o[u])}))?o.splice(u--,1):(s=!1,l0&&e[a-1][2]>l;a--)e[a]=e[a-1];e[a]=[o,r,l]}}(),function(){n.n=function(e){var t=e&&e.__esModule?function(){return e["default"]}:function(){return e};return n.d(t,{a:t}),t}}(),function(){n.d=function(e,t){for(var o in t)n.o(t,o)&&!n.o(e,o)&&Object.defineProperty(e,o,{enumerable:!0,get:t[o]})}}(),function(){n.g=function(){if("object"===typeof globalThis)return globalThis;try{return this||new Function("return this")()}catch(e){if("object"===typeof window)return window}}()}(),function(){n.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)}}(),function(){n.r=function(e){"undefined"!==typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})}}(),function(){n.nmd=function(e){return e.paths=[],e.children||(e.children=[]),e}}(),function(){var e={524:0};n.O.j=function(t){return 0===e[t]};var t=function(t,o){var r,l,i=o[0],s=o[1],u=o[2],c=0;if(i.some((function(t){return 0!==e[t]}))){for(r in s)n.o(s,r)&&(n.m[r]=s[r]);if(u)var a=u(n)}for(t&&t(o);c\n\n\n\n\n\n\n\n\n\n\n","// library to be used for calculations\nimport { create, all } from 'mathjs'\n\n\n// the precision of the calculations, this is then rounded using the number that is inputted by the user in settings.\nvar prec = 256;\n\n// the unit of angles, can be changed to deg or grad in settings\nvar angleUnit = 'rad';\n\n// configure the default type of numbers as BigNumbers\nconst config = {\n // Default type of number\n // Available options: 'number' (default), 'BigNumber', or 'Fraction'\n number: 'BigNumber',\n\n // Number of significant digits for BigNumbers\n precision: prec,\n angles: angleUnit\n}\n\n// set up the library\nconst math = create(all, config);\n\n\n// used externally to replace pi with the symbol pi when the equation is displayed\nexport function replaceSpecialCharacters(e) {\n return e.replaceAll(\"pi\", \"π\");\n}\n\n// used externally to replace when the user types \"ans\", with the previous answer.\nexport function replaceAns(e, prev) {\n if (prev == null) prev = \"1\";\n return e.replaceAll(\"ans\", `(${prev})`); \n}\n\n// makes sure that brackets are dealt with properly, for example, two brackets next to each other should be multiplied by each other.\n// or other example, a number then a bracket should multiply together. \nfunction surroundFunction(e) {\n let q = \"\";\n for (var i = 0; i < e.length; i++) {\n q += e[i];\n \n if (/^\\d+$/.test(e[i]) && e[i + 1] == \"(\") {\n q += \"*\";\n }\n\n if (e[i] == \")\" && /^\\d+$/.test(e[i + 1])) {\n q += \"*\";\n }\n }\n q = q.replaceAll(\")(\", \")*(\");\n q = q.replaceAll(\"log10*\", \"log10\");\n return q;\n}\n\n// used externally to return the answer to an equation in string form\nexport function newCalculateAnswer(e, index) {\n if (index == 0) {\n variables = new Map();\n }\n\n // if a line is commented out using \"//\", then an answer should not be returned. This can be used by the user to annotate their calculations as they wish\n if (e.substring(0, 2) == \"//\") {\n return \"\"\n }\n if (e.includes(\"=\") && /\\d/.test(e.split(\"=\")[0])) {\n return \"Variable names can't contain numbers\"\n }\n\n if (e.includes(\"=\")) {\n setVariable(e);\n return newCalculateAnswer(e.split(\"=\")[1]);\n }\n\n e = replaceVariables(e, variables);\n\n // remove all white space\n e = e.replaceAll(/\\s/g, \"\");\n\n if (initialErrorChecks(e)[0]) {\n return initialErrorChecks(e)[1];\n }\n\n // replace superscript opening and closing with opening and closing brackets, so that they are handled correctly\n e = e.replaceAll(\";\", \")\");\n e = e.replaceAll(\"^\", \"^(\");\n\n // replace all brackets with regular brackets for calculation\n e = e.replaceAll(\"{\", \"(\");\n e = e.replaceAll(\"}\", \")\");\n e = e.replaceAll(\"[\", \"(\");\n e = e.replaceAll(\"]\", \")\");\n // if the equation is blank, return 0\n if (e == \"\") {\n return \"0\"\n }\n\n // functions replaced with proper syntax to be used in math.js library\n let re = e;\n\n // array of what will be displayed in the equations, and what they need to be replaced with before parsing the equation.\n let replacements = [\n [\"π\", \"(pi)\"],\n [\"cosec(\", \"csc(\"],\n [\"log(\", \"log10(\"],\n [\"ln(\", \"log(\"]\n ];\n re = replaceExpressions(re, replacements, false);\n\n let definedFunctions = [\n \"sin(\",\n \"cos(\",\n \"cot(\",\n \"tan(\",\n \"csc(\",\n \"sec(\",\n \"i\",\n \"abs(\"\n ];\n\n replacements.forEach((replacement) => {\n definedFunctions.push(replacement[0]);\n });\n\n\n // all defined functions will be replaced out for blank, after that, if there is any undefined text remaining, an error will be returned.\n let ne = replaceExpressions(e, definedFunctions, true);\n\n // checking if for any undefined characters, return an error if there are.\n let regex = /[a-zA-Z]/g;\n if (regex.test(ne)) {\n return \"Syntax error, undefined letters\"\n }\n\n // evaluating brackets so that no errors are encountered. For example, previously if you had a power within a trig function, an error would occur\n // this function avoids this error.\n console.log(re);\n while (re.includes(\"(\")) {\n re = evaluateBrack(re);\n }\n\n // the previous function replaces brackets with square brackets so that it knows what brackets it has already evaluated, just replacing them back to normal brackets.\n re = re.replaceAll(\"[\", \"(\");\n re = re.replaceAll(\"]\", \")\");\n\n\n // makes sure that brackets are handled correctly, notably making sure that they multiply with eacher other.\n re = surroundFunction(re);\n\n // grab the unit for angles from settings\n angleUnit = document.getElementById(\"angleInput\").innerText;\n\n let trigFunctionsReplacements = [\n [/sin\\((.*?)\\)/g, `sin($1 ${angleUnit})`],\n [/cos\\((.*?)\\)/g, `cos($1 ${angleUnit})`],\n [/tan\\((.*?)\\)/g, `tan($1 ${angleUnit}`],\n [/cot\\((.*?)\\)/g, `cot($1 ${angleUnit})`],\n [/sec\\((.*?)\\)/g, `sec($1 ${angleUnit})`],\n [/csc\\((.*?)\\)/g, `csc($1 ${angleUnit})`]\n ];\n\n for (let i = 0; i < trigFunctionsReplacements.length; i++) {\n re = re.replace(trigFunctionsReplacements[i][0], trigFunctionsReplacements[i][1]);\n }\n\n try {\n // evaluates the answer, then rounds to the accuracy that the user entered into settings\n let answer = math.evaluate(re).toFixed(Number(document.getElementById(\"precisionInput\").value));\n\n // makes sure that the answer ends at the last significant figure, rather than displaying a bunch of zeros, for example 5.0000000 would be displayed as 5\n let lastSigFig = 0;\n for (let i = 0; i < answer.length; i++) {\n if (answer[i] != \"0\") {\n lastSigFig = i;\n }\n }\n\n // makes sure that there are no unnescessary decimal places, for example 5. would be displayed as 5\n answer = answer.substring(0, 1+lastSigFig);\n if (answer[answer.length - 1] == \".\") {\n answer = answer.substring(0, answer.length - 1);\n }\n\n // then returns the answer to be dispayed if there were no errors\n return answer;\n } catch (error) {\n // if there was an error which was not caught in the try method, just return \n // if it could be due to a negative log, then returns a preset error message\n if (error.message == \"math.evaluate(...).toFixed is not a function\") {\n return \"Math error, could be a negative log.\";\n } else {\n // otherwise, the math.js error message is returned\n return error.message;\n }\n }\n}\n\nfunction initialErrorChecks(e) {\n let supOp = e.replace(/[^^]/g, \"\").length;\n let supCl = e.replace(/[^;]/g, \"\").length;\n\n let depth = 0;\n for (let i = 0; i < e.length; i++) {\n if (e[i] == \"^\") {\n depth++;\n } else if (e[i] == \";\") {\n depth--;\n if (depth < 0) {\n return [true, \"unexpected power closing\"];\n }\n }\n }\n\n if (supOp > supCl) {\n return [true, \"Syntax error, close powers using ;\"]\n }\n \n if (supOp < supCl) {\n return [true, \"Syntax error, more power closings than openings\"]\n }\n\n // check if precison is set to a positive number, more than one\n if (document.getElementById(\"precisionInput\").value < 1) {\n return \"set precision to a number greater than 1\"\n }\n\n // make sure that only integers are entered into precision\n document.getElementById(\"precisionInput\").value = document.getElementById(\"precisionInput\").value.toString().replaceAll(\".\", \"\");\n\n // pow not supported, show the user how to use powers properly\n if (e.includes(\"pow\")) {\n return [true, \"Use ^ for powers. e.g. 5^2;=25. Close a power using ';'\"]\n }\n\n // makes sure that the equation does not end unexpectedly\n if (\"+-*/^(\".includes(e[e.length - 1])) {\n return [true, \"Syntax error, can't end with an operator, or opening bracket\"]\n }\n\n // makes sure that the equation does not begin unexpectedly\n if (\"+*/^)\".includes(e[0])) {\n return [true, \"Syntax error, can't begin with an operator, or closing bracket\"]\n }\n\n // makes sure that the number of closing brackets is the same as the number of opening brackets\n let numOfOpenings = e.replace(/[^(]/g, \"\").length;\n let numOfClosings = e.replace(/[^)]/g, \"\").length;\n if (numOfOpenings != numOfClosings) {\n return [true, \"Syntax error, must have equal number of opening and closing brackets\"]\n }\n\n // makes sure that the equation does not have empty brackets\n if (e.includes(\"()\")) {\n return [true, \"Syntax error, can't have empty brackets.\"]\n }\n\n // unexpected character\n if (e.includes(\"#\")) {\n return [true, \"Syntax error, remove #\"]\n }\n\n // if the equation is blank, return 0\n if (e == \"\") {\n return [true, \"0\"]\n }\n return [false]\n}\n\nfunction replaceExpressions(e, replacements, replaceWithBlank) {\n for (let i = 0; i < replacements.length; i++) {\n e = replaceWithBlank ? e.replaceAll(replacements[i], \"\") : e.replaceAll(replacements[i][0], replacements[i][1]);\n }\n return e;\n}\n\n// used to evaluate complex brackets before putting the equation into math.js. Avoids erros that occur when you have pwoers iwthin a trig function\nfunction evaluateBrack(e) {\n // depth of nested brackets\n let depth = 0;\n // the index of the first opening bracket\n let startOfBrackets;\n // iterating through to find the index of the corresponding closing bracket\n for (let i = 0; i < e.length; i++) {\n if (e[i] == \"(\") {\n depth ++;\n if (depth == 1) {\n startOfBrackets = i;\n }\n } else if (e[i] == \")\") {\n depth --;\n // when the corresponding closing bracket is found, return the equation with that brakcet evaluated, replacing the brackets with square brackets. This function will repeat until all brackets are replaced with square brackets. The square brackets tell the computer that it has already evaluated that bracket.\n if (depth == 0) {\n return e.substring(0, startOfBrackets) + \"[\" + math.evaluate(e.substring(startOfBrackets + 1, i)) + \"]\" + e.substring(i + 1, e.length);\n }\n }\n }\n}\n\nlet variables = new Map();\n\nfunction setVariable(equation) {\n let calculation = equation.split(\"=\")[1];\n if (calculation != \"\") {\n variables.set(equation.split(\"=\")[0], newCalculateAnswer(equation.split(\"=\")[1]));\n }\n}\n\nfunction replaceVariables(equation, variables) {\n let sortedVariables = new Map(\n Array.from(variables).sort((a, b) => b[0].length - a[0].length)\n );\n\n for (let [key,value] of sortedVariables) {\n equation = equation.replaceAll(key, `(${value})`);\n }\n return equation;\n}","import { ref } from 'vue';\nimport { Row } from '../utils/row';\n\nlet instance;\n\nclass RowManager {\n constructor() {\n // ensures that there is only one row manager, singleton\n if (instance) { throw new Error(\"RowManager is already initialized\"); }\n\n // sets up the rows array to be only a blank row, and makes sets the focusRowIndex to 0\n this.rows = ref([new Row(\"\", 0)]);\n this.focusRowIndex = ref(0);\n instance = this;\n }\n\n // returns an array of all the rows\n getRows() { return this.rows.value; }\n\n // returns the row class based on the index\n getRow(index) { return this.rows.value[index]; }\n\n // change the value of a row class\n setRow(index, value) { this.rows.value[index] = value; }\n\n // add a new row based on current index.\n addRowAt(index) {\n // gets the value of the current row\n let currentRow = this.getRow(index).getEquation();\n\n // gets the current row's input field\n let htmlCurrentRow = document.getElementById(`row${index}`);\n\n // gets the current selection within the input field\n let start = htmlCurrentRow.selectionStart;\n let end = htmlCurrentRow.selectionEnd;\n\n // deletes whatever is selected, and puts whatever is after the selection into a different element in the array. These are the new values for the current row, and the new row.\n let currentRowSplit = [currentRow.substring(0, start), currentRow.substring(end, currentRow.length)];\n\n // sets the current row class to a new row, with the first part of the previous array as the equation, and inputs the index\n this.setRow(index, new Row(currentRowSplit[0], index));\n\n // sets the focus row index to the new row\n this.focusRowIndex.value = index + 1;\n\n // resets the rows array\n let temp = this.rows.value;\n this.rows.value = null;\n setTimeout(() => {\n this.rows.value = temp;\n this.rows.value.splice(index + 1, 0, new Row(currentRowSplit[1], index+1));\n\n // makes sure the indexes are all correct\n for (let i = 0; i < this.rows.value.length; i++) {\n this.rows.value[i].setIndex(i);\n }\n }, 1);\n }\n removeRowAt(index) {\n let htmlRow = document.getElementById(`row${index}`);\n let start = htmlRow.selectionStart;\n let end = htmlRow.selectionEnd;\n // if (this.rows.value.length != 1) {\n if ((start == 0 || end == 0) && this.rows.value.length != 1) {\n let equation = this.getRow(index).getEquation();\n let remainingText = equation.substring(end, equation.length);\n let newEquation = this.getRow(index - 1).getEquation() + remainingText;\n let cursorPos = newEquation.length - remainingText.length;\n this.setRow(index - 1, new Row(newEquation, index - 1));\n this.focusRowIndex.value = index != 0 ? index - 1 : 0;\n let temp = this.rows.value;\n this.rows.value = null;\n setTimeout(() => {\n this.rows.value = temp;\n this.rows.value.splice(index, 1);\n\n for (let i = 0; i < this.rows.value.length; i++) {\n this.rows.value[i].setIndex(i);\n }\n }, 1);\n\n setTimeout(() => {\n document.getElementById(`row${this.focusRowIndex.value}`).setSelectionRange(cursorPos, cursorPos);\n this.calculateAllRows();\n }, 1);\n }\n }\n calculateAllRows() {\n setTimeout(() => {\n if (this.rows.value) {\n this.rows.value.forEach(row => row.calculate());\n\n for (let i = 0; i < this.rows.value.length; i++) {\n this.rows.value[i].calculate();\n }\n }\n }, 1);\n }\n getFocusRowIndex() { return this.focusRowIndex.value; }\n setFocusRowIndex(index) { this.focusRowIndex.value = index; }\n adjustFocusRowIndex(direction) {\n let oldIndex = this.focusRowIndex.value;\n let newIndex = oldIndex + direction;\n\n if (newIndex < (this.rows.value.length) && newIndex >= 0) {\n this.focusRowIndex.value = newIndex;\n let cursorPos = document.getElementById(`row${oldIndex}`).selectionStart;\n let newHtmlRow = document.getElementById(`row${this.focusRowIndex.value}`);\n newHtmlRow.focus();\n\n requestAnimationFrame(() => {\n newHtmlRow.setSelectionRange(cursorPos, cursorPos);\n this.calculateAllRows();\n });\n }\n }\n updateSmoothCursorPosition() {\n // cursor is a floating div, with position set to fixed. It's position is dependent on the screen position of inlineCursor\n let cursor = document.getElementById(\"cursor\");\n\n // inline Cursor is a div that is injected into the display equations in the getDisplayEquation function based on where the user's type cursor is.\n let start = document.getElementsByTagName(\"crs\")[0];\n\n if (cursor == null || start == null) {\n requestAnimationFrame(update);\n return\n }\n\n if (document.activeElement.className !== 'inputs') {\n cursor.style.opacity = 0;\n requestAnimationFrame(update);\n return\n }\n\n let end = document.getElementsByTagName(\"crs\")[1];\n \n if (end != null) {\n cursor.className = \"selection\";\n let startPos = start.getBoundingClientRect();\n let endPos = end.getBoundingClientRect();\n\n let width = Math.abs(startPos.left - endPos.left);\n cursor.style.width = width + \"px\";\n }\n else {\n cursor.className = \"cursor\";\n cursor.style.width = \"2px\";\n }\n\n // gets the screen location of the inline cursor\n let rect = start.getBoundingClientRect();\n\n // update position of the cursor\n cursor.style.top = rect.top + \"px\";\n cursor.style.left = rect.left + \"px\";\n\n // make sure that it is visible\n cursor.style.opacity = 1;\n\n // continue the loop\n requestAnimationFrame(update);\n }\n}\n\nconst rowManager = Object.freeze(new RowManager());\n\nrowManager.updateSmoothCursorPosition();\n\nfunction handleEvent(event) {\n if (event.key !== \"Enter\" && event.keyCode != \"38\" && event.keyCode != \"40\") {\n rowManager.calculateAllRows();\n }\n}\n\ndocument.onkeydown = checkKey;\n\nfunction checkKey(e) {\n e = e || window.event;\n if (e.keyCode == \"38\") {\n rowManager.adjustFocusRowIndex(-1);\n }\n else if (e.keyCode == \"40\") {\n rowManager.adjustFocusRowIndex(1);\n }\n}\n\nfunction update() {\n rowManager.updateSmoothCursorPosition();\n}\n\n\ndocument.addEventListener('keyup', handleEvent);\ndocument.addEventListener('keydown', handleEvent);\ndocument.addEventListener('click', handleEvent);\n\nexport default rowManager;","import { replaceSpecialCharacters, newCalculateAnswer, replaceAns } from './calculation';\nimport rowManager from './rowManager';\n\nexport class Row {\n constructor(e, i) {\n this.equation = e !== null ? e : '';\n this.dispEquation = displayEquation(this.equation);\n this.answer = 0;\n this.index = i;\n }\n\n calculate() {\n let prevRow;\n if (rowManager) \n prevRow = rowManager.getRow(this.index - 1);\n \n const prevAnswer = prevRow ? prevRow.getAnswer() : 0;\n this.equation = replaceSpecialCharacters(this.equation);\n this.answer = newCalculateAnswer(replaceAns(this.equation, prevAnswer), this.index);\n\n this.equation += \" \";\n this.equation = this.equation.substring(0, this.equation.length - 1);\n this.dispEquation = displayEquation(this.equation, this.index);\n }\n\n setEquation(e) {\n this.equation = e;\n rowManager.calculateAllRows();\n }\n\n setIndex(i) { this.index = i; }\n\n getEquation() { return this.equation; }\n getDispEquation() { return displayEquation(this.equation, this.index); }\n getAnswer() { return this.answer; }\n getIndex() { return this.index; }\n}\n\nfunction colouredBrackets(e) {\n let depth = 0;\n let nc = \"\";\n for (let i = 0; i < e.length; i++) {\n // if (e[i] == \"(\") {\n if (\"({[\".includes(e[i])) {\n nc += `${e[i]}`;\n //} else if (e[i] == \")\") {\n } else if (\")}]\".includes(e[i])) {\n nc += `${e[i]}`;\n } else {\n nc += e[i];\n }\n }\n return nc;\n}\n\nfunction displayEquation(e, index) {\n let commented = false;\n \n if (e.substring(0, 2) == \"//\") {\n commented = true;\n }\n if (rowManager) {\n let row = document.getElementById(\"row\" + rowManager.getFocusRowIndex());\n if (row) {\n if (index == rowManager.getFocusRowIndex()) {\n var start = row.selectionStart;\n var end = row.selectionEnd;\n if (start == end)\n e = e.substring(0, start) + \"\" + e.substring(start, e.length);\n else {\n let first = Math.min(...[start, end]);\n let second = Math.max(...[start, end]);\n e = e.substring(0, first) + \"\" + e.substring(first, second) + \"\" + e.substring(second, e.length);\n }\n }\n }\n }\n e = convertToSuperscript(e);\n\n e = e.replaceAll(\" \", \"_\");\n if (commented) {\n return `${e}`;\n }\n\n let operands = [\n [\"+\", \" + \"],\n [\"-\", \" - \"],\n [\"*\", \" × \"],\n [\"=\", \" = \"],\n [\"sin(\", \"sin(\"],\n [\"cos(\", \"cos(\"],\n [\"tan(\", \"tan(\"],\n [\"log(\", \"log(\"],\n [\"ln(\", \"ln(\"],\n [\"cosec(\", \"cosec(\"],\n [\"sec(\", \"sec(\"],\n [\"csc(\", \"csc(\"],\n [\"cot(\", \"cot(\"],\n [\"pow(\", \"pow(\"],\n [\"abs(\", \"abs(\"]\n ];\n\n for (let i = 0; i < operands.length; i++) {\n e = e.replaceAll(operands[i][0], operands[i][1]);\n }\n\n if (e == \"undefined\") {\n return \"\";\n }\n\n e = colouredBrackets(e);\n\n return e;\n}\n\nfunction convertToSuperscript(e) {\n // e = e.replaceAll(\"^\", \"\");\n // e = e.replaceAll(\";\", \" \");\n\n let op = 0;\n let cl = 0;\n let q = \"\";\n for (let i = 0; i < e.length; i++) {\n if (e[i] == \"^\") {\n op++;\n q += \"\";\n } else if (e[i] == \";\") {\n cl++;\n if (cl > op) {\n q += \";\";\n cl = op;\n } else {\n q += \"\";\n }\n } else {\n q += e[i];\n }\n }\n\n return q;\n}","\n\n\n
\n
\n \n
\n
\n
\n
\n
\n
{{ rowManager.getRow(props.index).getAnswer() }}
\n
\n\n\n\n","import script from \"./CalcRow.vue?vue&type=script&setup=true&lang=js\"\nexport * from \"./CalcRow.vue?vue&type=script&setup=true&lang=js\"\n\nimport \"./CalcRow.vue?vue&type=style&index=0&id=4b9a9a10&lang=css\"\n\nconst __exports__ = script;\n\nexport default __exports__","import script from \"./CalcTable.vue?vue&type=script&setup=true&lang=js\"\nexport * from \"./CalcTable.vue?vue&type=script&setup=true&lang=js\"\n\nconst __exports__ = script;\n\nexport default __exports__","\n\n \n
\n
\n
\n
Precision:
\n
\n
\n
\n
Angle Mode:
\n
\n
\n
\n
\n\n","import script from \"./CalcSettings.vue?vue&type=script&setup=true&lang=js\"\nexport * from \"./CalcSettings.vue?vue&type=script&setup=true&lang=js\"\n\nimport \"./CalcSettings.vue?vue&type=style&index=0&id=30d73f64&lang=css\"\n\nconst __exports__ = script;\n\nexport default __exports__","\n \n\n\n","import { render } from \"./TransitionCursor.vue?vue&type=template&id=9bdc2342\"\nconst script = {}\n\nimport \"./TransitionCursor.vue?vue&type=style&index=0&id=9bdc2342&lang=css\"\n\nimport exportComponent from \"../../node_modules/vue-loader/dist/exportHelper.js\"\nconst __exports__ = /*#__PURE__*/exportComponent(script, [['render',render]])\n\nexport default __exports__","import { render } from \"./App.vue?vue&type=template&id=0784ac70\"\nimport script from \"./App.vue?vue&type=script&lang=js\"\nexport * from \"./App.vue?vue&type=script&lang=js\"\n\nimport \"./App.vue?vue&type=style&index=0&id=0784ac70&lang=css\"\n\nimport exportComponent from \"../node_modules/vue-loader/dist/exportHelper.js\"\nconst __exports__ = /*#__PURE__*/exportComponent(script, [['render',render]])\n\nexport default __exports__","import { createApp } from 'vue'\nimport App from './App.vue'\n\ncreateApp(App).mount('#app')\n","// The module cache\nvar __webpack_module_cache__ = {};\n\n// The require function\nfunction __webpack_require__(moduleId) {\n\t// Check if module is in cache\n\tvar cachedModule = __webpack_module_cache__[moduleId];\n\tif (cachedModule !== undefined) {\n\t\treturn cachedModule.exports;\n\t}\n\t// Create a new module (and put it into the cache)\n\tvar module = __webpack_module_cache__[moduleId] = {\n\t\tid: moduleId,\n\t\tloaded: false,\n\t\texports: {}\n\t};\n\n\t// Execute the module function\n\t__webpack_modules__[moduleId].call(module.exports, module, module.exports, __webpack_require__);\n\n\t// Flag the module as loaded\n\tmodule.loaded = true;\n\n\t// Return the exports of the module\n\treturn module.exports;\n}\n\n// expose the modules object (__webpack_modules__)\n__webpack_require__.m = __webpack_modules__;\n\n","__webpack_require__.amdD = function () {\n\tthrow new Error('define cannot be used indirect');\n};","__webpack_require__.amdO = {};","var deferred = [];\n__webpack_require__.O = function(result, chunkIds, fn, priority) {\n\tif(chunkIds) {\n\t\tpriority = priority || 0;\n\t\tfor(var i = deferred.length; i > 0 && deferred[i - 1][2] > priority; i--) deferred[i] = deferred[i - 1];\n\t\tdeferred[i] = [chunkIds, fn, priority];\n\t\treturn;\n\t}\n\tvar notFulfilled = Infinity;\n\tfor (var i = 0; i < deferred.length; i++) {\n\t\tvar chunkIds = deferred[i][0];\n\t\tvar fn = deferred[i][1];\n\t\tvar priority = deferred[i][2];\n\t\tvar fulfilled = true;\n\t\tfor (var j = 0; j < chunkIds.length; j++) {\n\t\t\tif ((priority & 1 === 0 || notFulfilled >= priority) && Object.keys(__webpack_require__.O).every(function(key) { return __webpack_require__.O[key](chunkIds[j]); })) {\n\t\t\t\tchunkIds.splice(j--, 1);\n\t\t\t} else {\n\t\t\t\tfulfilled = false;\n\t\t\t\tif(priority < notFulfilled) notFulfilled = priority;\n\t\t\t}\n\t\t}\n\t\tif(fulfilled) {\n\t\t\tdeferred.splice(i--, 1)\n\t\t\tvar r = fn();\n\t\t\tif (r !== undefined) result = r;\n\t\t}\n\t}\n\treturn result;\n};","// getDefaultExport function for compatibility with non-harmony modules\n__webpack_require__.n = function(module) {\n\tvar getter = module && module.__esModule ?\n\t\tfunction() { return module['default']; } :\n\t\tfunction() { return module; };\n\t__webpack_require__.d(getter, { a: getter });\n\treturn getter;\n};","// define getter functions for harmony exports\n__webpack_require__.d = function(exports, definition) {\n\tfor(var key in definition) {\n\t\tif(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {\n\t\t\tObject.defineProperty(exports, key, { enumerable: true, get: definition[key] });\n\t\t}\n\t}\n};","__webpack_require__.g = (function() {\n\tif (typeof globalThis === 'object') return globalThis;\n\ttry {\n\t\treturn this || new Function('return this')();\n\t} catch (e) {\n\t\tif (typeof window === 'object') return window;\n\t}\n})();","__webpack_require__.o = function(obj, prop) { return Object.prototype.hasOwnProperty.call(obj, prop); }","// define __esModule on exports\n__webpack_require__.r = function(exports) {\n\tif(typeof Symbol !== 'undefined' && Symbol.toStringTag) {\n\t\tObject.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });\n\t}\n\tObject.defineProperty(exports, '__esModule', { value: true });\n};","__webpack_require__.nmd = function(module) {\n\tmodule.paths = [];\n\tif (!module.children) module.children = [];\n\treturn module;\n};","// no baseURI\n\n// object to store loaded and loading chunks\n// undefined = chunk not loaded, null = chunk preloaded/prefetched\n// [resolve, reject, Promise] = chunk loading, 0 = chunk loaded\nvar installedChunks = {\n\t524: 0\n};\n\n// no chunk on demand loading\n\n// no prefetching\n\n// no preloaded\n\n// no HMR\n\n// no HMR manifest\n\n__webpack_require__.O.j = function(chunkId) { return installedChunks[chunkId] === 0; };\n\n// install a JSONP callback for chunk loading\nvar webpackJsonpCallback = function(parentChunkLoadingFunction, data) {\n\tvar chunkIds = data[0];\n\tvar moreModules = data[1];\n\tvar runtime = data[2];\n\t// add \"moreModules\" to the modules object,\n\t// then flag all \"chunkIds\" as loaded and fire callback\n\tvar moduleId, chunkId, i = 0;\n\tif(chunkIds.some(function(id) { return installedChunks[id] !== 0; })) {\n\t\tfor(moduleId in moreModules) {\n\t\t\tif(__webpack_require__.o(moreModules, moduleId)) {\n\t\t\t\t__webpack_require__.m[moduleId] = moreModules[moduleId];\n\t\t\t}\n\t\t}\n\t\tif(runtime) var result = runtime(__webpack_require__);\n\t}\n\tif(parentChunkLoadingFunction) parentChunkLoadingFunction(data);\n\tfor(;i < chunkIds.length; i++) {\n\t\tchunkId = chunkIds[i];\n\t\tif(__webpack_require__.o(installedChunks, chunkId) && installedChunks[chunkId]) {\n\t\t\tinstalledChunks[chunkId][0]();\n\t\t}\n\t\tinstalledChunks[chunkId] = 0;\n\t}\n\treturn __webpack_require__.O(result);\n}\n\nvar chunkLoadingGlobal = self[\"webpackChunkvue_calculator\"] = self[\"webpackChunkvue_calculator\"] || [];\nchunkLoadingGlobal.forEach(webpackJsonpCallback.bind(null, 0));\nchunkLoadingGlobal.push = webpackJsonpCallback.bind(null, chunkLoadingGlobal.push.bind(chunkLoadingGlobal));","// startup\n// Load entry module and return exports\n// This entry module depends on other loaded chunks and execution need to be delayed\nvar __webpack_exports__ = __webpack_require__.O(undefined, [504], function() { return __webpack_require__(9083); })\n__webpack_exports__ = __webpack_require__.O(__webpack_exports__);\n"],"names":["_createElementBlock","_Fragment","_createVNode","_component_CalcSettings","_component_CalcTable","_component_TransitionCursor","prec","angleUnit","config","number","precision","angles","math","create","all","replaceSpecialCharacters","e","replaceAll","replaceAns","prev","surroundFunction","q","i","length","test","newCalculateAnswer","index","variables","Map","substring","includes","split","setVariable","replaceVariables","initialErrorChecks","re","replacements","replaceExpressions","definedFunctions","forEach","replacement","push","ne","regex","console","log","evaluateBrack","document","getElementById","innerText","trigFunctionsReplacements","replace","answer","evaluate","toFixed","Number","value","lastSigFig","error","message","supOp","supCl","depth","toString","numOfOpenings","numOfClosings","replaceWithBlank","startOfBrackets","instance","equation","calculation","set","sortedVariables","Array","from","sort","a","b","key","Row","constructor","this","dispEquation","displayEquation","calculate","prevRow","rowManager","getRow","prevAnswer","getAnswer","setEquation","calculateAllRows","setIndex","getEquation","getDispEquation","getIndex","colouredBrackets","nc","commented","row","getFocusRowIndex","start","selectionStart","end","selectionEnd","first","Math","min","second","max","convertToSuperscript","operands","op","cl","RowManager","Error","rows","ref","focusRowIndex","getRows","setRow","addRowAt","currentRow","htmlCurrentRow","currentRowSplit","temp","setTimeout","splice","removeRowAt","htmlRow","remainingText","newEquation","cursorPos","setSelectionRange","setFocusRowIndex","adjustFocusRowIndex","direction","oldIndex","newIndex","newHtmlRow","focus","requestAnimationFrame","updateSmoothCursorPosition","cursor","getElementsByTagName","update","activeElement","className","style","opacity","startPos","getBoundingClientRect","endPos","width","abs","left","rect","top","Object","freeze","handleEvent","event","keyCode","checkKey","window","onkeydown","addEventListener","props","__props","mounted","rowInput","handleInput","handleEnter","handleBackspace","focusOnRow","getEquals","copyAnswer","navigator","clipboard","writeText","onMounted","__exports__","open","openCloseSettings","changeAngleUnit","units","curUnit","indexOf","id","_hoisted_1","script","name","components","CalcTable","CalcSettings","TransitionCursor","render","createApp","App","mount","__webpack_module_cache__","__webpack_require__","moduleId","cachedModule","undefined","exports","module","loaded","__webpack_modules__","call","m","amdD","amdO","deferred","O","result","chunkIds","fn","priority","notFulfilled","Infinity","fulfilled","j","keys","every","r","n","getter","__esModule","d","definition","o","defineProperty","enumerable","get","g","globalThis","Function","obj","prop","prototype","hasOwnProperty","Symbol","toStringTag","nmd","paths","children","installedChunks","chunkId","webpackJsonpCallback","parentChunkLoadingFunction","data","moreModules","runtime","some","chunkLoadingGlobal","self","bind","__webpack_exports__"],"sourceRoot":""}
\ No newline at end of file
diff --git a/src/components/CalcRow.vue b/src/components/CalcRow.vue
index c557324..b53c8d3 100644
--- a/src/components/CalcRow.vue
+++ b/src/components/CalcRow.vue
@@ -68,36 +68,27 @@ function copyAnswer() {
/>
-