NIPE / Caret Geometry

Browser primitive · 0 runtime dependencies

Caret geometry
for the web.

Reliable viewport coordinates for inputs, textareas and editable DOM, with virtual references for floating UI.

npm install @nipe-solutions/caret-geometry

Caret rectPositioned popup

Measured live in your browser. Text stays on this page.

01 / API layers

Start with the smallest layer you need.

1 / Snapshot

getCaretRect()

You need the caret geometry now.

2 / Virtual reference

createCaretVirtualElement()

Another library expects a live getBoundingClientRect() reference.

3 / Observation

observeCaretGeometry()

You need to know when the caret itself changes.

02 / Responsibility boundary

Geometry and positioning are different jobs.

Caret Geometry tracks the caret. Your positioning engine tracks the world around it.

<textarea>
↓ Caret Geometry
Caret rect / virtual reference
↓ Positioning engine
Mention / slash / autocomplete popup

Caret changed

Typing · arrow keys · selection · mouse caret movement · internal input/textarea scroll · composition / IME

Caret Geometry → update

Environment changed

Page or modal scroll · ancestor scroll · window resize · layout shift · floating-content resize · collision / flip / shift

Positioning engine → update

Both feed one updatePosition() function.

03 / Why compose them?

Why doesn’t Floating UI solve this already?

Floating-positioning libraries answer: “Given this reference rectangle, where should the floating element go?” They handle placement, collision, scroll, resize and layout movement.

Inputs and textareas have no native caret element. The browser exposes a value and selection indices—not caretElement.getBoundingClientRect(). Caret Geometry supplies that missing reference.

INPUT ELEMENT
Hello @nich
caret rect
x 248.5 · y 184 · h 20
composes with
Floating UI / Anchored Layer

User types

input → caret moves → observeCaretGeometry() → update

User scrolls a modal

ancestor scroll → positioner auto-update → update

autoUpdate() alone is not enough: typing can move the virtual reference while the textarea, viewport and ancestors stay still. The reverse is also true: caret observation alone cannot see the page move around it.

04 / Correct integration

One live reference. Two update sources.

createCaretVirtualElement() provides live geometry.
observeCaretGeometry() detects caret-local changes.
autoUpdate() detects environmental changes.
computePosition() places the popup.

Read the Floating UI guide

05 / Positioning stress test

Keep it attached.

Type, move the caret, scroll either surface, or change its typography. Cyan is geometry; orange is positioning.

Scroll this container ↓
Environment movement lives here.

Useful in your project?

If Caret Geometry helps you build interfaces around the caret, a GitHub star helps other developers discover it. Explore more tools from NIPE Open Source for your next project.

06 / Responsibility matrix

Caret Geometry deliberately stops at the caret rectangle.

Concern Caret Geometry Positioning / overlay layer
Locate input, textarea or editable caret ✓ —
Typing, selection and internal-control scroll ✓ —
Page/ancestor scroll and layout shift — ✓
Collision, flip and shift — ✓
Portal rendering and interaction semantics — Framework / application

Do I need Caret Geometry?

Popup next to the input box? No. Use the element directly.

Popup next to the caret inside it? Yes.

Need collision, flip or portals? Add a positioning or overlay layer.

Caret anchor
Suggestions