diff --git a/packages/editor/src/components/ui/controls/metric-control.tsx b/packages/editor/src/components/ui/controls/metric-control.tsx
index e48e398802..797ea8e835 100644
--- a/packages/editor/src/components/ui/controls/metric-control.tsx
+++ b/packages/editor/src/components/ui/controls/metric-control.tsx
@@ -2,11 +2,7 @@
import { useScene } from '@pascal-app/core'
import { useCallback, useEffect, useRef, useState } from 'react'
-import {
- lingoUnitSpec,
- measurementHint,
- parseMeasurement,
-} from '../../../lib/measurement-parser'
+import { lingoUnitSpec, measurementHint, parseMeasurement } from '../../../lib/measurement-parser'
import { useLinearDisplay } from '../../../lib/use-linear-display'
import { cn } from '../../../lib/utils'
@@ -31,8 +27,8 @@ export function MetricControl({
onCommit,
min = Number.NEGATIVE_INFINITY,
max = Number.POSITIVE_INFINITY,
- precision = 2,
- step = 1,
+ precision: storedPrecision = 2,
+ step: storedStep = 1,
className,
unit = '',
restoreOnCommit = true,
@@ -40,9 +36,12 @@ export function MetricControl({
const {
isImperial,
displayUnit,
+ parseUnit,
+ precision,
+ step,
toDisplay: toDisplayValue,
toStored: toStoredValue,
- } = useLinearDisplay(unit, precision)
+ } = useLinearDisplay(unit, storedPrecision, storedStep)
const clamp = useCallback(
(val: number) => {
@@ -110,7 +109,14 @@ export function MetricControl({
container.addEventListener('wheel', handleWheel, { passive: false })
return () => container.removeEventListener('wheel', handleWheel)
- }, [isEditing, step, clamp, applyCommittedValue, toStoredValue, roundStoredValueForDisplayPrecision])
+ }, [
+ isEditing,
+ step,
+ clamp,
+ applyCommittedValue,
+ toStoredValue,
+ roundStoredValueForDisplayPrecision,
+ ])
useEffect(() => {
if (!isHovered || isEditing) return
@@ -226,7 +232,7 @@ export function MetricControl({
const spec = lingoUnitSpec(unit)
let stored = spec
? parseMeasurement(inputValue, spec, {
- bareUnit: isImperial ? 'ft' : spec.unitId,
+ bareUnit: parseUnit ?? spec.unitId,
system: isImperial ? 'us' : 'metric',
})
: null
@@ -244,6 +250,7 @@ export function MetricControl({
inputValue,
unit,
isImperial,
+ parseUnit,
applyCommittedValue,
clamp,
toStoredValue,
@@ -256,9 +263,9 @@ export function MetricControl({
const hint =
isEditing && spec
? measurementHint(inputValue, spec, {
- bareUnit: isImperial ? 'ft' : spec.unitId,
+ bareUnit: parseUnit ?? spec.unitId,
system: isImperial ? 'us' : 'metric',
- displayUnit: isImperial ? 'ft' : spec.unitId,
+ displayUnit: parseUnit ?? spec.unitId,
precision,
clamp,
})
@@ -287,7 +294,16 @@ export function MetricControl({
setInputValue(toDisplayValue(newV).toFixed(precision))
}
},
- [submitValue, value, toDisplayValue, precision, step, clamp, applyCommittedValue, toStoredValue],
+ [
+ submitValue,
+ value,
+ toDisplayValue,
+ precision,
+ step,
+ clamp,
+ applyCommittedValue,
+ toStoredValue,
+ ],
)
return (
diff --git a/packages/editor/src/components/ui/controls/slider-control.tsx b/packages/editor/src/components/ui/controls/slider-control.tsx
index a3c5d06d70..e89b84f17f 100644
--- a/packages/editor/src/components/ui/controls/slider-control.tsx
+++ b/packages/editor/src/components/ui/controls/slider-control.tsx
@@ -2,11 +2,7 @@
import { useScene } from '@pascal-app/core'
import { useCallback, useEffect, useRef, useState } from 'react'
-import {
- lingoUnitSpec,
- measurementHint,
- parseMeasurement,
-} from '../../../lib/measurement-parser'
+import { lingoUnitSpec, measurementHint, parseMeasurement } from '../../../lib/measurement-parser'
import { useLinearDisplay } from '../../../lib/use-linear-display'
import { cn } from '../../../lib/utils'
@@ -60,19 +56,16 @@ export function SliderControl({
onCommit,
min = Number.NEGATIVE_INFINITY,
max = Number.POSITIVE_INFINITY,
- precision = 0,
- step = 1,
+ precision: storedPrecision = 0,
+ step: storedStep = 1,
className,
unit = '',
restoreOnCommit = true,
mixed = false,
}: SliderControlProps) {
- // Display/storage conversion so the value honors the metric/imperial toggle.
- // `value`, `onChange`, `onCommit`, `min`/`max`/`clamp` are always in the
- // stored unit (meters for `unit === 'm'`); the step, drag deltas, text field
- // and rendered number are in the DISPLAY unit (feet when imperial). For
- // metric and non-length units these conversions are the identity.
- const { isImperial, displayUnit, toDisplay, toStored } = useLinearDisplay(unit, precision)
+ // Values and bounds stay in meters; gestures and input use the displayed unit.
+ const { isImperial, displayUnit, parseUnit, precision, step, toDisplay, toStored } =
+ useLinearDisplay(unit, storedPrecision, storedStep)
const [isEditing, setIsEditing] = useState(false)
const [isDragging, setIsDragging] = useState(false)
@@ -106,7 +99,9 @@ export function SliderControl({
(storedValue: number, displayDelta: number, displayStep: number) =>
clamp(
toStored(
- Number.parseFloat((toDisplay(storedValue) + displayDelta).toFixed(stepPrecision(displayStep))),
+ Number.parseFloat(
+ (toDisplay(storedValue) + displayDelta).toFixed(stepPrecision(displayStep)),
+ ),
),
),
[clamp, toDisplay, toStored],
@@ -231,7 +226,7 @@ export function SliderControl({
const spec = lingoUnitSpec(unit)
let stored = spec
? parseMeasurement(inputValue, spec, {
- bareUnit: isImperial ? 'ft' : spec.unitId,
+ bareUnit: parseUnit ?? spec.unitId,
system: isImperial ? 'us' : 'metric',
})
: null
@@ -248,15 +243,27 @@ export function SliderControl({
onCommit?.(nextValue)
}
setIsEditing(false)
- }, [inputValue, unit, isImperial, onChange, onCommit, clamp, precision, value, toDisplay, toStored])
+ }, [
+ inputValue,
+ unit,
+ isImperial,
+ parseUnit,
+ onChange,
+ onCommit,
+ clamp,
+ precision,
+ value,
+ toDisplay,
+ toStored,
+ ])
const spec = lingoUnitSpec(unit)
const hint =
isEditing && spec
? measurementHint(inputValue, spec, {
- bareUnit: isImperial ? 'ft' : spec.unitId,
+ bareUnit: parseUnit ?? spec.unitId,
system: isImperial ? 'us' : 'metric',
- displayUnit: isImperial ? 'ft' : spec.unitId,
+ displayUnit: parseUnit ?? spec.unitId,
precision,
clamp,
})
diff --git a/packages/editor/src/components/ui/floating-level-selector.tsx b/packages/editor/src/components/ui/floating-level-selector.tsx
index 7e88c4af06..de3eaec260 100644
--- a/packages/editor/src/components/ui/floating-level-selector.tsx
+++ b/packages/editor/src/components/ui/floating-level-selector.tsx
@@ -145,11 +145,14 @@ function LevelRow({
const [duplicateDialogOpen, setDuplicateDialogOpen] = useState(false)
const [isEditing, setIsEditing] = useState(false)
const updateNode = useScene((s) => s.updateNode)
- const { isImperial, toDisplay, displayUnit } = useLinearDisplay('m', 2)
+ const { isImperial, toDisplay, displayUnit, precision: displayPrecision } = useLinearDisplay('m', 2)
const storeyHeight = getStoredLevelHeight(level)
- // toFixed(2) + strip one trailing zero: "2.50" → "2.5", "2.75" stays.
- const storeyHeightLabel = `${toDisplay(storeyHeight).toFixed(2).replace(/0$/, '')} ${displayUnit}`
+ // Decimal units keep the compact readout; integer millimeters must retain trailing zeroes.
+ const formattedStoreyHeight = toDisplay(storeyHeight).toFixed(displayPrecision)
+ const storeyHeightLabel = `${
+ displayPrecision > 0 ? formattedStoreyHeight.replace(/0$/, '') : formattedStoreyHeight
+ } ${displayUnit}`
// Same rule as the site panel and command palette: the ordinal-0 ground
// floor is the vertical model's zero anchor and must never be deletable.
const canDeleteLevel = level.level !== 0
@@ -244,7 +247,7 @@ function LevelRow({
precision={3}
step={0.1}
unit="m"
- value={Math.round(storeyHeight * 1000) / 1000}
+ value={storeyHeight}
/>
{heightPresets.map((preset) => (
diff --git a/packages/editor/src/components/ui/panels/multi-parametric-inspector.tsx b/packages/editor/src/components/ui/panels/multi-parametric-inspector.tsx
index 7246aab6f4..bab0b2ace8 100644
--- a/packages/editor/src/components/ui/panels/multi-parametric-inspector.tsx
+++ b/packages/editor/src/components/ui/panels/multi-parametric-inspector.tsx
@@ -254,7 +254,7 @@ function MultiVec3Field({
restoreOnCommit={false}
step={0.05}
unit="m"
- value={Math.round(axisValue * 100) / 100}
+ value={axisValue}
/>
)
})}
diff --git a/packages/editor/src/components/ui/panels/parametric-field-control.tsx b/packages/editor/src/components/ui/panels/parametric-field-control.tsx
index 4defaeeccf..4dc18ee7ee 100644
--- a/packages/editor/src/components/ui/panels/parametric-field-control.tsx
+++ b/packages/editor/src/components/ui/panels/parametric-field-control.tsx
@@ -159,7 +159,7 @@ export function ParametricFieldControl({
restoreOnCommit={!onCommit}
step={0.05}
unit="m"
- value={Math.round(axisValue * 100) / 100}
+ value={axisValue}
/>
)
})}
diff --git a/packages/editor/src/components/ui/panels/reference-panel.tsx b/packages/editor/src/components/ui/panels/reference-panel.tsx
index 86da5ccd89..e18df87827 100644
--- a/packages/editor/src/components/ui/panels/reference-panel.tsx
+++ b/packages/editor/src/components/ui/panels/reference-panel.tsx
@@ -376,7 +376,7 @@ export function ReferencePanel() {
precision={2}
step={0.1}
unit="m"
- value={Math.round(node.position[0] * 100) / 100}
+ value={node.position[0]}
/>
diff --git a/packages/editor/src/components/ui/sidebar/panels/site-panel/index.tsx b/packages/editor/src/components/ui/sidebar/panels/site-panel/index.tsx
index 7520477e95..d05658b63c 100644
--- a/packages/editor/src/components/ui/sidebar/panels/site-panel/index.tsx
+++ b/packages/editor/src/components/ui/sidebar/panels/site-panel/index.tsx
@@ -949,7 +949,7 @@ const LevelItem = memo(function LevelItem({
precision={2}
step={0.05}
unit="m"
- value={Math.round((level.baseElevation ?? 0) * 100) / 100}
+ value={(level.baseElevation ?? 0)}
/>
{
+ test('keeps meter storage while displaying and accepting millimeters', () => {
+ const display = getLinearDisplay('m', 'metric', 'millimeters', 2, 0.05)
+ expect(display.displayUnit).toBe('mm')
+ expect(display.parseUnit).toBe('mm')
+ expect(display.toDisplay(2.5)).toBe(2500)
+ expect(display.toStored(1800)).toBe(1.8)
+ expect(display.toStored(-250)).toBe(-0.25)
+ expect(display.precision).toBe(0)
+ expect(display.step).toBe(50)
+ expect(display.toStored(display.step)).toBe(0.05)
+ })
+
+ test('retains sub-millimeter precision when the field supports it', () => {
+ const display = getLinearDisplay('m', 'metric', 'millimeters', 4, 0.0001)
+ expect(display.precision).toBe(1)
+ expect(display.step).toBe(0.1)
+ expect(display.toDisplay(0.0125)).toBe(12.5)
+ expect(display.roundStored(0.01254)).toBe(0.0125)
+ })
+
+ test('imperial preference takes precedence over the saved metric notation', () => {
+ const display = getLinearDisplay('m', 'imperial', 'millimeters', 2, 0.05)
+ expect(display.displayUnit).toBe('ft')
+ expect(display.parseUnit).toBe('ft')
+ expect(display.toDisplay(0.9144)).toBeCloseTo(3, 10)
+ expect(display.toStored(7)).toBeCloseTo(2.1336, 10)
+ expect(display.precision).toBe(2)
+ expect(display.step).toBe(0.05)
+ })
+
+ test('switching notation round-trips the same stored dimensions', () => {
+ for (const stored of [0, 0.01, 0.125, 0.9, 2.1, -0.25]) {
+ for (const [unit, notation] of [
+ ['metric', 'meters'],
+ ['metric', 'millimeters'],
+ ['imperial', 'meters'],
+ ] as const) {
+ const display = getLinearDisplay('m', unit, notation, 2, 0.01)
+ expect(display.toStored(display.toDisplay(stored))).toBeCloseTo(stored, 12)
+ }
+ }
+ })
+
+ test('leaves non-meter fields and their gesture steps unchanged', () => {
+ for (const unit of ['°', 'rad', '%', '', 'in', 'cm']) {
+ const display = getLinearDisplay(unit, 'metric', 'millimeters', 2, 0.05)
+ expect(display.displayUnit).toBe(unit)
+ expect(display.parseUnit).toBeUndefined()
+ expect(display.toDisplay(12.5)).toBe(12.5)
+ expect(display.toStored(12.5)).toBe(12.5)
+ expect(display.precision).toBe(2)
+ expect(display.step).toBe(0.05)
+ }
+ })
+})
diff --git a/packages/editor/src/lib/linear-display.ts b/packages/editor/src/lib/linear-display.ts
new file mode 100644
index 0000000000..a2fd50e352
--- /dev/null
+++ b/packages/editor/src/lib/linear-display.ts
@@ -0,0 +1,39 @@
+import {
+ getLinearUnitLabel,
+ type LinearUnit,
+ linearUnitToMeters,
+ type MetricNotation,
+ metersToLinearUnit,
+} from './measurements'
+
+export function getLinearDisplay(
+ unit: string,
+ viewerUnit: LinearUnit,
+ metricNotation: MetricNotation,
+ precision: number,
+ step: number,
+) {
+ const isImperial = unit === 'm' && viewerUnit === 'imperial'
+ const isMillimeters = unit === 'm' && viewerUnit === 'metric' && metricNotation === 'millimeters'
+ const displayUnit = isImperial ? getLinearUnitLabel('imperial') : isMillimeters ? 'mm' : unit
+ const displayPrecision = isMillimeters ? Math.max(0, precision - 3) : precision
+ const displayStep = isMillimeters ? step * 1000 : step
+ const parseUnit = isImperial ? 'ft' : isMillimeters ? 'mm' : undefined
+ const toDisplay = (stored: number) =>
+ isImperial ? metersToLinearUnit(stored, 'imperial') : isMillimeters ? stored * 1000 : stored
+ const toStored = (display: number) =>
+ isImperial ? linearUnitToMeters(display, 'imperial') : isMillimeters ? display / 1000 : display
+ const roundStored = (stored: number) =>
+ toStored(Number.parseFloat(toDisplay(stored).toFixed(displayPrecision)))
+
+ return {
+ isImperial,
+ displayUnit,
+ parseUnit,
+ precision: displayPrecision,
+ step: displayStep,
+ toDisplay,
+ toStored,
+ roundStored,
+ }
+}
diff --git a/packages/editor/src/lib/use-linear-display.ts b/packages/editor/src/lib/use-linear-display.ts
index 6578ea30a3..f7512903df 100644
--- a/packages/editor/src/lib/use-linear-display.ts
+++ b/packages/editor/src/lib/use-linear-display.ts
@@ -1,40 +1,16 @@
'use client'
import { useViewer } from '@pascal-app/viewer'
-import { useCallback } from 'react'
-import { getLinearUnitLabel, linearUnitToMeters, metersToLinearUnit } from './measurements'
+import { useMemo } from 'react'
+import { getLinearDisplay } from './linear-display'
-/**
- * Shared display/storage conversion for numeric property controls so that
- * every length input honors the metric/imperial toggle identically.
- *
- * Values are always STORED in the field's own unit (meters for `unit === 'm'`).
- * When the viewer preference is imperial AND the field is a meter length, the
- * value is DISPLAYED (and edited) in feet; otherwise the conversions are the
- * identity, so metric fields and non-length units (`'°'`, `'%'`, `'in'`, `''`,
- * …) behave exactly as before.
- *
- * Used by both `SliderControl` and `MetricControl` — keep the two in sync via
- * this single source of truth.
- */
-export function useLinearDisplay(unit: string, precision: number) {
+/** Shared display/input conversion; values and bounds stay in the stored unit. */
+export function useLinearDisplay(unit: string, precision: number, step = 1) {
const viewerUnit = useViewer((state) => state.unit)
- const isImperial = viewerUnit === 'imperial' && unit === 'm'
- const displayUnit = isImperial ? getLinearUnitLabel('imperial') : unit
+ const metricNotation = useViewer((state) => state.metricNotation)
- const toDisplay = useCallback(
- (stored: number) => (isImperial ? metersToLinearUnit(stored, 'imperial') : stored),
- [isImperial],
+ return useMemo(
+ () => getLinearDisplay(unit, viewerUnit, metricNotation, precision, step),
+ [unit, viewerUnit, metricNotation, precision, step],
)
- const toStored = useCallback(
- (display: number) => (isImperial ? linearUnitToMeters(display, 'imperial') : display),
- [isImperial],
- )
- // Round a stored value so it lands on a clean number of DISPLAY-unit digits.
- const roundStored = useCallback(
- (stored: number) => toStored(Number.parseFloat(toDisplay(stored).toFixed(precision))),
- [toDisplay, toStored, precision],
- )
-
- return { isImperial, displayUnit, toDisplay, toStored, roundStored }
}
diff --git a/packages/nodes/src/box-vent/panel.tsx b/packages/nodes/src/box-vent/panel.tsx
index 537496152f..bb6a757eda 100644
--- a/packages/nodes/src/box-vent/panel.tsx
+++ b/packages/nodes/src/box-vent/panel.tsx
@@ -193,7 +193,7 @@ export default function BoxVentPanel() {
restoreOnCommit={false}
step={0.01}
unit="m"
- value={Math.round(node.width * 100) / 100}
+ value={node.width}
/>
{/* Hood Overhang is `cap`-only — the dome shape rolls down to
the body footprint without a flange skirt, and `box` doesn't
@@ -234,7 +234,7 @@ export default function BoxVentPanel() {
restoreOnCommit={false}
step={0.005}
unit="m"
- value={Math.round((node.hoodOverhang ?? 0) * 1000) / 1000}
+ value={node.hoodOverhang ?? 0}
/>
)}
{node.style === 'box' && (
@@ -249,7 +249,7 @@ export default function BoxVentPanel() {
restoreOnCommit={false}
step={0.005}
unit="m"
- value={Math.round((node.baseInset ?? 0.06) * 1000) / 1000}
+ value={node.baseInset ?? 0.06}
/>
>
)}
@@ -292,7 +292,7 @@ export default function BoxVentPanel() {
restoreOnCommit={false}
step={0.005}
unit="m"
- value={Math.round((node.capHeight ?? 0.07) * 1000) / 1000}
+ value={node.capHeight ?? 0.07}
/>
>
)}
@@ -369,7 +369,7 @@ export default function BoxVentPanel() {
restoreOnCommit={false}
step={0.05}
unit="m"
- value={Math.round((node.position[0] ?? 0) * 100) / 100}
+ value={node.position[0] ?? 0}
/>
)}
diff --git a/packages/nodes/src/chimney/panel.tsx b/packages/nodes/src/chimney/panel.tsx
index d706dbd5e8..d97af04fe7 100644
--- a/packages/nodes/src/chimney/panel.tsx
+++ b/packages/nodes/src/chimney/panel.tsx
@@ -377,7 +377,7 @@ export default function ChimneyPanel() {
restoreOnCommit={false}
step={0.05}
unit="m"
- value={Math.round(node.width * 100) / 100}
+ value={node.width}
/>
{(node.bodyShape ?? 'square') !== 'round' && (
)}
{(node.bodyShape ?? 'square') !== 'round' && (
)}
@@ -444,7 +444,7 @@ export default function ChimneyPanel() {
restoreOnCommit={false}
step={0.1}
unit="m"
- value={Math.round(node.heightAboveRidge * 100) / 100}
+ value={node.heightAboveRidge}
/>
@@ -478,7 +478,7 @@ export default function ChimneyPanel() {
restoreOnCommit={false}
step={0.05}
unit="m"
- value={Math.round(worldX_now * 100) / 100}
+ value={worldX_now}
/>
>
)}
@@ -620,7 +620,7 @@ export default function ChimneyPanel() {
restoreOnCommit={false}
step={0.05}
unit="m"
- value={Math.round((node.shoulderHeight ?? 0.5) * 100) / 100}
+ value={node.shoulderHeight ?? 0.5}
/>
>
)}
@@ -673,7 +673,7 @@ export default function ChimneyPanel() {
restoreOnCommit={false}
step={0.01}
unit="m"
- value={Math.round((node.flueDiameter ?? 0.22) * 100) / 100}
+ value={node.flueDiameter ?? 0.22}
/>
{(node.flueCount ?? 1) > 1 && (
>
)}
@@ -741,7 +741,7 @@ export default function ChimneyPanel() {
restoreOnCommit={false}
step={0.01}
unit="m"
- value={Math.round((node.bandHeight ?? 0.1) * 100) / 100}
+ value={node.bandHeight ?? 0.1}
/>
>
)}
@@ -804,7 +804,7 @@ export default function ChimneyPanel() {
restoreOnCommit={false}
step={0.05}
unit="m"
- value={Math.round((node.cricketLength ?? 0.6) * 100) / 100}
+ value={node.cricketLength ?? 0.6}
/>
>
)}
@@ -846,7 +846,7 @@ export default function ChimneyPanel() {
restoreOnCommit={false}
step={0.005}
unit="m"
- value={Math.round((node.panelDepth ?? 0.03) * 1000) / 1000}
+ value={node.panelDepth ?? 0.03}
/>
>
)}
diff --git a/packages/nodes/src/cupola/panel.tsx b/packages/nodes/src/cupola/panel.tsx
index 2d5913a341..bc2aead4db 100644
--- a/packages/nodes/src/cupola/panel.tsx
+++ b/packages/nodes/src/cupola/panel.tsx
@@ -173,7 +173,7 @@ export default function CupolaPanel() {
restoreOnCommit={false}
step={0.05}
unit="m"
- value={Math.round(node.width * 100) / 100}
+ value={node.width}
/>
@@ -216,7 +216,7 @@ export default function CupolaPanel() {
restoreOnCommit={false}
step={0.05}
unit="m"
- value={Math.round((node.position[0] ?? 0) * 100) / 100}
+ value={node.position[0] ?? 0}
/>
{showFlipSide && (
@@ -726,7 +726,7 @@ export default function DoorPanel() {
restoreOnCommit={false}
step={0.05}
unit="m"
- value={Math.round(node.width * 100) / 100}
+ value={node.width}
/>
@@ -799,7 +799,7 @@ export default function DoorPanel() {
precision={2}
step={0.05}
unit="m"
- value={Math.round(cornerRadius * 100) / 100}
+ value={cornerRadius}
/>
) : (
<>
@@ -817,7 +817,7 @@ export default function DoorPanel() {
precision={2}
step={0.05}
unit="m"
- value={Math.round((openingTopRadii[index as number] ?? 0) * 100) / 100}
+ value={openingTopRadii[index as number] ?? 0}
/>
))}
>
@@ -831,7 +831,7 @@ export default function DoorPanel() {
precision={3}
step={0.005}
unit="m"
- value={Math.round(openingRevealRadius * 1000) / 1000}
+ value={openingRevealRadius}
/>
>
)}
@@ -845,7 +845,7 @@ export default function DoorPanel() {
restoreOnCommit={false}
step={0.05}
unit="m"
- value={Math.round(archHeight * 100) / 100}
+ value={archHeight}
/>
)}
@@ -896,7 +896,7 @@ export default function DoorPanel() {
precision={2}
step={0.05}
unit="m"
- value={Math.round(cornerRadius * 100) / 100}
+ value={cornerRadius}
/>
) : (
<>
@@ -914,7 +914,7 @@ export default function DoorPanel() {
precision={2}
step={0.05}
unit="m"
- value={Math.round((openingTopRadii[index as number] ?? 0) * 100) / 100}
+ value={openingTopRadii[index as number] ?? 0}
/>
))}
>
@@ -928,7 +928,7 @@ export default function DoorPanel() {
precision={3}
step={0.005}
unit="m"
- value={Math.round(openingRevealRadius * 1000) / 1000}
+ value={openingRevealRadius}
/>
>
)}
@@ -942,7 +942,7 @@ export default function DoorPanel() {
restoreOnCommit={false}
step={0.05}
unit="m"
- value={Math.round(archHeight * 100) / 100}
+ value={archHeight}
/>
)}
@@ -960,7 +960,7 @@ export default function DoorPanel() {
precision={3}
step={0.01}
unit="m"
- value={Math.round(node.frameThickness * 1000) / 1000}
+ value={node.frameThickness}
/>
)}
@@ -985,7 +985,7 @@ export default function DoorPanel() {
precision={3}
step={0.005}
unit="m"
- value={Math.round(node.contentPadding[0] * 1000) / 1000}
+ value={node.contentPadding[0]}
/>
)}
@@ -1052,7 +1052,7 @@ export default function DoorPanel() {
precision={3}
step={0.005}
unit="m"
- value={Math.round(node.thresholdHeight * 1000) / 1000}
+ value={node.thresholdHeight}
/>
)}
@@ -1078,7 +1078,7 @@ export default function DoorPanel() {
precision={2}
step={0.05}
unit="m"
- value={Math.round(node.handleHeight * 100) / 100}
+ value={node.handleHeight}
/>
{supportsHandleSide && (
@@ -1122,7 +1122,7 @@ export default function DoorPanel() {
precision={2}
step={0.05}
unit="m"
- value={Math.round(node.panicBarHeight * 100) / 100}
+ value={node.panicBarHeight}
/>
)}
@@ -1211,7 +1211,7 @@ export default function DoorPanel() {
precision={3}
step={0.005}
unit="m"
- value={Math.round(seg.dividerThickness * 1000) / 1000}
+ value={seg.dividerThickness}
/>
)}
@@ -1231,7 +1231,7 @@ export default function DoorPanel() {
precision={3}
step={0.005}
unit="m"
- value={Math.round(seg.panelInset * 1000) / 1000}
+ value={seg.panelInset}
/>
)}
diff --git a/packages/nodes/src/dormer/panel-position-section.tsx b/packages/nodes/src/dormer/panel-position-section.tsx
index 545d55f15f..a2f95ee440 100644
--- a/packages/nodes/src/dormer/panel-position-section.tsx
+++ b/packages/nodes/src/dormer/panel-position-section.tsx
@@ -180,7 +180,7 @@ export function DormerPositionSection({
restoreOnCommit={false}
step={0.05}
unit="m"
- value={Math.round(worldX_now * 100) / 100}
+ value={worldX_now}
/>
diff --git a/packages/nodes/src/eyebrow-vent/panel.tsx b/packages/nodes/src/eyebrow-vent/panel.tsx
index 5ced7043e8..7e4c600fab 100644
--- a/packages/nodes/src/eyebrow-vent/panel.tsx
+++ b/packages/nodes/src/eyebrow-vent/panel.tsx
@@ -192,7 +192,7 @@ export default function EyebrowVentPanel() {
restoreOnCommit={false}
step={0.05}
unit="m"
- value={Math.round(node.width * 100) / 100}
+ value={node.width}
/>
@@ -235,7 +235,7 @@ export default function EyebrowVentPanel() {
restoreOnCommit={false}
step={0.05}
unit="m"
- value={Math.round((node.position[0] ?? 0) * 100) / 100}
+ value={node.position[0] ?? 0}
/>
)
}
diff --git a/packages/nodes/src/item/panel.tsx b/packages/nodes/src/item/panel.tsx
index 60f8d93f7b..cffbe56435 100644
--- a/packages/nodes/src/item/panel.tsx
+++ b/packages/nodes/src/item/panel.tsx
@@ -120,7 +120,7 @@ export default function ItemPanel() {
precision={2}
step={0.01}
unit="m"
- value={Math.round(node.position[0] * 100) / 100}
+ value={node.position[0]}
/>
diff --git a/packages/nodes/src/ridge-vent/panel.tsx b/packages/nodes/src/ridge-vent/panel.tsx
index fb8e41b373..1a17150ed1 100644
--- a/packages/nodes/src/ridge-vent/panel.tsx
+++ b/packages/nodes/src/ridge-vent/panel.tsx
@@ -165,7 +165,7 @@ export default function RidgeVentPanel() {
restoreOnCommit={false}
step={0.05}
unit="m"
- value={Math.round(node.length * 100) / 100}
+ value={node.length}
/>
@@ -212,7 +212,7 @@ export default function RidgeVentPanel() {
restoreOnCommit={false}
step={0.05}
unit="m"
- value={Math.round((node.position[0] ?? 0) * 100) / 100}
+ value={node.position[0] ?? 0}
/>
) : (
<>
@@ -409,7 +409,7 @@ export default function RoofSegmentPanel() {
precision={2}
step={0.5}
unit="m"
- value={Math.round(node.width * 100) / 100}
+ value={node.width}
/>
>
)}
@@ -475,7 +475,7 @@ export default function RoofSegmentPanel() {
precision={2}
step={0.1}
unit="m"
- value={Math.round(node.wallHeight * 100) / 100}
+ value={node.wallHeight}
/>
@@ -595,11 +595,7 @@ export default function RoofSegmentPanel() {
precision={2}
step={0.01}
unit="m"
- value={
- Math.round(
- (node.dutchTopRakeThickness ?? ROOF_SHAPE_DEFAULTS.dutchTopRakeThickness) * 100,
- ) / 100
- }
+ value={node.dutchTopRakeThickness ?? ROOF_SHAPE_DEFAULTS.dutchTopRakeThickness}
/>
)}
@@ -625,7 +619,7 @@ export default function RoofSegmentPanel() {
precision={2}
step={0.05}
unit="m"
- value={Math.round(node.wallThickness * 100) / 100}
+ value={node.wallThickness}
/>
@@ -670,7 +664,7 @@ export default function RoofSegmentPanel() {
precision={2}
step={0.05}
unit="m"
- value={Math.round(node.position[0] * 100) / 100}
+ value={node.position[0]}
/>
{(node.roofType !== 'conical' || !conicalCoverage.fullCircle) && (
<>
diff --git a/packages/nodes/src/roof/panel.tsx b/packages/nodes/src/roof/panel.tsx
index ac07a728d1..cfca19a34a 100644
--- a/packages/nodes/src/roof/panel.tsx
+++ b/packages/nodes/src/roof/panel.tsx
@@ -281,7 +281,7 @@ export default function RoofPanel() {
precision={2}
step={0.05}
unit="m"
- value={Math.round(node.position[0] * 100) / 100}
+ value={node.position[0]}
/>
{activeSkylightType === 'lantern' && (
<>
@@ -311,7 +311,7 @@ export default function SkylightPanel() {
restoreOnCommit={false}
step={0.01}
unit="m"
- value={Math.round((node.lanternHeight ?? 0.25) * 1000) / 1000}
+ value={node.lanternHeight ?? 0.25}
/>
)}
>
@@ -419,7 +419,7 @@ export default function SkylightPanel() {
restoreOnCommit={false}
step={0.005}
unit="m"
- value={Math.round((node.trackWidth ?? 0.045) * 1000) / 1000}
+ value={node.trackWidth ?? 0.045}
/>
>
)}
@@ -436,7 +436,7 @@ export default function SkylightPanel() {
restoreOnCommit={false}
step={0.05}
unit="m"
- value={Math.round(node.width * 100) / 100}
+ value={node.width}
/>
@@ -463,7 +463,7 @@ export default function SkylightPanel() {
restoreOnCommit={false}
step={0.005}
unit="m"
- value={Math.round((node.frameThickness ?? 0.05) * 1000) / 1000}
+ value={node.frameThickness ?? 0.05}
/>
@@ -511,7 +511,7 @@ export default function SkylightPanel() {
restoreOnCommit={false}
step={0.005}
unit="m"
- value={Math.round((node.curbHeight ?? 0.1) * 1000) / 1000}
+ value={node.curbHeight ?? 0.1}
/>
)}
@@ -531,7 +531,7 @@ export default function SkylightPanel() {
restoreOnCommit={false}
step={0.05}
unit="m"
- value={Math.round(worldX_now * 100) / 100}
+ value={worldX_now}
/>
{node.recessed ? (
@@ -312,7 +312,7 @@ export function SlabPanel() {
precision={2}
step={0.01}
unit="m"
- value={Math.round(getSlabRecessDepth(node) * 100) / 100}
+ value={getSlabRecessDepth(node)}
/>
) : (
)}
diff --git a/packages/nodes/src/solar-panel/panel.tsx b/packages/nodes/src/solar-panel/panel.tsx
index aa7d7c913d..37aee8e087 100644
--- a/packages/nodes/src/solar-panel/panel.tsx
+++ b/packages/nodes/src/solar-panel/panel.tsx
@@ -255,7 +255,7 @@ export default function SolarPanelPanel() {
restoreOnCommit={false}
step={0.005}
unit="m"
- value={Math.round(num(node.gapX, 0.02) * 1000) / 1000}
+ value={num(node.gapX, 0.02)}
/>
@@ -286,7 +286,7 @@ export default function SolarPanelPanel() {
restoreOnCommit={false}
step={0.05}
unit="m"
- value={Math.round(num(node.panelWidth, 1) * 100) / 100}
+ value={num(node.panelWidth, 1)}
/>
@@ -313,7 +313,7 @@ export default function SolarPanelPanel() {
restoreOnCommit={false}
step={0.005}
unit="m"
- value={Math.round(num(node.frameThickness, 0.04) * 1000) / 1000}
+ value={num(node.frameThickness, 0.04)}
/>
@@ -362,7 +362,7 @@ export default function SolarPanelPanel() {
restoreOnCommit={false}
step={0.005}
unit="m"
- value={Math.round(num(node.standoffHeight, 0.05) * 1000) / 1000}
+ value={num(node.standoffHeight, 0.05)}
/>
diff --git a/packages/nodes/src/spawn/panel.tsx b/packages/nodes/src/spawn/panel.tsx
index de8e49d093..bfdcba9e6d 100644
--- a/packages/nodes/src/spawn/panel.tsx
+++ b/packages/nodes/src/spawn/panel.tsx
@@ -111,7 +111,7 @@ export default function SpawnPanel() {
precision={2}
step={0.01}
unit="m"
- value={Math.round(node.position[0] * 100) / 100}
+ value={node.position[0]}
/>
diff --git a/packages/nodes/src/stair-segment/panel.tsx b/packages/nodes/src/stair-segment/panel.tsx
index daad0fa4b2..5ff957ddc0 100644
--- a/packages/nodes/src/stair-segment/panel.tsx
+++ b/packages/nodes/src/stair-segment/panel.tsx
@@ -166,7 +166,7 @@ export default function StairSegmentPanel() {
precision={2}
step={0.1}
unit="m"
- value={Math.round(node.width * 100) / 100}
+ value={node.width}
/>
{node.segmentType === 'stair' && (
<>
@@ -188,7 +188,7 @@ export default function StairSegmentPanel() {
precision={2}
step={0.1}
unit="m"
- value={Math.round(node.height * 100) / 100}
+ value={node.height}
/>
)}
@@ -237,7 +237,7 @@ export default function StairSegmentPanel() {
precision={2}
step={0.05}
unit="m"
- value={Math.round(node.position[0] * 100) / 100}
+ value={node.position[0]}
/>
) : null}
>
@@ -411,7 +411,7 @@ export default function StairPanel() {
precision={2}
step={0.05}
unit="m"
- value={Math.round((node.topLandingDepth ?? 0.9) * 100) / 100}
+ value={node.topLandingDepth ?? 0.9}
/>
)}
>
@@ -459,7 +459,7 @@ export default function StairPanel() {
precision={2}
step={0.05}
unit="m"
- value={Math.round((node.width ?? 1) * 100) / 100}
+ value={node.width ?? 1}
/>
)}
)}
diff --git a/packages/nodes/src/turbine-vent/panel.tsx b/packages/nodes/src/turbine-vent/panel.tsx
index fc23df3142..50418742d4 100644
--- a/packages/nodes/src/turbine-vent/panel.tsx
+++ b/packages/nodes/src/turbine-vent/panel.tsx
@@ -189,7 +189,7 @@ export default function TurbineVentPanel() {
restoreOnCommit={false}
step={0.01}
unit="m"
- value={Math.round(node.diameter * 100) / 100}
+ value={node.diameter}
/>
{showFlipSide && (
@@ -570,7 +570,7 @@ export default function WindowPanel() {
restoreOnCommit={false}
step={0.1}
unit="m"
- value={Math.round(node.width * 100) / 100}
+ value={node.width}
/>
@@ -631,7 +631,7 @@ export default function WindowPanel() {
precision={2}
step={0.05}
unit="m"
- value={Math.round(cornerRadius * 100) / 100}
+ value={cornerRadius}
/>
) : (
<>
@@ -651,7 +651,7 @@ export default function WindowPanel() {
precision={2}
step={0.05}
unit="m"
- value={Math.round((openingCornerRadii[index as number] ?? 0) * 100) / 100}
+ value={openingCornerRadii[index as number] ?? 0}
/>
))}
>
@@ -665,7 +665,7 @@ export default function WindowPanel() {
precision={3}
step={0.005}
unit="m"
- value={Math.round(openingRevealRadius * 1000) / 1000}
+ value={openingRevealRadius}
/>
)}
@@ -680,7 +680,7 @@ export default function WindowPanel() {
restoreOnCommit={false}
step={0.05}
unit="m"
- value={Math.round(archHeight * 100) / 100}
+ value={archHeight}
/>
)}
@@ -722,7 +722,7 @@ export default function WindowPanel() {
precision={2}
step={0.05}
unit="m"
- value={Math.round(cornerRadius * 100) / 100}
+ value={cornerRadius}
/>
) : (
<>
@@ -742,7 +742,7 @@ export default function WindowPanel() {
precision={2}
step={0.05}
unit="m"
- value={Math.round((openingCornerRadii[index as number] ?? 0) * 100) / 100}
+ value={openingCornerRadii[index as number] ?? 0}
/>
))}
>
@@ -756,7 +756,7 @@ export default function WindowPanel() {
precision={3}
step={0.005}
unit="m"
- value={Math.round(openingRevealRadius * 1000) / 1000}
+ value={openingRevealRadius}
/>
)}
@@ -771,7 +771,7 @@ export default function WindowPanel() {
restoreOnCommit={false}
step={0.05}
unit="m"
- value={Math.round(archHeight * 100) / 100}
+ value={archHeight}
/>
)}
@@ -789,7 +789,7 @@ export default function WindowPanel() {
precision={3}
step={0.01}
unit="m"
- value={Math.round(node.frameThickness * 1000) / 1000}
+ value={node.frameThickness}
/>
)}
@@ -857,7 +857,7 @@ export default function WindowPanel() {
precision={3}
step={0.01}
unit="m"
- value={Math.round((node.columnDividerThickness ?? 0.03) * 1000) / 1000}
+ value={node.columnDividerThickness ?? 0.03}
/>
@@ -890,7 +890,7 @@ export default function WindowPanel() {
precision={3}
step={0.01}
unit="m"
- value={Math.round((node.rowDividerThickness ?? 0.03) * 1000) / 1000}
+ value={node.rowDividerThickness ?? 0.03}
/>
@@ -914,7 +914,7 @@ export default function WindowPanel() {
precision={3}
step={0.01}
unit="m"
- value={Math.round(node.sillDepth * 1000) / 1000}
+ value={node.sillDepth}
/>
)}