From 88010409d4a4d4887f1663efa3cb7c5daaf16dab Mon Sep 17 00:00:00 2001 From: lucas Date: Mon, 21 Jul 2025 22:18:00 -0300 Subject: [PATCH] add command math --- package.json | 1 + src/renderer/src/App.tsx | 3 + src/renderer/src/components/CommandMath.tsx | 44 ++++++++++++ src/renderer/src/elements/Card.tsx | 74 +++++++++++++++++++++ src/renderer/src/lib/math.ts | 19 ++++++ yarn.lock | 60 +++++++++++++++++ 6 files changed, 201 insertions(+) create mode 100644 src/renderer/src/components/CommandMath.tsx create mode 100644 src/renderer/src/elements/Card.tsx create mode 100644 src/renderer/src/lib/math.ts diff --git a/package.json b/package.json index 8c20e50..373d63c 100644 --- a/package.json +++ b/package.json @@ -39,6 +39,7 @@ "js-yaml": "^4.1.0", "lodash.shuffle": "^4.2.0", "lucide-react": "^0.462.0", + "mathjs": "^14.5.3", "tailwind-merge": "^2.5.4", "tailwindcss-animate": "^1.0.7" }, diff --git a/src/renderer/src/App.tsx b/src/renderer/src/App.tsx index 5359d9d..13544b1 100644 --- a/src/renderer/src/App.tsx +++ b/src/renderer/src/App.tsx @@ -9,6 +9,7 @@ import { CommandApplications } from '@renderer/components/CommandApplications' import { CommandShortcuts } from '@renderer/components/CommandShortcuts' import { useScrollToTop } from '@renderer/hooks' import { Settings } from '@renderer/components/Settings' +import { CommandMath } from './components/CommandMath' const App = () => { const [selectedCommand, setSelectedCommand] = useState(null) @@ -50,6 +51,8 @@ const App = () => { + + diff --git a/src/renderer/src/components/CommandMath.tsx b/src/renderer/src/components/CommandMath.tsx new file mode 100644 index 0000000..5c87162 --- /dev/null +++ b/src/renderer/src/components/CommandMath.tsx @@ -0,0 +1,44 @@ +import { Card } from '@renderer/elements/Card' +import { CommandGroup } from '@renderer/elements/Command' +import { evaluateMathExpression, isMathExpression } from '@renderer/lib/math' +import { ArrowRight } from 'lucide-react' +import { useMemo } from 'react' + +type CommandMathProps = { commandSearch: string } + +export const CommandMath = ({ commandSearch }: CommandMathProps) => { + const { isMathCommand, resultMath } = useMemo(() => { + const isMathCommand = isMathExpression(commandSearch) + if (isMathCommand) { + return { isMathCommand, resultMath: evaluateMathExpression(commandSearch) } + } + return { isMathCommand: false, resultMath: null } + }, [commandSearch]) + + return ( + <> + {isMathCommand && ( +
+
+

Calculator

+ +
+
+ {commandSearch} +
+ + + +
+
+ {resultMath} +
+
+
+
+
+
+ )} + + ) +} diff --git a/src/renderer/src/elements/Card.tsx b/src/renderer/src/elements/Card.tsx new file mode 100644 index 0000000..f257980 --- /dev/null +++ b/src/renderer/src/elements/Card.tsx @@ -0,0 +1,74 @@ +import { cn } from '@renderer/lib/utils' +import * as React from 'react' + +function Card({ className, ...props }: React.ComponentProps<'div'>) { + return ( +
+ ) +} + +function CardHeader({ className, ...props }: React.ComponentProps<'div'>) { + return ( +
+ ) +} + +function CardTitle({ className, ...props }: React.ComponentProps<'div'>) { + return ( +
+ ) +} + +function CardDescription({ className, ...props }: React.ComponentProps<'div'>) { + return ( +
+ ) +} + +function CardAction({ className, ...props }: React.ComponentProps<'div'>) { + return ( +
+ ) +} + +function CardContent({ className, ...props }: React.ComponentProps<'div'>) { + return
+} + +function CardFooter({ className, ...props }: React.ComponentProps<'div'>) { + return ( +
+ ) +} + +export { Card, CardHeader, CardFooter, CardTitle, CardAction, CardDescription, CardContent } diff --git a/src/renderer/src/lib/math.ts b/src/renderer/src/lib/math.ts new file mode 100644 index 0000000..65fdf42 --- /dev/null +++ b/src/renderer/src/lib/math.ts @@ -0,0 +1,19 @@ +import { evaluate } from 'mathjs' + +export function isMathExpression(str: string): boolean { + try { + const result = evaluate(str) + return typeof result === 'number' && isFinite(result) + } catch { + return false + } +} + +export function evaluateMathExpression(str: string): string { + try { + const result = evaluate(str) + return typeof result === 'number' ? result.toString() : 'Invalid expression' + } catch (error) { + return 'Invalid expression' + } +} diff --git a/yarn.lock b/yarn.lock index 885d3ad..daf4272 100644 --- a/yarn.lock +++ b/yarn.lock @@ -171,6 +171,11 @@ dependencies: "@babel/helper-plugin-utils" "^7.27.1" +"@babel/runtime@^7.26.10": + version "7.27.6" + resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.27.6.tgz#ec4070a04d76bae8ddbb10770ba55714a417b7c6" + integrity sha512-vbavdySgbTTrmFE+EsiqUTzlOr5bzlnJtUv9PynGCAKvfQqjIXbvFdumPM/GxMDfyuGMJaJAU6TO4zc1Jf1i8Q== + "@babel/template@^7.25.9", "@babel/template@^7.27.1": version "7.27.2" resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.27.2.tgz#fa78ceed3c4e7b63ebf6cb39e5852fca45f6809d" @@ -2251,6 +2256,11 @@ compare-version@^0.1.2: resolved "https://registry.yarnpkg.com/compare-version/-/compare-version-0.1.2.tgz#0162ec2d9351f5ddd59a9202cba935366a725080" integrity sha512-pJDh5/4wrEnXX/VWRZvruAGHkzKdr46z11OlTPN+VrATlWWhSKewNCJ1futCO5C7eJB3nPMFZA1LeYtcFboZ2A== +complex.js@^2.2.5: + version "2.4.2" + resolved "https://registry.yarnpkg.com/complex.js/-/complex.js-2.4.2.tgz#76f260a9e7e232d8ad26348484a9b128c13fcc9a" + integrity sha512-qtx7HRhPGSCBtGiST4/WGHuW+zeaND/6Ld+db6PbrulIB1i2Ev/2UPiqcmpQNPSyfBKraC0EOvOKCB5dGZKt3g== + concat-map@0.0.1: version "0.0.1" resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" @@ -2379,6 +2389,11 @@ debug@^4.1.0, debug@^4.1.1, debug@^4.3.1, debug@^4.3.2, debug@^4.3.4: dependencies: ms "^2.1.3" +decimal.js@^10.4.3: + version "10.6.0" + resolved "https://registry.yarnpkg.com/decimal.js/-/decimal.js-10.6.0.tgz#e649a43e3ab953a72192ff5983865e509f37ed9a" + integrity sha512-YpgQiITW3JXGntzdUmyUR1V812Hn8T1YVXhCu+wO3OpS4eU9l4YdD3qjyiKdV6mvV29zapkMeD390UVEf2lkUg== + decompress-response@^6.0.0: version "6.0.0" resolved "https://registry.yarnpkg.com/decompress-response/-/decompress-response-6.0.0.tgz#ca387612ddb7e104bd16d85aab00d5ecf09c66fc" @@ -2912,6 +2927,11 @@ escalade@^3.1.1, escalade@^3.2.0: resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.2.0.tgz#011a3f69856ba189dffa7dc8fcce99d2a87903e5" integrity sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA== +escape-latex@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/escape-latex/-/escape-latex-1.2.0.tgz#07c03818cf7dac250cce517f4fda1b001ef2bca1" + integrity sha512-nV5aVWW1K0wEiUIEdZ4erkGGH8mDxGyxSeqPzRNtWP7ataw+/olFObw7hujFWlVjNsaDFw5VZ5NzVSIqRgfTiw== + escape-string-regexp@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz#14ba83a5d373e3d311e5afca29cf5bfad965bf34" @@ -3194,6 +3214,11 @@ form-data@^4.0.0: es-set-tostringtag "^2.1.0" mime-types "^2.1.12" +fraction.js@^5.2.1: + version "5.2.2" + resolved "https://registry.yarnpkg.com/fraction.js/-/fraction.js-5.2.2.tgz#c1295bc47307c5f93f75790859645fd74edaa195" + integrity sha512-uXBDv5knpYmv/2gLzWQ5mBHGBRk9wcKTeWu6GLTUEQfjCxO09uM/mHDrojlL+Q1mVGIIFo149Gba7od1XPgSzQ== + fs-extra@^10.0.0, fs-extra@^10.1.0: version "10.1.0" resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-10.1.0.tgz#02873cfbc4084dde127eaa5f9905eef2325d1abf" @@ -3923,6 +3948,11 @@ jake@^10.8.5: filelist "^1.0.4" minimatch "^3.1.2" +javascript-natural-sort@^0.7.1: + version "0.7.1" + resolved "https://registry.yarnpkg.com/javascript-natural-sort/-/javascript-natural-sort-0.7.1.tgz#f9e2303d4507f6d74355a73664d1440fb5a0ef59" + integrity sha512-nO6jcEfZWQXDhOiBtG2KvKyEptz7RVbpGP4vTD2hLBdmNQSsCiicO2Ioinv6UI4y9ukqnBpy+XZ9H6uLNgJTlw== + jiti@^2.4.2: version "2.4.2" resolved "https://registry.yarnpkg.com/jiti/-/jiti-2.4.2.tgz#d19b7732ebb6116b06e2038da74a55366faef560" @@ -4235,6 +4265,21 @@ math-intrinsics@^1.1.0: resolved "https://registry.yarnpkg.com/math-intrinsics/-/math-intrinsics-1.1.0.tgz#a0dd74be81e2aa5c2f27e65ce283605ee4e2b7f9" integrity sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g== +mathjs@^14.5.3: + version "14.5.3" + resolved "https://registry.yarnpkg.com/mathjs/-/mathjs-14.5.3.tgz#e75100088adfb6da7c367404f9aba9ed9354c450" + integrity sha512-srHhiZwFPUjHuRywRG/+5xWUNcQJsDBNMYaSu7zEN+th6BB2TkUmBkIc2cpdDqtgu40Q7DneAsFmyzo8q3ugmA== + dependencies: + "@babel/runtime" "^7.26.10" + complex.js "^2.2.5" + decimal.js "^10.4.3" + escape-latex "^1.2.0" + fraction.js "^5.2.1" + javascript-natural-sort "^0.7.1" + seedrandom "^3.0.5" + tiny-emitter "^2.1.0" + typed-function "^4.2.1" + merge2@^1.3.0, merge2@^1.4.1: version "1.4.1" resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.4.1.tgz#4368892f885e907455a6fd7dc55c0c9d404990ae" @@ -5090,6 +5135,11 @@ scheduler@^0.23.2: dependencies: loose-envify "^1.1.0" +seedrandom@^3.0.5: + version "3.0.5" + resolved "https://registry.yarnpkg.com/seedrandom/-/seedrandom-3.0.5.tgz#54edc85c95222525b0c7a6f6b3543d8e0b3aa0a7" + integrity sha512-8OwmbklUNzwezjGInmZ+2clQmExQPvomqjL7LFqOYqtmuxRgQYqOD3mHaU+MvZn5FLUeVxVfQjwLZW/n/JFuqg== + semver-compare@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/semver-compare/-/semver-compare-1.0.0.tgz#0dee216a1c941ab37e9efb1788f6afc5ff5537fc" @@ -5496,6 +5546,11 @@ temp-file@^3.4.0: async-exit-hook "^2.0.1" fs-extra "^10.0.0" +tiny-emitter@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/tiny-emitter/-/tiny-emitter-2.1.0.tgz#1d1a56edfc51c43e863cbb5382a72330e3555423" + integrity sha512-NB6Dk1A9xgQPMoGqC5CVXn123gWyte215ONT5Pp5a0yt4nlEoO1ZWeCwpncaekPHXO60i47ihFnZPiRPjRMq4Q== + tiny-typed-emitter@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/tiny-typed-emitter/-/tiny-typed-emitter-2.1.0.tgz#b3b027fdd389ff81a152c8e847ee2f5be9fad7b5" @@ -5607,6 +5662,11 @@ typed-array-length@^1.0.7: possible-typed-array-names "^1.0.0" reflect.getprototypeof "^1.0.6" +typed-function@^4.2.1: + version "4.2.1" + resolved "https://registry.yarnpkg.com/typed-function/-/typed-function-4.2.1.tgz#19aa51847aa2dea9ef5e7fb7641c060179a74426" + integrity sha512-EGjWssW7Tsk4DGfE+5yluuljS1OGYWiI1J6e8puZz9nTMM51Oug8CD5Zo4gWMsOhq5BI+1bF+rWTm4Vbj3ivRA== + typescript@^5.4.3: version "5.7.2" resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.7.2.tgz#3169cf8c4c8a828cde53ba9ecb3d2b1d5dd67be6"