@khanacademy/perseus 76.0.2 → 76.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (33) hide show
  1. package/dist/components/fixed-to-responsive.d.ts +1 -0
  2. package/dist/es/index.css +2 -2
  3. package/dist/es/index.css.map +1 -1
  4. package/dist/es/index.js +65 -43
  5. package/dist/es/index.js.map +1 -1
  6. package/dist/es/strings.js +1 -1
  7. package/dist/es/strings.js.map +1 -1
  8. package/dist/index.css +2 -2
  9. package/dist/index.css.map +1 -1
  10. package/dist/index.d.ts +1 -1
  11. package/dist/index.js +66 -41
  12. package/dist/index.js.map +1 -1
  13. package/dist/renderer.d.ts +5 -5
  14. package/dist/strings.d.ts +129 -0
  15. package/dist/strings.js +1 -1
  16. package/dist/strings.js.map +1 -1
  17. package/dist/util/register-all-widgets-for-testing.d.ts +4 -2
  18. package/dist/widget-ai-utils/interactive-graph/interactive-graph-ai-utils.d.ts +24 -2
  19. package/dist/widgets/image/components/explore-image-modal-content.d.ts +4 -2
  20. package/dist/widgets/image/components/explore-image-modal.d.ts +4 -2
  21. package/dist/widgets/image/components/image-info-area.d.ts +19 -12
  22. package/dist/widgets/image/utils.d.ts +1 -0
  23. package/dist/widgets/interactive-graphs/graphs/absolute-value.d.ts +27 -0
  24. package/dist/widgets/interactive-graphs/graphs/components/asymptote-drag-handle.d.ts +15 -0
  25. package/dist/widgets/interactive-graphs/graphs/components/movable-asymptote.d.ts +26 -0
  26. package/dist/widgets/interactive-graphs/graphs/exponential.d.ts +12 -0
  27. package/dist/widgets/interactive-graphs/graphs/tangent.d.ts +14 -0
  28. package/dist/widgets/interactive-graphs/interactive-graph-question-builder.d.ts +14 -0
  29. package/dist/widgets/interactive-graphs/interactive-graph.d.ts +7 -1
  30. package/dist/widgets/interactive-graphs/reducer/initialize-graph-state.d.ts +7 -1
  31. package/dist/widgets/interactive-graphs/reducer/interactive-graph-action.d.ts +10 -0
  32. package/dist/widgets/interactive-graphs/types.d.ts +15 -1
  33. package/package.json +13 -13
@@ -2,17 +2,7 @@ import { type Interval, type PerseusImageBackground, type PerseusImageLabel, typ
2
2
  import * as React from "react";
3
3
  import type { APIOptions } from "../../../types";
4
4
  import type { LinterContextProps } from "@khanacademy/perseus-linter";
5
- export interface ImageInfoAreaProps {
6
- backgroundImage: PerseusImageBackground;
7
- title: string;
8
- caption: string;
9
- alt: string;
10
- longDescription: string;
11
- box: Size;
12
- labels: Array<PerseusImageLabel>;
13
- range: [Interval, Interval];
14
- linterContext: LinterContextProps;
15
- apiOptions: APIOptions;
5
+ export interface ZoomProps {
16
6
  /**
17
7
  * zoomSize represents the larger of the image’s natural size (calculated on load)
18
8
  * and the saved backgroundImage size (specified when the content is written). This
@@ -22,12 +12,29 @@ export interface ImageInfoAreaProps {
22
12
  * determine if the image is large enough to allow zooming.
23
13
  */
24
14
  zoomSize: Size;
15
+ }
16
+ export interface GifProps {
25
17
  isGifPlaying: boolean;
26
18
  setIsGifPlaying: (isPaused: boolean) => void;
27
19
  }
20
+ export interface CommonImageProps {
21
+ backgroundImage: PerseusImageBackground;
22
+ scale: number;
23
+ title: string;
24
+ caption: string;
25
+ alt: string;
26
+ longDescription: string;
27
+ box: Size;
28
+ labels: Array<PerseusImageLabel>;
29
+ range: [Interval, Interval];
30
+ linterContext: LinterContextProps;
31
+ apiOptions: APIOptions;
32
+ }
33
+ type Props = ZoomProps & GifProps & CommonImageProps;
28
34
  /**
29
35
  * The ImageInfoArea component includes the GIF controls, description modal
30
36
  * launcher, and caption for the image. This is displayed underneath the image
31
37
  * in the Image widget.
32
38
  */
33
- export declare const ImageInfoArea: (props: ImageInfoAreaProps) => React.JSX.Element | null;
39
+ export declare const ImageInfoArea: (props: Props) => React.JSX.Element | null;
40
+ export {};
@@ -1,4 +1,5 @@
1
1
  export declare function isGif(url: string): boolean;
2
+ export declare function isSvg(url: string): boolean;
2
3
  export declare const earthMoonImage: {
3
4
  url: string;
4
5
  width: number;
@@ -0,0 +1,27 @@
1
+ import { vec } from "mafs";
2
+ import { type I18nContextType } from "../../../components/i18n-context";
3
+ import type { AbsoluteValueGraphState, Dispatch, InteractiveGraphElementSuite } from "../types";
4
+ import type { Coord } from "@khanacademy/perseus-core";
5
+ export declare function renderAbsoluteValueGraph(state: AbsoluteValueGraphState, dispatch: Dispatch, i18n: I18nContextType): InteractiveGraphElementSuite;
6
+ export type AbsoluteValueCoefficients = {
7
+ m: number;
8
+ h: number;
9
+ v: number;
10
+ };
11
+ /**
12
+ * Compute the coefficients [m, h, v] for f(x) = m * |x - h| + v from two
13
+ * control points: p1 (vertex) and p2 (a point on one arm).
14
+ *
15
+ * Returns undefined if p1 and p2 share the same x-coordinate (slope undefined).
16
+ */
17
+ export declare function getAbsoluteValueCoefficients(coords: ReadonlyArray<Coord>): AbsoluteValueCoefficients | undefined;
18
+ /**
19
+ * Keyboard constraint for absolute value control points.
20
+ * Skips any horizontal position where both points would share the same x.
21
+ */
22
+ export declare const getAbsoluteValueKeyboardConstraint: (coords: ReadonlyArray<Coord>, snapStep: vec.Vector2, pointIndex: number) => {
23
+ up: vec.Vector2;
24
+ down: vec.Vector2;
25
+ left: vec.Vector2;
26
+ right: vec.Vector2;
27
+ };
@@ -0,0 +1,15 @@
1
+ import * as React from "react";
2
+ import type { vec } from "mafs";
3
+ type Props = {
4
+ /** Pixel-space center of the handle (already transformed from graph coordinates). */
5
+ center: vec.Vector2;
6
+ active: boolean;
7
+ focused: boolean;
8
+ /**
9
+ * "horizontal" — wide pill with a 3×2 grip dot grid (exponential asymptote)
10
+ * "vertical" — tall pill with a 2×3 grip dot grid (logarithm asymptote)
11
+ */
12
+ orientation: "horizontal" | "vertical";
13
+ };
14
+ export declare function AsymptoteDragHandle(props: Props): React.JSX.Element;
15
+ export {};
@@ -0,0 +1,26 @@
1
+ import * as React from "react";
2
+ import type { KeyboardMovementConstraint } from "../use-draggable";
3
+ import type { vec } from "mafs";
4
+ type Props = {
5
+ /** Pixel-space start point of the asymptote line. */
6
+ start: vec.Vector2;
7
+ /** Pixel-space end point of the asymptote line. */
8
+ end: vec.Vector2;
9
+ /** Pixel-space center of the drag handle (midpoint of the line). */
10
+ mid: vec.Vector2;
11
+ /** Graph-space position used by useDraggable for movement tracking. */
12
+ point: vec.Vector2;
13
+ /** Called with the new graph-space position when the asymptote moves. */
14
+ onMove: (destination: vec.Vector2) => void;
15
+ /** Keyboard movement constraint (e.g. prevent landing between curve points). Defaults to unconstrained. */
16
+ constrainKeyboardMovement?: KeyboardMovementConstraint;
17
+ /**
18
+ * "horizontal" — asymptote is a horizontal line (exponential graph)
19
+ * "vertical" — asymptote is a vertical line (logarithm graph)
20
+ */
21
+ orientation: "horizontal" | "vertical";
22
+ /** Accessible label for the asymptote drag target. */
23
+ ariaLabel: string;
24
+ };
25
+ export declare function MovableAsymptote(props: Props): React.JSX.Element;
26
+ export {};
@@ -0,0 +1,12 @@
1
+ import { vec } from "mafs";
2
+ import { type I18nContextType } from "../../../components/i18n-context";
3
+ import type { ExponentialGraphState, Dispatch, InteractiveGraphElementSuite } from "../types";
4
+ import type { Coord } from "@khanacademy/perseus-core";
5
+ export declare function renderExponentialGraph(state: ExponentialGraphState, dispatch: Dispatch, i18n: I18nContextType): InteractiveGraphElementSuite;
6
+ export declare const constrainAsymptoteKeyboard: (p: vec.Vector2, coords: ReadonlyArray<Coord>, snapStep: vec.Vector2) => vec.Vector2;
7
+ export declare const getExponentialKeyboardConstraint: (coords: ReadonlyArray<Coord>, asymptote: number, snapStep: vec.Vector2, pointIndex: number) => {
8
+ up: vec.Vector2;
9
+ down: vec.Vector2;
10
+ left: vec.Vector2;
11
+ right: vec.Vector2;
12
+ };
@@ -0,0 +1,14 @@
1
+ import { vec } from "mafs";
2
+ import { type I18nContextType } from "../../../components/i18n-context";
3
+ import type { TangentGraphState, Dispatch, InteractiveGraphElementSuite } from "../types";
4
+ import type { NamedTangentCoefficient } from "@khanacademy/kmath";
5
+ import type { Coord } from "@khanacademy/perseus-core";
6
+ export declare function renderTangentGraph(state: TangentGraphState, dispatch: Dispatch, i18n: I18nContextType): InteractiveGraphElementSuite;
7
+ export declare const getTangentKeyboardConstraint: (coords: ReadonlyArray<Coord>, snapStep: vec.Vector2, pointIndex: number) => {
8
+ up: vec.Vector2;
9
+ down: vec.Vector2;
10
+ left: vec.Vector2;
11
+ right: vec.Vector2;
12
+ };
13
+ export declare const computeTangent: (x: number, tangentCoefficients: NamedTangentCoefficient) => number;
14
+ export declare const getTangentCoefficients: (coords: ReadonlyArray<Coord>) => NamedTangentCoefficient | undefined;
@@ -99,6 +99,16 @@ declare class InteractiveGraphQuestionBuilder {
99
99
  coords?: [Coord, Coord];
100
100
  startCoords?: [Coord, Coord];
101
101
  }): InteractiveGraphQuestionBuilder;
102
+ withExponential(options?: {
103
+ coords?: [Coord, Coord];
104
+ asymptote?: number;
105
+ startCoords?: [Coord, Coord];
106
+ startAsymptote?: number;
107
+ }): InteractiveGraphQuestionBuilder;
108
+ withTangent(options?: {
109
+ coords?: [Coord, Coord];
110
+ startCoords?: [Coord, Coord];
111
+ }): InteractiveGraphQuestionBuilder;
102
112
  withPolygon(snapTo?: SnapTo, options?: {
103
113
  match?: "similar" | "congruent" | "approx";
104
114
  numSides?: number | "unlimited";
@@ -120,6 +130,10 @@ declare class InteractiveGraphQuestionBuilder {
120
130
  snapDegrees?: number;
121
131
  match?: "congruent";
122
132
  }): InteractiveGraphQuestionBuilder;
133
+ withAbsoluteValue(options?: {
134
+ coords?: [Coord, Coord];
135
+ startCoords?: [Coord, Coord];
136
+ }): InteractiveGraphQuestionBuilder;
123
137
  addLockedPointAt(x: number, y: number, options?: {
124
138
  color?: LockedFigureColor;
125
139
  filled?: boolean;
@@ -5,7 +5,7 @@ import type { Coord } from "../../interactive2/types";
5
5
  import type { WidgetProps } from "../../types";
6
6
  import type { InteractiveGraphPromptJSON } from "../../widget-ai-utils/interactive-graph/interactive-graph-ai-utils";
7
7
  import type { UnsupportedWidgetPromptJSON } from "../../widget-ai-utils/unsupported-widget";
8
- import type { QuadraticCoefficient, SineCoefficient, Range } from "@khanacademy/kmath";
8
+ import type { QuadraticCoefficient, SineCoefficient, TangentCoefficient, Range } from "@khanacademy/kmath";
9
9
  import type { PerseusGraphType, PerseusGraphTypeAngle, PerseusGraphTypePoint, PerseusGraphTypeSegment, PerseusInteractiveGraphWidgetOptions, GraphRange, InteractiveGraphPublicWidgetOptions, LockedFigure, PerseusImageBackground, MarkingsType, PerseusInteractiveGraphUserInput, AxisLabelLocation, ShowAxisArrows } from "@khanacademy/perseus-core";
10
10
  type InteractiveGraphProps = {
11
11
  /**
@@ -258,6 +258,12 @@ declare class InteractiveGraph extends React.Component<Props, State> {
258
258
  static getCurrentSinusoidCoefficients(props: Props): SineCoefficient;
259
259
  static defaultSinusoidCoords(props: Props): Coord[];
260
260
  static getSinusoidEquationString(props: Props): string;
261
+ static defaultExponentialCoords(props: Props): Coord[];
262
+ static getExponentialEquationString(props: Props): string;
263
+ static getAbsoluteValueEquationString(props: Props): string;
264
+ static getCurrentTangentCoefficients(props: Props): TangentCoefficient;
265
+ static defaultTangentCoords(props: Props): Coord[];
266
+ static getTangentEquationString(props: Props): string;
261
267
  static getCircleEquationString(props: Props): string;
262
268
  static getLinearSystemEquationString(props: Props): string;
263
269
  static getPointEquationString(props: Props): string;
@@ -1,6 +1,6 @@
1
1
  import type { Coord } from "../../../interactive2/types";
2
2
  import type { InteractiveGraphState, PairOfPoints } from "../types";
3
- import type { PerseusGraphType, PerseusGraphTypeAngle, PerseusGraphTypeCircle, PerseusGraphTypeLinear, PerseusGraphTypeLinearSystem, PerseusGraphTypePoint, PerseusGraphTypePolygon, PerseusGraphTypeQuadratic, PerseusGraphTypeRay, PerseusGraphTypeSegment, PerseusGraphTypeSinusoid } from "@khanacademy/perseus-core";
3
+ import type { PerseusGraphType, PerseusGraphTypeAbsoluteValue, PerseusGraphTypeAngle, PerseusGraphTypeCircle, PerseusGraphTypeLinear, PerseusGraphTypeLinearSystem, PerseusGraphTypePoint, PerseusGraphTypePolygon, PerseusGraphTypeQuadratic, PerseusGraphTypeRay, PerseusGraphTypeSegment, PerseusGraphTypeSinusoid, PerseusGraphTypeExponential, PerseusGraphTypeTangent } from "@khanacademy/perseus-core";
4
4
  import type { Interval } from "mafs";
5
5
  export type InitializeGraphStateParams = {
6
6
  range: [x: Interval, y: Interval];
@@ -15,11 +15,17 @@ export declare function getLineCoords(graph: PerseusGraphTypeRay | PerseusGraphT
15
15
  export declare function getLinearSystemCoords(graph: PerseusGraphTypeLinearSystem, range: [x: Interval, y: Interval], step: [x: number, y: number]): PairOfPoints[];
16
16
  export declare function getPolygonCoords(graph: PerseusGraphTypePolygon, range: [x: Interval, y: Interval], step: [x: number, y: number]): Coord[];
17
17
  export declare function getSinusoidCoords(graph: PerseusGraphTypeSinusoid, range: [x: Interval, y: Interval], step: [x: number, y: number]): [Coord, Coord];
18
+ export declare function getAbsoluteValueCoords(graph: PerseusGraphTypeAbsoluteValue, range: [x: Interval, y: Interval], step: [x: number, y: number]): [Coord, Coord];
19
+ export declare function getTangentCoords(graph: PerseusGraphTypeTangent, range: [x: Interval, y: Interval], step: [x: number, y: number]): [Coord, Coord];
18
20
  export declare function getQuadraticCoords(graph: PerseusGraphTypeQuadratic, range: [x: Interval, y: Interval], step: [x: number, y: number]): [Coord, Coord, Coord];
19
21
  export declare function getCircleCoords(graph: PerseusGraphTypeCircle): {
20
22
  center: Coord;
21
23
  radiusPoint: Coord;
22
24
  };
25
+ export declare function getExponentialCoords(graph: PerseusGraphTypeExponential, range: [x: Interval, y: Interval], step: [x: number, y: number]): {
26
+ coords: [Coord, Coord];
27
+ asymptote: number;
28
+ };
23
29
  export declare const getAngleCoords: (params: {
24
30
  graph: PerseusGraphTypeAngle;
25
31
  range: [x: Interval, y: Interval];
@@ -56,6 +56,16 @@ export declare const actions: {
56
56
  sinusoid: {
57
57
  movePoint: typeof movePoint;
58
58
  };
59
+ exponential: {
60
+ movePoint: typeof movePoint;
61
+ moveCenter: typeof moveCenter;
62
+ };
63
+ absoluteValue: {
64
+ movePoint: typeof movePoint;
65
+ };
66
+ tangent: {
67
+ movePoint: typeof movePoint;
68
+ };
59
69
  };
60
70
  export declare const DELETE_INTENT = "delete-intent";
61
71
  export interface DeleteIntent {
@@ -15,7 +15,7 @@ export type InteractiveGraphElementSuite = {
15
15
  graph: ReactNode;
16
16
  interactiveElementsDescription: ReactNode;
17
17
  };
18
- export type InteractiveGraphState = AngleGraphState | SegmentGraphState | LinearSystemGraphState | LinearGraphState | RayGraphState | NoneGraphState | PolygonGraphState | PointGraphState | CircleGraphState | QuadraticGraphState | SinusoidGraphState;
18
+ export type InteractiveGraphState = AbsoluteValueGraphState | AngleGraphState | SegmentGraphState | LinearSystemGraphState | LinearGraphState | RayGraphState | NoneGraphState | PolygonGraphState | PointGraphState | CircleGraphState | QuadraticGraphState | SinusoidGraphState | ExponentialGraphState | TangentGraphState;
19
19
  export type UnlimitedGraphState = PointGraphState | PolygonGraphState;
20
20
  export interface InteractiveGraphStateCommon {
21
21
  hasBeenInteractedWith: boolean;
@@ -77,6 +77,20 @@ export interface SinusoidGraphState extends InteractiveGraphStateCommon {
77
77
  type: "sinusoid";
78
78
  coords: [vec.Vector2, vec.Vector2];
79
79
  }
80
+ export interface ExponentialGraphState extends InteractiveGraphStateCommon {
81
+ type: "exponential";
82
+ coords: [vec.Vector2, vec.Vector2];
83
+ /** The y-value of the horizontal asymptote (y = asymptote). */
84
+ asymptote: number;
85
+ }
86
+ export interface AbsoluteValueGraphState extends InteractiveGraphStateCommon {
87
+ type: "absolute-value";
88
+ coords: [vec.Vector2, vec.Vector2];
89
+ }
90
+ export interface TangentGraphState extends InteractiveGraphStateCommon {
91
+ type: "tangent";
92
+ coords: [vec.Vector2, vec.Vector2];
93
+ }
80
94
  export interface AngleGraphState extends InteractiveGraphStateCommon {
81
95
  type: "angle";
82
96
  showAngles?: boolean;
package/package.json CHANGED
@@ -3,7 +3,7 @@
3
3
  "description": "Core Perseus API (includes renderers and widgets)",
4
4
  "author": "Khan Academy",
5
5
  "license": "MIT",
6
- "version": "76.0.2",
6
+ "version": "76.1.0",
7
7
  "publishConfig": {
8
8
  "access": "public"
9
9
  },
@@ -41,16 +41,16 @@
41
41
  "mafs": "0.19.0",
42
42
  "tiny-invariant": "1.3.1",
43
43
  "uuid": "^10.0.0",
44
- "@khanacademy/kas": "2.2.0",
45
- "@khanacademy/keypad-context": "3.2.38",
46
- "@khanacademy/kmath": "2.2.38",
47
- "@khanacademy/math-input": "26.4.8",
48
- "@khanacademy/perseus-core": "23.6.0",
49
- "@khanacademy/perseus-linter": "4.8.6",
50
- "@khanacademy/perseus-score": "8.3.0",
51
- "@khanacademy/perseus-utils": "2.1.4",
52
- "@khanacademy/pure-markdown": "2.2.6",
53
- "@khanacademy/simple-markdown": "2.2.1"
44
+ "@khanacademy/kas": "2.2.1",
45
+ "@khanacademy/keypad-context": "3.2.40",
46
+ "@khanacademy/kmath": "2.3.0",
47
+ "@khanacademy/math-input": "26.4.10",
48
+ "@khanacademy/perseus-core": "23.7.0",
49
+ "@khanacademy/perseus-linter": "4.9.0",
50
+ "@khanacademy/perseus-score": "8.4.0",
51
+ "@khanacademy/perseus-utils": "2.1.5",
52
+ "@khanacademy/pure-markdown": "2.2.7",
53
+ "@khanacademy/simple-markdown": "2.2.2"
54
54
  },
55
55
  "devDependencies": {
56
56
  "@khanacademy/wonder-blocks-announcer": "1.0.6",
@@ -86,8 +86,8 @@
86
86
  "react-dom": "18.2.0",
87
87
  "react-popper": "^2.2.5",
88
88
  "underscore": "1.4.4",
89
- "raphael": "1.5.4",
90
- "perseus-build-settings": "0.9.0"
89
+ "perseus-build-settings": "0.9.0",
90
+ "raphael": "1.5.4"
91
91
  },
92
92
  "peerDependencies": {
93
93
  "@khanacademy/wonder-blocks-announcer": "^1.0.6",