diff --git a/.changeset/hungry-masks-hang.md b/.changeset/hungry-masks-hang.md
new file mode 100644
index 00000000000..5cd0bf4ce17
--- /dev/null
+++ b/.changeset/hungry-masks-hang.md
@@ -0,0 +1,8 @@
+---
+"@khanacademy/perseus-core": major
+"@khanacademy/perseus": minor
+"@khanacademy/perseus-editor": minor
+"@khanacademy/perseus-linter": minor
+---
+
+Change shape of `LockedPolygonType.points` from `[]Coord` to `LockedPolygonPointType`. This is to support adding fields to the Locked Polygon points in the future. Callers should migrate to using the new shape.
diff --git a/__docs__/sample-data.ts b/__docs__/sample-data.ts
index 00ef876f2aa..8aeb3d9ca28 100644
--- a/__docs__/sample-data.ts
+++ b/__docs__/sample-data.ts
@@ -84,11 +84,11 @@ export const graphExample: PerseusRenderer = {
weight: "thick",
fillStyle: "translucent",
points: [
- [7, -3],
- [8, -5],
- [4, -7],
- [0, -7],
- [2, -3],
+ {coord: [7, -3]},
+ {coord: [8, -5]},
+ {coord: [4, -7]},
+ {coord: [0, -7]},
+ {coord: [2, -3]},
],
showVertices: false,
strokeStyle: "solid",
diff --git a/packages/perseus-core/src/data-schema.ts b/packages/perseus-core/src/data-schema.ts
index 5c5eb882b26..6f3a6af83aa 100644
--- a/packages/perseus-core/src/data-schema.ts
+++ b/packages/perseus-core/src/data-schema.ts
@@ -1075,9 +1075,13 @@ export type LockedEllipseType = {
ariaLabel?: string;
};
+export type LockedPolygonPointType = {
+ coord: Coord;
+};
+
export type LockedPolygonType = {
type: "polygon";
- points: Coord[];
+ points: LockedPolygonPointType[];
color: LockedFigureColor;
showVertices: boolean;
fillStyle: LockedFigureFillType;
diff --git a/packages/perseus-core/src/parse-perseus-json/perseus-parsers/interactive-graph-widget.test.ts b/packages/perseus-core/src/parse-perseus-json/perseus-parsers/interactive-graph-widget.test.ts
index ae34c9ac9c8..fdf24e52015 100644
--- a/packages/perseus-core/src/parse-perseus-json/perseus-parsers/interactive-graph-widget.test.ts
+++ b/packages/perseus-core/src/parse-perseus-json/perseus-parsers/interactive-graph-widget.test.ts
@@ -385,6 +385,180 @@ describe("parseInteractiveGraphWidget", () => {
);
});
+ it("parses locked polygon points with coord field", () => {
+ const result = parse(
+ {
+ type: "interactive-graph",
+ options: {
+ step: [1, 1],
+ markings: "grid",
+ showProtractor: false,
+ range: [
+ [-10, 10],
+ [-10, 10],
+ ],
+ showAxisArrows: {
+ xMin: true,
+ xMax: true,
+ yMin: true,
+ yMax: true,
+ },
+ showAxisTicks: {x: true, y: true},
+ correct: {
+ type: "linear",
+ },
+ lockedFigures: [
+ {
+ type: "polygon",
+ points: [
+ {coord: [0, 0]},
+ {coord: [1, 0]},
+ {coord: [1, 1]},
+ ],
+ color: "blue",
+ showVertices: false,
+ fillStyle: "none",
+ strokeStyle: "solid",
+ weight: "medium",
+ },
+ ],
+ },
+ },
+ parseInteractiveGraphWidget,
+ );
+
+ expect(result).toEqual(
+ success({
+ type: "interactive-graph",
+ options: {
+ step: [1, 1],
+ markings: "grid",
+ showProtractor: false,
+ range: [
+ [-10, 10],
+ [-10, 10],
+ ],
+ showAxisArrows: {
+ xMin: true,
+ xMax: true,
+ yMin: true,
+ yMax: true,
+ },
+ showAxisTicks: {x: true, y: true},
+ correct: {
+ type: "linear",
+ },
+ graph: {
+ type: "linear",
+ },
+ lockedFigures: [
+ {
+ type: "polygon",
+ points: [
+ {coord: [0, 0]},
+ {coord: [1, 0]},
+ {coord: [1, 1]},
+ ],
+ color: "blue",
+ showVertices: false,
+ fillStyle: "none",
+ strokeStyle: "solid",
+ weight: "medium",
+ labels: [],
+ },
+ ],
+ },
+ }),
+ );
+ });
+
+ it("normalizes legacy locked polygon points array to coord field", () => {
+ const result = parse(
+ {
+ type: "interactive-graph",
+ options: {
+ step: [1, 1],
+ markings: "grid",
+ showProtractor: false,
+ range: [
+ [-10, 10],
+ [-10, 10],
+ ],
+ showAxisArrows: {
+ xMin: true,
+ xMax: true,
+ yMin: true,
+ yMax: true,
+ },
+ showAxisTicks: {x: true, y: true},
+ correct: {
+ type: "linear",
+ },
+ lockedFigures: [
+ {
+ type: "polygon",
+ points: [
+ [0, 0],
+ [1, 0],
+ [1, 1],
+ ],
+ color: "blue",
+ showVertices: false,
+ fillStyle: "none",
+ strokeStyle: "solid",
+ weight: "medium",
+ },
+ ],
+ },
+ },
+ parseInteractiveGraphWidget,
+ );
+
+ expect(result).toEqual(
+ success({
+ type: "interactive-graph",
+ options: {
+ step: [1, 1],
+ markings: "grid",
+ showProtractor: false,
+ range: [
+ [-10, 10],
+ [-10, 10],
+ ],
+ showAxisArrows: {
+ xMin: true,
+ xMax: true,
+ yMin: true,
+ yMax: true,
+ },
+ showAxisTicks: {x: true, y: true},
+ correct: {
+ type: "linear",
+ },
+ graph: {
+ type: "linear",
+ },
+ lockedFigures: [
+ {
+ type: "polygon",
+ points: [
+ {coord: [0, 0]},
+ {coord: [1, 0]},
+ {coord: [1, 1]},
+ ],
+ color: "blue",
+ showVertices: false,
+ fillStyle: "none",
+ strokeStyle: "solid",
+ weight: "medium",
+ labels: [],
+ },
+ ],
+ },
+ }),
+ );
+ });
+
it("rejects unrecognized color names on locked figures", () => {
const result = parse(
{
diff --git a/packages/perseus-core/src/parse-perseus-json/perseus-parsers/interactive-graph-widget.ts b/packages/perseus-core/src/parse-perseus-json/perseus-parsers/interactive-graph-widget.ts
index cf5559ae6f0..3c92d9cc0e8 100644
--- a/packages/perseus-core/src/parse-perseus-json/perseus-parsers/interactive-graph-widget.ts
+++ b/packages/perseus-core/src/parse-perseus-json/perseus-parsers/interactive-graph-widget.ts
@@ -256,9 +256,23 @@ const parseLockedEllipseType = object({
ariaLabel: optional(string),
});
+const parseLockedPolygonPointType = object({
+ coord: pairOfNumbers,
+});
+
+const parseLockedPolygonPointsType = union(
+ array(parseLockedPolygonPointType),
+).or(
+ // Normalize legacy representation of points as Coord[] to
+ // LockedPolygonPointType[].
+ pipeParsers(array(pairOfNumbers)).then(
+ convert((coords) => coords.map((coord) => ({coord}))),
+ ).parser,
+).parser;
+
const parseLockedPolygonType = object({
type: constant("polygon"),
- points: array(pairOfNumbers),
+ points: parseLockedPolygonPointsType,
color: parseLockedFigureColor,
showVertices: boolean,
fillStyle: parseLockedFigureFillType,
diff --git a/packages/perseus-core/src/parse-perseus-json/regression-tests/__snapshots__/parse-perseus-json-regression.test.ts.snap b/packages/perseus-core/src/parse-perseus-json/regression-tests/__snapshots__/parse-perseus-json-regression.test.ts.snap
index 1fedc2480da..ed45eff0998 100644
--- a/packages/perseus-core/src/parse-perseus-json/regression-tests/__snapshots__/parse-perseus-json-regression.test.ts.snap
+++ b/packages/perseus-core/src/parse-perseus-json/regression-tests/__snapshots__/parse-perseus-json-regression.test.ts.snap
@@ -6972,18 +6972,24 @@ exports[`parseAndMigratePerseusItem given interactive-graph-locked-figures-missi
"fillStyle": "none",
"labels": [],
"points": [
- [
- -8,
- -7,
- ],
- [
- -8,
- -3,
- ],
- [
- -4,
- -3,
- ],
+ {
+ "coord": [
+ -8,
+ -7,
+ ],
+ },
+ {
+ "coord": [
+ -8,
+ -3,
+ ],
+ },
+ {
+ "coord": [
+ -4,
+ -3,
+ ],
+ },
],
"showVertices": false,
"strokeStyle": "solid",
@@ -7248,18 +7254,24 @@ exports[`parseAndMigratePerseusItem given interactive-graph-locked-figures-missi
"fillStyle": "none",
"labels": [],
"points": [
- [
- -8,
- -7,
- ],
- [
- -8,
- -3,
- ],
- [
- -4,
- -3,
- ],
+ {
+ "coord": [
+ -8,
+ -7,
+ ],
+ },
+ {
+ "coord": [
+ -8,
+ -3,
+ ],
+ },
+ {
+ "coord": [
+ -4,
+ -3,
+ ],
+ },
],
"showVertices": false,
"strokeStyle": "solid",
diff --git a/packages/perseus-core/src/utils/generators/interactive-graph-widget-generator.test.ts b/packages/perseus-core/src/utils/generators/interactive-graph-widget-generator.test.ts
index c119e48cb0e..a7ed5fc2889 100644
--- a/packages/perseus-core/src/utils/generators/interactive-graph-widget-generator.test.ts
+++ b/packages/perseus-core/src/utils/generators/interactive-graph-widget-generator.test.ts
@@ -1180,9 +1180,15 @@ describe("generateIGLockedPolygon", () => {
expect(lockedPolygon).toEqual({
type: "polygon",
points: [
- [0, 2],
- [-1, 0],
- [1, 0],
+ {
+ coord: [0, 2],
+ },
+ {
+ coord: [-1, 0],
+ },
+ {
+ coord: [1, 0],
+ },
],
color: "grayH",
showVertices: false,
@@ -1197,9 +1203,15 @@ describe("generateIGLockedPolygon", () => {
// Arrange, Act
const lockedPolygon = generateIGLockedPolygon({
points: [
- [1, 1],
- [2, 2],
- [3, 3],
+ {
+ coord: [1, 1],
+ },
+ {
+ coord: [2, 2],
+ },
+ {
+ coord: [3, 3],
+ },
],
color: "blue",
showVertices: true,
@@ -1222,9 +1234,15 @@ describe("generateIGLockedPolygon", () => {
expect(lockedPolygon).toEqual({
type: "polygon",
points: [
- [1, 1],
- [2, 2],
- [3, 3],
+ {
+ coord: [1, 1],
+ },
+ {
+ coord: [2, 2],
+ },
+ {
+ coord: [3, 3],
+ },
],
color: "blue",
showVertices: true,
diff --git a/packages/perseus-core/src/utils/get-default-figure-for-type.test.ts b/packages/perseus-core/src/utils/get-default-figure-for-type.test.ts
index a2a463ce4cf..8ce8c98502b 100644
--- a/packages/perseus-core/src/utils/get-default-figure-for-type.test.ts
+++ b/packages/perseus-core/src/utils/get-default-figure-for-type.test.ts
@@ -75,11 +75,7 @@ describe("getDefaultFigureForType", () => {
const figure = getDefaultFigureForType("polygon");
expect(figure).toEqual({
type: "polygon",
- points: [
- [0, 2],
- [-1, 0],
- [1, 0],
- ],
+ points: [{coord: [0, 2]}, {coord: [-1, 0]}, {coord: [1, 0]}],
color: "grayH",
showVertices: false,
fillStyle: "none",
diff --git a/packages/perseus-core/src/utils/get-default-figure-for-type.ts b/packages/perseus-core/src/utils/get-default-figure-for-type.ts
index e9c6d301329..4c6428d8082 100644
--- a/packages/perseus-core/src/utils/get-default-figure-for-type.ts
+++ b/packages/perseus-core/src/utils/get-default-figure-for-type.ts
@@ -77,11 +77,7 @@ export function getDefaultFigureForType(type: LockedFigureType): LockedFigure {
case "polygon":
return {
type: "polygon",
- points: [
- [0, 2],
- [-1, 0],
- [1, 0],
- ],
+ points: [{coord: [0, 2]}, {coord: [-1, 0]}, {coord: [1, 0]}],
color: DEFAULT_COLOR,
showVertices: false,
fillStyle: "none",
diff --git a/packages/perseus-editor/src/__testdata__/interactive-graph.testdata.ts b/packages/perseus-editor/src/__testdata__/interactive-graph.testdata.ts
index 4626935cb4c..08cb8ecb261 100644
--- a/packages/perseus-editor/src/__testdata__/interactive-graph.testdata.ts
+++ b/packages/perseus-editor/src/__testdata__/interactive-graph.testdata.ts
@@ -265,10 +265,10 @@ export const segmentWithLockedFigures: PerseusRenderer =
}),
generateIGLockedPolygon({
points: [
- [-9, 4],
- [-6, 4],
- [-6, 1],
- [-9, 1],
+ {coord: [-9, 4]},
+ {coord: [-6, 4]},
+ {coord: [-6, 1]},
+ {coord: [-9, 1]},
],
color: "pink",
labels: [
diff --git a/packages/perseus-editor/src/widgets/__tests__/interactive-graph-editor-locked-figures.test.tsx b/packages/perseus-editor/src/widgets/__tests__/interactive-graph-editor-locked-figures.test.tsx
index 78e04c64fb2..9fc17d6561e 100644
--- a/packages/perseus-editor/src/widgets/__tests__/interactive-graph-editor-locked-figures.test.tsx
+++ b/packages/perseus-editor/src/widgets/__tests__/interactive-graph-editor-locked-figures.test.tsx
@@ -1079,7 +1079,7 @@ describe("InteractiveGraphEditor locked figures", () => {
lockedFigures: [
expect.objectContaining({
type: "polygon",
- points: [...defaultPolygon.points, [0, 0]],
+ points: [...defaultPolygon.points, {coord: [0, 0]}],
}),
],
}),
@@ -1091,10 +1091,10 @@ describe("InteractiveGraphEditor locked figures", () => {
const onChangeMock = jest.fn();
const squarePolygonPoints = [
- [-9, 4],
- [-6, 4],
- [-6, 1],
- [-9, 1],
+ {coord: [-9, 4]},
+ {coord: [-6, 4]},
+ {coord: [-6, 1]},
+ {coord: [-9, 1]},
];
renderEditor({
@@ -1119,7 +1119,11 @@ describe("InteractiveGraphEditor locked figures", () => {
lockedFigures: [
expect.objectContaining({
type: "polygon",
- points: squarePolygonPoints.slice(1),
+ points: [
+ {coord: [-6, 4]},
+ {coord: [-6, 1]},
+ {coord: [-9, 1]},
+ ],
}),
],
}),
@@ -1149,9 +1153,9 @@ describe("InteractiveGraphEditor locked figures", () => {
expect.objectContaining({
type: "polygon",
points: [
- [7, 2],
- [-1, 0],
- [1, 0],
+ {coord: [7, 2]},
+ {coord: [-1, 0]},
+ {coord: [1, 0]},
],
}),
],
@@ -1182,9 +1186,9 @@ describe("InteractiveGraphEditor locked figures", () => {
expect.objectContaining({
type: "polygon",
points: [
- [0, 7],
- [-1, 0],
- [1, 0],
+ {coord: [0, 7]},
+ {coord: [-1, 0]},
+ {coord: [1, 0]},
],
}),
],
diff --git a/packages/perseus-editor/src/widgets/interactive-graph-editor/locked-figures/locked-polygon-settings.test.tsx b/packages/perseus-editor/src/widgets/interactive-graph-editor/locked-figures/locked-polygon-settings.test.tsx
index 438b67fac9a..8682dfc16d8 100644
--- a/packages/perseus-editor/src/widgets/interactive-graph-editor/locked-figures/locked-polygon-settings.test.tsx
+++ b/packages/perseus-editor/src/widgets/interactive-graph-editor/locked-figures/locked-polygon-settings.test.tsx
@@ -47,10 +47,10 @@ describe("LockedPolygonSettings", () => {
,
{
@@ -119,10 +119,10 @@ describe("LockedPolygonSettings", () => {
,
{
@@ -185,10 +185,10 @@ describe("LockedPolygonSettings", () => {
labels={[initialLabel]}
onChangeProps={onChangeSpy}
points={[
- [1, 1],
- [2, 1],
- [2, 2],
- [1, 2],
+ {coord: [1, 1]},
+ {coord: [2, 1]},
+ {coord: [2, 2]},
+ {coord: [1, 2]},
]}
/>,
{
@@ -204,10 +204,10 @@ describe("LockedPolygonSettings", () => {
expect(onChangeSpy).toHaveBeenCalledWith({
labels: [{...initialLabel, coord: [0, 1]}],
points: [
- [1, 2],
- [2, 2],
- [2, 3],
- [1, 3],
+ {coord: [1, 2]},
+ {coord: [2, 2]},
+ {coord: [2, 3]},
+ {coord: [1, 3]},
],
});
});
@@ -228,10 +228,10 @@ describe("LockedPolygonSettings", () => {
labels={[initialLabel]}
onChangeProps={onChangeSpy}
points={[
- [1, 1],
- [2, 1],
- [2, 2],
- [1, 2],
+ {coord: [1, 1]},
+ {coord: [2, 1]},
+ {coord: [2, 2]},
+ {coord: [1, 2]},
]}
/>,
{
@@ -247,10 +247,10 @@ describe("LockedPolygonSettings", () => {
expect(onChangeSpy).toHaveBeenCalledWith({
labels: [{...initialLabel, coord: [0, -1]}],
points: [
- [1, 0],
- [2, 0],
- [2, 1],
- [1, 1],
+ {coord: [1, 0]},
+ {coord: [2, 0]},
+ {coord: [2, 1]},
+ {coord: [1, 1]},
],
});
});
@@ -271,10 +271,10 @@ describe("LockedPolygonSettings", () => {
onChangeProps={onChangeSpy}
labels={[initialLabel]}
points={[
- [1, 1],
- [2, 1],
- [2, 2],
- [1, 2],
+ {coord: [1, 1]},
+ {coord: [2, 1]},
+ {coord: [2, 2]},
+ {coord: [1, 2]},
]}
/>,
{
@@ -290,10 +290,10 @@ describe("LockedPolygonSettings", () => {
expect(onChangeSpy).toHaveBeenCalledWith({
labels: [{...initialLabel, coord: [-1, 0]}],
points: [
- [0, 1],
- [1, 1],
- [1, 2],
- [0, 2],
+ {coord: [0, 1]},
+ {coord: [1, 1]},
+ {coord: [1, 2]},
+ {coord: [0, 2]},
],
});
});
@@ -314,10 +314,10 @@ describe("LockedPolygonSettings", () => {
onChangeProps={onChangeSpy}
labels={[initialLabel]}
points={[
- [1, 1],
- [2, 1],
- [2, 2],
- [1, 2],
+ {coord: [1, 1]},
+ {coord: [2, 1]},
+ {coord: [2, 2]},
+ {coord: [1, 2]},
]}
/>,
{
@@ -333,10 +333,10 @@ describe("LockedPolygonSettings", () => {
expect(onChangeSpy).toHaveBeenCalledWith({
labels: [{...initialLabel, coord: [1, 0]}],
points: [
- [2, 1],
- [3, 1],
- [3, 2],
- [2, 2],
+ {coord: [2, 1]},
+ {coord: [3, 1]},
+ {coord: [3, 2]},
+ {coord: [2, 2]},
],
});
});
@@ -407,7 +407,7 @@ describe("LockedPolygonSettings", () => {
render(
({coord}))}
labels={[
{
...defaultLabel,
@@ -433,7 +433,7 @@ describe("LockedPolygonSettings", () => {
// Assert
expect(onChangeProps).toHaveBeenCalledWith({
- points: expectedCoords,
+ points: expectedCoords.map((coord) => ({coord})),
labels: [
{
...defaultLabel,
@@ -542,11 +542,7 @@ describe("LockedPolygonSettings", () => {
render(
{
render(
,
@@ -663,11 +655,7 @@ describe("LockedPolygonSettings", () => {
render(
{
render(
) => void;
};
@@ -78,8 +77,9 @@ const LockedPolygonSettings = (props: Props) => {
// Add the coordinates of each point to the aria label
const pointsList = await Promise.all(
- points.map(async ([x, y]) => {
+ points.map(async (point) => {
// Ensure negative values are read correctly within aria labels.
+ const [x, y] = point.coord;
const spokenX = await generateSpokenMathDetails(`$${x}$`);
const spokenY = await generateSpokenMathDetails(`$${y}$`);
return `${spokenX} comma ${spokenY}`;
@@ -115,7 +115,10 @@ const LockedPolygonSettings = (props: Props) => {
switch (movement) {
case "up":
onChangeProps({
- points: points.map(([x, y]) => [x, y + 1]),
+ points: points.map((point) => ({
+ ...point,
+ coord: [point.coord[0], point.coord[1] + 1],
+ })),
labels: labels.map((label) => ({
...label,
coord: [label.coord[0], label.coord[1] + 1],
@@ -124,7 +127,10 @@ const LockedPolygonSettings = (props: Props) => {
break;
case "down":
onChangeProps({
- points: points.map(([x, y]) => [x, y - 1]),
+ points: points.map((point) => ({
+ ...point,
+ coord: [point.coord[0], point.coord[1] - 1],
+ })),
labels: labels.map((label) => ({
...label,
coord: [label.coord[0], label.coord[1] - 1],
@@ -133,7 +139,10 @@ const LockedPolygonSettings = (props: Props) => {
break;
case "left":
onChangeProps({
- points: points.map(([x, y]) => [x - 1, y]),
+ points: points.map((point) => ({
+ ...point,
+ coord: [point.coord[0] - 1, point.coord[1]],
+ })),
labels: labels.map((label) => ({
...label,
coord: [label.coord[0] - 1, label.coord[1]],
@@ -142,7 +151,10 @@ const LockedPolygonSettings = (props: Props) => {
break;
case "right":
onChangeProps({
- points: points.map(([x, y]) => [x + 1, y]),
+ points: points.map((point) => ({
+ ...point,
+ coord: [point.coord[0] + 1, point.coord[1]],
+ })),
labels: labels.map((label) => ({
...label,
coord: [label.coord[0] + 1, label.coord[1]],
@@ -282,11 +294,14 @@ const LockedPolygonSettings = (props: Props) => {
>{`${pointLabel}:`}
{
+ onChange={(newValue) => {
const newPoints = [...points];
- newPoints[index] = newValue;
+ newPoints[index] = {
+ ...point,
+ coord: newValue,
+ };
props.onChangeProps({points: newPoints});
}}
/>
@@ -301,10 +316,11 @@ const LockedPolygonSettings = (props: Props) => {
kind="tertiary"
actionType="destructive"
onClick={() => {
- const newPoints = [...points];
- newPoints.splice(index, 1);
props.onChangeProps({
- points: newPoints,
+ points: points.filter(
+ (_, pointIndex) =>
+ pointIndex !== index,
+ ),
});
}}
style={styles.icon}
@@ -320,7 +336,7 @@ const LockedPolygonSettings = (props: Props) => {
startIcon={plusCircle}
onClick={() => {
props.onChangeProps({
- points: [...points, [0, 0]],
+ points: [...points, {coord: [0, 0]}],
});
}}
>
@@ -402,10 +418,10 @@ const LockedPolygonSettings = (props: Props) => {
const newLabel = {
...getDefaultFigureForType("label"),
coord: [
- points[0][0],
+ points[0].coord[0],
// Additional vertical offset for each
// label so they don't overlap.
- points[0][1] - labels.length,
+ points[0].coord[1] - labels.length,
],
// Default to the same color as the ellipse
color: color,
diff --git a/packages/perseus-linter/src/rules/interactive-graph-widget-error.test.ts b/packages/perseus-linter/src/rules/interactive-graph-widget-error.test.ts
index 62326c39462..c7eb3894f49 100644
--- a/packages/perseus-linter/src/rules/interactive-graph-widget-error.test.ts
+++ b/packages/perseus-linter/src/rules/interactive-graph-widget-error.test.ts
@@ -51,9 +51,9 @@ describe("interactive-graph-widget-error", () => {
lockedFigures: [
generateIGLockedPolygon({
points: [
- [0, 0],
- [0, 0],
- [0, 0],
+ {coord: [0, 0]},
+ {coord: [0, 0]},
+ {coord: [0, 0]},
],
}),
],
@@ -153,9 +153,9 @@ describe("interactive-graph-widget-error", () => {
}),
generateIGLockedPolygon({
points: [
- [0, 0],
- [0, 2],
- [1, 1],
+ {coord: [0, 0]},
+ {coord: [0, 2]},
+ {coord: [1, 1]},
],
}),
generateIGLockedEllipse({radius: [2, 2]}),
diff --git a/packages/perseus-linter/src/rules/interactive-graph-widget-error.ts b/packages/perseus-linter/src/rules/interactive-graph-widget-error.ts
index 7172ad8cbc4..a9e6d21c50c 100644
--- a/packages/perseus-linter/src/rules/interactive-graph-widget-error.ts
+++ b/packages/perseus-linter/src/rules/interactive-graph-widget-error.ts
@@ -38,12 +38,11 @@ export default Rule.makeRule({
// A locked polygon can't have all coordinates be the same.
if (figure.type === "polygon") {
+ const coords = figure.points.map((point) => point.coord);
if (
// If every point is the same as the first point,
// then all the points are the same.
- figure.points.every((point) =>
- kvector.equal(point, figure.points[0]),
- )
+ coords.every((point) => kvector.equal(point, coords[0]))
) {
issues.push(
"Locked polygon cannot have all coordinates be the same.",
diff --git a/packages/perseus/src/widgets/interactive-graphs/__docs__/interactive-graph-initial-state-regression.stories.tsx b/packages/perseus/src/widgets/interactive-graphs/__docs__/interactive-graph-initial-state-regression.stories.tsx
index 84fc20c9a17..43be5439a9d 100644
--- a/packages/perseus/src/widgets/interactive-graphs/__docs__/interactive-graph-initial-state-regression.stories.tsx
+++ b/packages/perseus/src/widgets/interactive-graphs/__docs__/interactive-graph-initial-state-regression.stories.tsx
@@ -539,10 +539,10 @@ function lockedFiguresWithWeight(
}),
generateIGLockedPolygon({
points: [
- [-7.5, -3.5],
- [-6.5, -2.5],
- [-5.5, -3.5],
- [-6.5, -4.5],
+ {coord: [-7.5, -3.5]},
+ {coord: [-6.5, -2.5]},
+ {coord: [-5.5, -3.5]},
+ {coord: [-6.5, -4.5]},
],
weight,
color: "pink",
diff --git a/packages/perseus/src/widgets/interactive-graphs/interactive-graph.test.tsx b/packages/perseus/src/widgets/interactive-graphs/interactive-graph.test.tsx
index 81e55d3075f..1b8c1124134 100644
--- a/packages/perseus/src/widgets/interactive-graphs/interactive-graph.test.tsx
+++ b/packages/perseus/src/widgets/interactive-graphs/interactive-graph.test.tsx
@@ -1236,9 +1236,9 @@ describe("Interactive Graph", function () {
lockedFigures: [
generateIGLockedPolygon({
points: [
- [0, 0],
- [0, 1],
- [1, 1],
+ {coord: [0, 0]},
+ {coord: [0, 1]},
+ {coord: [1, 1]},
],
weight: weight,
}),
@@ -1352,9 +1352,9 @@ describe("Interactive Graph", function () {
lockedFigures: [
generateIGLockedPolygon({
points: [
- [0, 0],
- [0, 1],
- [1, 1],
+ {coord: [0, 0]},
+ {coord: [0, 1]},
+ {coord: [1, 1]},
],
ariaLabel: "Polygon A",
}),
@@ -1380,9 +1380,9 @@ describe("Interactive Graph", function () {
lockedFigures: [
generateIGLockedPolygon({
points: [
- [0, 0],
- [0, 1],
- [1, 1],
+ {coord: [0, 0]},
+ {coord: [0, 1]},
+ {coord: [1, 1]},
],
}),
],
diff --git a/packages/perseus/src/widgets/interactive-graphs/interactive-graph.testdata.ts b/packages/perseus/src/widgets/interactive-graphs/interactive-graph.testdata.ts
index 052ae6fab45..0f1bee625fe 100644
--- a/packages/perseus/src/widgets/interactive-graphs/interactive-graph.testdata.ts
+++ b/packages/perseus/src/widgets/interactive-graphs/interactive-graph.testdata.ts
@@ -861,18 +861,14 @@ export const segmentWithLockedPolygons: PerseusRenderer =
correct: generateIGSegmentGraph(),
lockedFigures: [
generateIGLockedPolygon({
- points: [
- [-3, 4],
- [-5, 1],
- [-1, 1],
- ],
+ points: [{coord: [-3, 4]}, {coord: [-5, 1]}, {coord: [-1, 1]}],
}),
generateIGLockedPolygon({
points: [
- [1, 4],
- [4, 4],
- [4, 1],
- [1, 1],
+ {coord: [1, 4]},
+ {coord: [4, 4]},
+ {coord: [4, 1]},
+ {coord: [1, 1]},
],
color: "green",
showVertices: true,
@@ -881,11 +877,11 @@ export const segmentWithLockedPolygons: PerseusRenderer =
}),
generateIGLockedPolygon({
points: [
- [0, -1],
- [-2, -3],
- [-1, -5],
- [1, -5],
- [2, -3],
+ {coord: [0, -1]},
+ {coord: [-2, -3]},
+ {coord: [-1, -5]},
+ {coord: [1, -5]},
+ {coord: [2, -3]},
],
color: "purple",
showVertices: false,
@@ -900,20 +896,12 @@ export const segmentWithLockedPolygonWhite: PerseusRenderer =
correct: generateIGSegmentGraph(),
lockedFigures: [
generateIGLockedPolygon({
- points: [
- [0, 3],
- [-3, 0],
- [3, 0],
- ],
+ points: [{coord: [0, 3]}, {coord: [-3, 0]}, {coord: [3, 0]}],
color: "green",
fillStyle: "white",
}),
generateIGLockedPolygon({
- points: [
- [-5, 0],
- [-3, -1],
- [3, -1],
- ],
+ points: [{coord: [-5, 0]}, {coord: [-3, -1]}, {coord: [3, -1]}],
color: "pink",
fillStyle: "translucent",
}),
@@ -1012,10 +1000,10 @@ export const staticGraphQuestion: PerseusRenderer =
}),
generateIGLockedPolygon({
points: [
- [-9, 4],
- [-6, 4],
- [-6, 1],
- [-9, 1],
+ {coord: [-9, 4]},
+ {coord: [-6, 4]},
+ {coord: [-6, 1]},
+ {coord: [-9, 1]},
],
color: "pink",
}),
@@ -1050,10 +1038,10 @@ export const staticGraphQuestionWithAnotherWidget: () => PerseusRenderer =
}),
generateIGLockedPolygon({
points: [
- [-9, 4],
- [-6, 4],
- [-6, 1],
- [-9, 1],
+ {coord: [-9, 4]},
+ {coord: [-6, 4]},
+ {coord: [-6, 1]},
+ {coord: [-9, 1]},
],
color: "pink",
}),
@@ -1168,11 +1156,7 @@ export const graphWithLabeledPolygon: PerseusRenderer =
correct: generateIGSegmentGraph(),
lockedFigures: [
generateIGLockedPolygon({
- points: [
- [0, 0],
- [4, 0],
- [2, 4],
- ],
+ points: [{coord: [0, 0]}, {coord: [4, 0]}, {coord: [2, 4]}],
labels: [generateIGLockedLabel({text: "E", coord: [0, 0]})],
}),
],
diff --git a/packages/perseus/src/widgets/interactive-graphs/locked-figures/locked-polygon.tsx b/packages/perseus/src/widgets/interactive-graphs/locked-figures/locked-polygon.tsx
index eef5a0cdb4b..2514a953922 100644
--- a/packages/perseus/src/widgets/interactive-graphs/locked-figures/locked-polygon.tsx
+++ b/packages/perseus/src/widgets/interactive-graphs/locked-figures/locked-polygon.tsx
@@ -25,7 +25,7 @@ const LockedPolygon = (props: LockedPolygonType) => {
role="img"
>
coord)]}
fillOpacity={lockedFigureFillStyles[fillStyle]}
strokeStyle={strokeStyle}
color={lockedFigureColors[color]}
@@ -46,8 +46,8 @@ const LockedPolygon = (props: LockedPolygonType) => {
points.map((point, index) => (
))}