Skip to content

[AbsoluteValue] PR5 - editor support#3352

Open
handeyeco wants to merge 4 commits intoLEMS-3347/absolute-value-pr4from
LEMS-3347/absolute-value-pr5
Open

[AbsoluteValue] PR5 - editor support#3352
handeyeco wants to merge 4 commits intoLEMS-3347/absolute-value-pr4from
LEMS-3347/absolute-value-pr5

Conversation

@handeyeco
Copy link
Contributor

@handeyeco handeyeco commented Mar 13, 2026

Everything is AI

Summary:

This is part of a series of PRs as defined in the first PR:

Initial implementation experiment is Perseus#3304.

Issue: LEMS-3347


Add editor support for absolute-value graph type

Surfaces the absolute-value graph in the content creator UI. Depends on PR
1 + PR 2 (for getAbsoluteValueCoords). No new components needed — the
two-point shape fits existing patterns.

Changes:

  • initialize-graph-state.ts — Exports getAbsoluteValueCoords (previously
    file-private) so the editor can import it via @khanacademy/perseus.
  • perseus/src/index.ts — Re-exports getAbsoluteValueCoords alongside the
    other getXxxCoords helpers.
  • graph-type-selector.tsx — Adds to the answer type dropdown.
  • start-coords/types.ts — Adds {type: "absolute-value"} to
    GraphTypesThatHaveStartCoords so the StartCoords type includes its
    startCoords field.
  • start-coords-settings.tsx — Adds case "absolute-value" using
    getAbsoluteValueCoords + StartCoordsPoint (the two-point shape maps
    directly onto the existing generic point coordinate UI).
  • start-coords/util.ts — Adds case "absolute-value" in
    getDefaultGraphStartCoords so the "Use default start coordinates" reset
    button returns the correct defaults.

@handeyeco handeyeco self-assigned this Mar 13, 2026
@handeyeco handeyeco changed the title Implement PR #5 [AbsoluteValue] PR4 - editor support Mar 13, 2026
@github-actions github-actions bot added schema-change Attached to PRs when we detect Perseus Schema changes in it and removed schema-change Attached to PRs when we detect Perseus Schema changes in it labels Mar 13, 2026
@github-actions
Copy link
Contributor

github-actions bot commented Mar 13, 2026

🗄️ Schema Change: No Changes ✅

@github-actions
Copy link
Contributor

github-actions bot commented Mar 13, 2026

npm Snapshot: Published

Good news!! We've packaged up the latest commit from this PR (23ab60e) and published it to npm. You
can install it using the tag PR3352.

Example:

pnpm add @khanacademy/perseus@PR3352

If you are working in Khan Academy's frontend, you can run the below command.

./dev/tools/bump_perseus_version.ts -t PR3352

If you are working in Khan Academy's webapp, you can run the below command.

./dev/tools/bump_perseus_version.js -t PR3352

@github-actions
Copy link
Contributor

github-actions bot commented Mar 13, 2026

🛠️ Item Splitting: No Changes ✅

@github-actions
Copy link
Contributor

github-actions bot commented Mar 13, 2026

Size Change: +68 B (+0.01%)

Total Size: 488 kB

Filename Size Change
packages/perseus-editor/dist/es/index.js 100 kB +60 B (+0.06%)
packages/perseus/dist/es/index.js 189 kB +8 B (0%)
ℹ️ View Unchanged
Filename Size
packages/kas/dist/es/index.js 20.8 kB
packages/keypad-context/dist/es/index.js 1 kB
packages/kmath/dist/es/index.js 6.03 kB
packages/math-input/dist/es/index.js 98.5 kB
packages/math-input/dist/es/strings.js 1.61 kB
packages/perseus-core/dist/es/index.item-splitting.js 11.9 kB
packages/perseus-core/dist/es/index.js 25 kB
packages/perseus-linter/dist/es/index.js 8.82 kB
packages/perseus-score/dist/es/index.js 9.32 kB
packages/perseus-utils/dist/es/index.js 403 B
packages/perseus/dist/es/strings.js 7.66 kB
packages/pure-markdown/dist/es/index.js 1.39 kB
packages/simple-markdown/dist/es/index.js 6.71 kB

compressed-size-action

@handeyeco handeyeco changed the title [AbsoluteValue] PR4 - editor support [AbsoluteValue] PR5 - editor support Mar 13, 2026
Comment on lines +46 to +57
case "absolute-value":
const absoluteValueCoords = getAbsoluteValueCoords(
props,
range,
step,
);
return (
<StartCoordsPoint
startCoords={absoluteValueCoords}
onChange={onChange}
/>
);
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 The absolute-value case uses StartCoordsPoint (which expects Coord[]) instead of StartCoordsLine (which expects CollinearTuple / [Coord, Coord]). Since getAbsoluteValueCoords returns [Coord, Coord], using StartCoordsLine would be more type-safe and consistent with how linear/ray handle the same structure.

Extended reasoning...

What the bug is

The new absolute-value case in StartCoordsSettingsInner (line 46-57) renders StartCoordsPoint to handle start coordinate editing. However, getAbsoluteValueCoords returns [Coord, Coord] (a fixed-length tuple), which is the same shape as CollinearTuple used by linear and ray graph types. StartCoordsPoint expects Coord[] (variable-length array) and is designed for point/polygon graphs.

How the type widening happens

StartCoordsPoint declares its props as { startCoords: Coord[]; onChange: (startCoords: Coord[]) => void }. Its onChange handler uses const newStartCoords = [...startCoords] (spread into a new array), then calls onChange(newStartCoords). This spread widens the TypeScript type from [Coord, Coord] to Coord[]. In contrast, StartCoordsLine declares { startCoords: CollinearTuple; onChange: (startCoords: CollinearTuple) => void } and its onChange constructs the tuple explicitly: onChange([value, startCoords[1]]), preserving the [Coord, Coord] type.

Step-by-step proof

  1. User opens the interactive graph editor and selects "Absolute value" as the graph type.
  2. StartCoordsSettingsInner matches case "absolute-value" (line 46).
  3. getAbsoluteValueCoords is called, returning a [Coord, Coord] value.
  4. This is passed to <StartCoordsPoint startCoords={absoluteValueCoords} onChange={onChange} />.
  5. User edits Point 1 — StartCoordsPoint.onChange fires with [...startCoords] (line 31 of start-coords-point.tsx), producing Coord[].
  6. The onChange prop propagates this Coord[] value upward, where the absolute-value graph expects [Coord, Coord].

For comparison, linear and ray (which have the identical [Coord, Coord] type) correctly use StartCoordsLine (lines 62-68), and sinusoid (also [Coord, Coord]) uses StartCoordsSinusoid.

Impact

This is not a runtime bug — at JavaScript runtime, a 2-element array is indistinguishable whether typed as [Coord, Coord] or Coord[], and the UI renders identically (both show "Point 1" / "Point 2" inputs). The onChange handler at line 170 is untyped, so the widening passes silently. However, it is a type-safety and consistency concern: downstream TypeScript code expecting [Coord, Coord] could receive Coord[], and this breaks the established pattern in the codebase.

How to fix

Replace StartCoordsPoint with StartCoordsLine in the absolute-value case, matching the pattern used by linear/ray:

case "absolute-value":
    const absoluteValueCoords = getAbsoluteValueCoords(props, range, step);
    return (
        <StartCoordsLine
            startCoords={absoluteValueCoords}
            onChange={onChange}
        />
    );

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant