KQ-1143 · MEASURE/LINE
Measure Line
A plan you measure by dragging: the finger draws a dimension line with end bars, a ruler of ticks and a live length label in real units that stays upright at any angle, hopping over the line on the snap spring when it swings through vertical. The end follows 1:1, catches corners and the ends of other lines, rubber-bands past the sheet and springs back on snap with the release velocity, and every tick the length crosses ratchets. The keyboard walks a cursor corner to corner, Enter anchors a line, the arrows carry its end on the flick spring with the same ratchet, and after any line the arrows adjust its last point.
Drag across the plan to measure. From the keyboard, the arrow keys move a cursor between corners; Enter starts a line, the arrows carry its end, and Enter finishes it. After a line, the arrows adjust its last point. Backspace removes the newest line.
flat 4b · 1:50 · drag across the plan to measure
Install
One command — the source lands in your repo. Or copy it from the Code tab.
$ pnpm dlx shadcn@latest add @kinetiq/measure-line
Props
- width
- number
- default —
- The sheet's width in drawing units (millimetres on paper, say). Lines and corners are in these units.
- height
- number
- default —
- The sheet's height in drawing units.
- children
- React.ReactNode
- default —
- The plan: SVG elements in drawing units, drawn over a scale grid and under the lines.
- corners
- [number, number][]
- default []
- Points the ends snap to — wall corners, door jambs — in drawing units. The ends of lines already drawn are snap points too.
- label
- string
- default —
- The plan's accessible name.
- value / defaultValue
- { id: string; a: [number, number]; b: [number, number] }[]
- default []
- The lines, each from a to b in drawing units.
- onValueChange
- (lines: MeasureLineSegment[]) => void
- default —
- Fires from the drag, key or tap that changed the lines. Controlled, a refused change puts the live end back where the host says it is.
- units
- "m" | "cm" | "ft"
- default "m"
- How lengths read ("3.42 m", "342 cm", "11′ 3″"), and the spacing of the ticks and the grid.
- snap
- boolean
- default true
- Ends catch corners and the ends of other lines within 14px, with a catch ring and a snap; the keyboard cursor jumps corner to corner.
- scale
- number
- default 50
- The drawing's scale, 1:n: one drawing unit is n real ones. The same line reads longer at 1:100, and ticks and grid re-space.
- keep
- boolean
- default true
- Keep every line (six at most, the oldest goes first), or let each new line replace the last.
- sound
- boolean
- default false
- Play the ratchet (a detent per tick crossed, rising with the length, louder on long ticks) and the snap as an end catches. Nothing plays, and no audio context exists, unless this is on.
- disabled
- boolean
- default false
- Blocks drawing and removing, and takes the plan out of the tab order.
- className
- string
- default —
- Merged onto the wrapper's classes.
| Prop | Type | Default | Description |
|---|---|---|---|
| width | number | — | The sheet's width in drawing units (millimetres on paper, say). Lines and corners are in these units. |
| height | number | — | The sheet's height in drawing units. |
| children | React.ReactNode | — | The plan: SVG elements in drawing units, drawn over a scale grid and under the lines. |
| corners | [number, number][] | [] | Points the ends snap to — wall corners, door jambs — in drawing units. The ends of lines already drawn are snap points too. |
| label | string | — | The plan's accessible name. |
| value / defaultValue | { id: string; a: [number, number]; b: [number, number] }[] | [] | The lines, each from a to b in drawing units. |
| onValueChange | (lines: MeasureLineSegment[]) => void | — | Fires from the drag, key or tap that changed the lines. Controlled, a refused change puts the live end back where the host says it is. |
| units | "m" | "cm" | "ft" | "m" | How lengths read ("3.42 m", "342 cm", "11′ 3″"), and the spacing of the ticks and the grid. |
| snap | boolean | true | Ends catch corners and the ends of other lines within 14px, with a catch ring and a snap; the keyboard cursor jumps corner to corner. |
| scale | number | 50 | The drawing's scale, 1:n: one drawing unit is n real ones. The same line reads longer at 1:100, and ticks and grid re-space. |
| keep | boolean | true | Keep every line (six at most, the oldest goes first), or let each new line replace the last. |
| sound | boolean | false | Play the ratchet (a detent per tick crossed, rising with the length, louder on long ticks) and the snap as an end catches. Nothing plays, and no audio context exists, unless this is on. |
| disabled | boolean | false | Blocks drawing and removing, and takes the plan out of the tab order. |
| className | string | — | Merged onto the wrapper's classes. |