diff --git a/packages/editor/package.json b/packages/editor/package.json index 02ead606..481ab352 100644 --- a/packages/editor/package.json +++ b/packages/editor/package.json @@ -26,6 +26,7 @@ "@dnd-kit/utilities": "^3.2.2", "@iconify/react": "^6.0.2", "@number-flow/react": "^0.6.0", + "@pascal-app/lingo": "^0.1.0", "@radix-ui/react-alert-dialog": "^1.1.15", "@radix-ui/react-context-menu": "^2.2.16", "@radix-ui/react-dialog": "^1.1.15", diff --git a/packages/editor/src/components/ui/controls/metric-control.tsx b/packages/editor/src/components/ui/controls/metric-control.tsx index 1ce1f5fc..f9336eb7 100644 --- a/packages/editor/src/components/ui/controls/metric-control.tsx +++ b/packages/editor/src/components/ui/controls/metric-control.tsx @@ -3,6 +3,11 @@ import { useScene } from '@pascal-app/core' import { useViewer } from '@pascal-app/viewer' import { useCallback, useEffect, useRef, useState } from 'react' +import { + lingoUnitSpec, + measurementHint, + parseMeasurement, +} from '../../../lib/measurement-parser' import { getLinearUnitLabel, linearUnitToMeters, @@ -229,14 +234,46 @@ export function MetricControl({ }, []) const submitValue = useCallback(() => { - const numValue = Number.parseFloat(inputValue) - if (Number.isNaN(numValue)) { + const spec = lingoUnitSpec(unit) + let stored = spec + ? parseMeasurement(inputValue, spec, { + bareUnit: isImperial ? 'ft' : spec.unitId, + system: isImperial ? 'us' : 'metric', + }) + : null + if (stored === null) { + const numValue = Number.parseFloat(inputValue) + stored = Number.isFinite(numValue) ? toStoredValue(numValue) : null + } + if (stored === null) { setInputValue(toDisplayValue(value).toFixed(precision)) } else { - applyCommittedValue(clamp(toStoredValue(numValue))) + applyCommittedValue(clamp(stored)) } setIsEditing(false) - }, [inputValue, applyCommittedValue, clamp, toStoredValue, value, precision, toDisplayValue]) + }, [ + inputValue, + unit, + isImperial, + applyCommittedValue, + clamp, + toStoredValue, + value, + precision, + toDisplayValue, + ]) + + const spec = lingoUnitSpec(unit) + const hint = + isEditing && spec + ? measurementHint(inputValue, spec, { + bareUnit: isImperial ? 'ft' : spec.unitId, + system: isImperial ? 'us' : 'metric', + displayUnit: isImperial ? 'ft' : spec.unitId, + precision, + clamp, + }) + : null const handleInputBlur = useCallback(() => { submitValue() @@ -290,6 +327,11 @@ export function MetricControl({