Skip to content

feat(g.Point): add chooseClosestIndex() and string support in update() - #3502

Open
kumilingus wants to merge 5 commits into
clientIO:devfrom
kumilingus:feat/point-choose-closest-index
Open

kumilingus wants to merge 5 commits into
clientIO:devfrom
kumilingus:feat/point-choose-closest-index

Conversation

@kumilingus

@kumilingus kumilingus commented Sep 12, 2026

Copy link
Copy Markdown
Contributor

Summary

  • g.Point#chooseClosestIndex(points) — returns the index of the closest point in points, -1 for an empty array. Useful when the caller needs its own anchor object back rather than a g.Point copy (the chooseClosest() contract). chooseClosest() is now a thin wrapper over it.
  • Zero per-candidate allocation — the loop reuses one scratch Point via update() instead of new Point(points[i]) for every item.
  • g.Point#update() accepts strings'10 20' / '10@20' are parsed the same way the constructor does (shared parsePointString()). Previously update('10 20') silently stored the string as x and 0 as y. Typing widened from PlainPoint to PointInit to match the constructor and runtime.
  • fixed-connection-points story — hand-rolled closest-anchor loop replaced with chooseClosest() (the story only reads x/y, so the copy is fine); the | null return makes the empty-anchors case explicit and falls back to the drop point instead of indexing past the array.

Changesets: two minor entries, one for the new method and one for the update() string support (new PointInit overload in the public typings).

The same hand-rolled loop lives in joint-demos/fixed-connection-points. Like the story, it only reads x/y from the result, so it can switch to the already-released chooseClosest() independently of this PR. chooseClosestIndex() is for callers that need their original anchor object back (identity, or anchors carrying extra data such as an id or side).

Test plan

  • karma:geometry — 353/353 (new tests: chooseClosestIndex incl. empty / single / g.Point / string / partial { x } inputs and tie → first index; update() with string arg). Each new test was watched failing first.
  • grunt test:ts (core typings)
  • joint-react: eslint on the story; tsc --noEmit reports no errors in touched files
  • eslint on all touched core files

🤖 Generated with Claude Code

kumilingus and others added 3 commits September 12, 2026 10:37
`chooseClosestIndex(points)` returns the index of the closest point
(`-1` for an empty array), so callers can keep a reference to their
own anchor object instead of receiving a copy. `chooseClosest()` is
now a thin wrapper over it.

The search reuses a single scratch `Point` via `update()` rather than
allocating one per candidate. For that to cover every `PointInit`,
`update()` now parses `'10 20'` / `'10@20'` strings the same way the
constructor does; previously it silently stored the string as `x`.

The fixed-connection-points story replaces its hand-rolled
closest-anchor loop with the new method.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
The public typing gains a `PointInit` overload, which is new API surface
rather than a fix of a documented behavior.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
… story

The story only reads x/y from the found anchor, so the `g.Point` copy
from `chooseClosest()` is enough; its `| null` return also makes the
empty-anchors case explicit (falls back to the drop point) instead of
indexing past the array.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
kumilingus and others added 2 commits September 12, 2026 11:46
…ring parsing code

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…ests

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant