Implement vue math (#7759)

Adds support for entering math inside number widgets in vue mode

![vue-math_00001](https://github.com/user-attachments/assets/e8ed7e2a-511f-4550-bfdd-1c467972d30d)

Migrates components to simple html elements (div and button) by
borrowing styling from the (reverted) reka-ui migration in #6985. The
existing (evil) litegraph eval code is extracted as a utility function
and reused.

This PR means we're entirely writing our own NumberField.

Also adds support for scrubbing widgets like in litegraph

![scrubbing_00001](https://github.com/user-attachments/assets/890bcd28-34f4-4be0-908f-657e43f671b0)

### Known Issue
- Scrubbing causes text to be highlighted, ~~starting a scrub from
highlighted text will instead drag the text~~.
- It seems this can only be prevented with `pointerdown.prevent`, but
this requires a manual `input.focus()` which does not place the cursor
at location of mouse click.

(Obligatory: _It won't do you a bit of good to review math_)

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-7759-Implement-vue-math-2d46d73d365081b9acd4d6422669016e)
by [Unito](https://www.unito.io)

---------

Co-authored-by: github-actions <github-actions@github.com>
Co-authored-by: DrJKL <DrJKL0424@gmail.com>
This commit is contained in:
AustinMroz
2026-01-13 15:11:33 -08:00
committed by GitHub
parent 4b2e4c59af
commit 97a78f4a35
28 changed files with 217 additions and 191 deletions

View File

@@ -8,3 +8,18 @@ import type { IWidgetOptions } from '@/lib/litegraph/src/types/widgets'
export function getWidgetStep(options: IWidgetOptions<unknown>): number {
return options.step2 || (options.step || 10) * 0.1
}
export function evaluateInput(input: string): number | undefined {
// Check if v is a valid equation or a number
if (/^[\d\s.()*+/-]+$/.test(input)) {
// Solve the equation if possible
try {
input = eval(input)
} catch {
// Ignore eval errors
}
}
const newValue = Number(input)
if (isNaN(newValue)) return undefined
return newValue
}

View File

@@ -1,5 +1,5 @@
import type { INumericWidget } from '@/lib/litegraph/src/types/widgets'
import { getWidgetStep } from '@/lib/litegraph/src/utils/widget'
import { evaluateInput, getWidgetStep } from '@/lib/litegraph/src/utils/widget'
import { BaseSteppedWidget } from './BaseSteppedWidget'
import type { WidgetEventOptions } from './BaseWidget'
@@ -68,19 +68,8 @@ export class NumberWidget
'Value',
this.value,
(v: string) => {
// Check if v is a valid equation or a number
if (/^[\d\s()*+/-]+|\d+\.\d+$/.test(v)) {
// Solve the equation if possible
try {
v = eval(v)
} catch {
// Ignore eval errors
}
}
const newValue = Number(v)
if (!isNaN(newValue)) {
this.setValue(newValue, { e, node, canvas })
}
const parsed = evaluateInput(v)
if (parsed !== undefined) this.setValue(parsed, { e, node, canvas })
},
e
)