@khanacademy/perseus 45.0.0 → 45.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.
@@ -5,9 +5,30 @@
5
5
  *
6
6
  * TODO(aria): Move this out of interactive2
7
7
  */
8
- declare const _default: {
9
- pluck: (table: any, subKey: string) => any;
10
- mapObject: <K extends string, V, U>(obj: Record<K, V>, lambda: (arg1: V, arg2: K) => U) => Record<K, U>;
11
- mapObjectFromArray: <K extends string, V>(arr: ReadonlyArray<K>, lambda: (arg1: K) => V) => Record<K, V>;
12
- };
13
- export default _default;
8
+ /**
9
+ * Does a pluck on keys inside objects in an object
10
+ *
11
+ * Ex:
12
+ * tools = {
13
+ * translation: {
14
+ * enabled: true
15
+ * },
16
+ * rotation: {
17
+ * enabled: false
18
+ * }
19
+ * };
20
+ * pluckObject(tools, "enabled") returns {
21
+ * translation: true
22
+ * rotation: false
23
+ * }
24
+ */
25
+ export declare const pluck: (table: any, subKey: string) => any;
26
+ /**
27
+ * Maps an object to an object
28
+ *
29
+ * > mapObject({a: '1', b: '2'}, (value, key) => {
30
+ * return value + 1;
31
+ * });
32
+ * {a: 2, b: 3}
33
+ */
34
+ export declare const mapObject: <K extends string, V, U>(obj: Record<K, V>, lambda: (arg1: V, arg2: K) => U) => Record<K, U>;
@@ -4,72 +4,99 @@ export type Range = Interval;
4
4
  export type Size = [number, number];
5
5
  export type CollinearTuple = [vec.Vector2, vec.Vector2];
6
6
  export type ShowSolutions = "all" | "selected" | "none";
7
+ /**
8
+ * Our core set of Perseus widgets.
9
+ *
10
+ * This interface is the basis for "registering" all Perseus widget types.
11
+ * There should be one key/value pair for each supported widget. If you create
12
+ * a new widget, an entry should be added to this interface. Note that this
13
+ * only registers the widget options type, you'll also need to register the
14
+ * widget so that it's available at runtime (@see
15
+ * {@link file://./widgets.ts#registerWidget}).
16
+ *
17
+ * Importantly, the key should be the name that is used in widget IDs. For most
18
+ * widgets that is the same as the widget option's `type` field. In cases where
19
+ * a widget has been deprecated and replaced with the deprecated-standin
20
+ * widget, it should be the original widget type!
21
+ *
22
+ * If you define the widget outside of this package, you can still add the new
23
+ * widget to this interface by writing the following in that package that
24
+ * contains the widget. TypeScript will merge that definition of the
25
+ * `PerseusWidgets` with the one defined below.
26
+ *
27
+ * ```typescript
28
+ * declare module "@khanacademy/perseus" {
29
+ * interface PerseusWidgetTypes {
30
+ * // A new widget
31
+ * "new-awesomeness": MyAwesomeNewWidget;
32
+ *
33
+ * // A deprecated widget
34
+ * "super-old-widget": AutoCorrectWidget;
35
+ * }
36
+ * }
37
+ *
38
+ * // The new widget's options definition
39
+ * type MyAwesomeNewWidget = WidgetOptions<'new-awesomeness', MyAwesomeNewWidgetOptions>;
40
+ *
41
+ * // The deprecated widget's options definition
42
+ * type SuperOldWidget = WidgetOptions<'super-old-widget', object>;
43
+ * ```
44
+ *
45
+ * This interface can be extended through the magic of TypeScript "Declaration
46
+ * merging". Specifically, we augment this module and extend this interface.
47
+ *
48
+ * @see {@link https://www.typescriptlang.org/docs/handbook/declaration-merging.html#module-augmentation}
49
+ */
50
+ export interface PerseusWidgetTypes {
51
+ categorizer: CategorizerWidget;
52
+ "cs-program": CSProgramWidget;
53
+ definition: DefinitionWidget;
54
+ dropdown: DropdownWidget;
55
+ explanation: ExplanationWidget;
56
+ expression: ExpressionWidget;
57
+ grapher: GrapherWidget;
58
+ "graded-group-set": GradedGroupSetWidget;
59
+ "graded-group": GradedGroupWidget;
60
+ group: GroupWidget;
61
+ iframe: IFrameWidget;
62
+ image: ImageWidget;
63
+ "input-number": InputNumberWidget;
64
+ interaction: InteractionWidget;
65
+ "interactive-graph": InteractiveGraphWidget;
66
+ "label-image": LabelImageWidget;
67
+ matcher: MatcherWidget;
68
+ matrix: MatrixWidget;
69
+ measurer: MeasurerWidget;
70
+ "molecule-renderer": MoleculeRendererWidget;
71
+ "number-line": NumberLineWidget;
72
+ "numeric-input": NumericInputWidget;
73
+ orderer: OrdererWidget;
74
+ "passage-ref-target": RefTargetWidget;
75
+ "passage-ref": PassageRefWidget;
76
+ passage: PassageWidget;
77
+ "phet-simulation": PhetSimulationWidget;
78
+ "python-program": PythonProgramWidget;
79
+ plotter: PlotterWidget;
80
+ radio: RadioWidget;
81
+ sorter: SorterWidget;
82
+ table: TableWidget;
83
+ video: VideoWidget;
84
+ sequence: AutoCorrectWidget;
85
+ }
86
+ /**
87
+ * A map of widget IDs to widget options. This is most often used as the type
88
+ * for a set of widgets defined in a `PerseusItem` but can also be useful to
89
+ * represent a function parameter where only `widgets` from a `PerseusItem` are
90
+ * needed. Today Widget IDs are made up of the widget type and an incrementing
91
+ * integer (eg. `interactive-graph 1` or `radio 3`). It is suggested to avoid
92
+ * reading/parsing the widget id to derive any information from it, except in
93
+ * the case of this map.
94
+ *
95
+ * @see {@link PerseusWidgetTypes} additional widgets can be added to this map type
96
+ * by augmenting the PerseusWidgetTypes with new widget types!
97
+ */
7
98
  export type PerseusWidgetsMap = {
8
- [key in `categorizer ${number}`]: CategorizerWidget;
9
- } & {
10
- [key in `cs-program ${number}`]: CSProgramWidget;
11
- } & {
12
- [key in `definition ${number}`]: DefinitionWidget;
13
- } & {
14
- [key in `dropdown ${number}`]: DropdownWidget;
15
- } & {
16
- [key in `explanation ${number}`]: ExplanationWidget;
17
- } & {
18
- [key in `expression ${number}`]: ExpressionWidget;
19
- } & {
20
- [key in `grapher ${number}`]: GrapherWidget;
21
- } & {
22
- [key in `group ${number}`]: GroupWidget;
23
- } & {
24
- [key in `graded-group ${number}`]: GradedGroupWidget;
25
- } & {
26
- [key in `graded-group-set ${number}`]: GradedGroupSetWidget;
27
- } & {
28
- [key in `iframe ${number}`]: IFrameWidget;
29
- } & {
30
- [key in `image ${number}`]: ImageWidget;
31
- } & {
32
- [key in `input-number ${number}`]: InputNumberWidget;
33
- } & {
34
- [key in `interaction ${number}`]: InteractionWidget;
35
- } & {
36
- [key in `interactive-graph ${number}`]: InteractiveGraphWidget;
37
- } & {
38
- [key in `label-image ${number}`]: LabelImageWidget;
39
- } & {
40
- [key in `matcher ${number}`]: MatcherWidget;
41
- } & {
42
- [key in `matrix ${number}`]: MatrixWidget;
43
- } & {
44
- [key in `measurer ${number}`]: MeasurerWidget;
45
- } & {
46
- [key in `molecule-renderer ${number}`]: MoleculeRendererWidget;
47
- } & {
48
- [key in `number-line ${number}`]: NumberLineWidget;
49
- } & {
50
- [key in `numeric-input ${number}`]: NumericInputWidget;
51
- } & {
52
- [key in `orderer ${number}`]: OrdererWidget;
53
- } & {
54
- [key in `passage ${number}`]: PassageWidget;
55
- } & {
56
- [key in `passage-ref ${number}`]: PassageRefWidget;
57
- } & {
58
- [key in `passage-ref-target ${number}`]: PassageRefWidget;
59
- } & {
60
- [key in `phet-simulation ${number}`]: PhetSimulationWidget;
61
- } & {
62
- [key in `plotter ${number}`]: PlotterWidget;
63
- } & {
64
- [key in `python-program ${number}`]: PythonProgramWidget;
65
- } & {
66
- [key in `radio ${number}`]: RadioWidget;
67
- } & {
68
- [key in `sorter ${number}`]: SorterWidget;
69
- } & {
70
- [key in `table ${number}`]: TableWidget;
71
- } & {
72
- [key in `video ${number}`]: VideoWidget;
99
+ [Property in keyof PerseusWidgetTypes as `${Property} ${number}`]: PerseusWidgetTypes[Property];
73
100
  };
74
101
  /**
75
102
  * A "PerseusItem" is a classic Perseus item. It is rendered by the
@@ -101,6 +128,9 @@ export type PerseusArticle = PerseusRenderer | ReadonlyArray<PerseusRenderer>;
101
128
  * A "MultiItem" is an advanced Perseus item. It is rendered by the
102
129
  * `MultiRenderer` and you can control the layout of individual parts of the
103
130
  * item.
131
+ *
132
+ * @deprecated MultiItem support is slated for removal in a future Perseus
133
+ * release.
104
134
  */
105
135
  export type MultiItem = {
106
136
  _multi: any;
@@ -110,11 +140,25 @@ export type Version = {
110
140
  minor: number;
111
141
  };
112
142
  export type PerseusRenderer = {
143
+ /**
144
+ * Translatable Markdown content to be rendered. May include references to
145
+ * widgets (as [[☃ widgetName]]) or images (as ![image text](imageUrl)).
146
+ * For each image found in this content, there can be an entry in the
147
+ * `images` dict (below) with the key being the image's url which defines
148
+ * additional attributes for the image.
149
+ */
113
150
  content: string;
151
+ /**
152
+ * A dictionary of {[widgetName]: Widget} to be referenced from the content
153
+ * field.
154
+ */
114
155
  widgets: PerseusWidgetsMap;
115
156
  metadata?: ReadonlyArray<string>;
157
+ /**
158
+ * A dictionary of {[imageUrl]: PerseusImageDetail}.
159
+ */
116
160
  images: {
117
- [key: string]: PerseusImageDetail;
161
+ [imageUrl: string]: PerseusImageDetail;
118
162
  };
119
163
  };
120
164
  export type Hint = PerseusRenderer & {
@@ -131,6 +175,10 @@ export type PerseusImageDetail = {
131
175
  };
132
176
  export declare const ItemExtras: readonly ["calculator", "chi2Table", "financialCalculatorMonthlyPayment", "financialCalculatorTotalAmount", "financialCalculatorTimeToPayOff", "periodicTable", "periodicTableWithKey", "tTable", "zTable"];
133
177
  export type PerseusAnswerArea = Record<(typeof ItemExtras)[number], boolean>;
178
+ /**
179
+ * The type representing the common structure of all widget's options. The
180
+ * `Options` generic type represents the widget-specific option data.
181
+ */
134
182
  export type WidgetOptions<Type extends string, Options> = {
135
183
  type: Type;
136
184
  static?: boolean;
@@ -173,8 +221,11 @@ export type InputNumberWidget = WidgetOptions<'input-number', PerseusInputNumber
173
221
  export type MoleculeRendererWidget = WidgetOptions<'molecule-renderer', PerseusMoleculeRendererWidgetOptions>;
174
222
  export type RefTargetWidget = WidgetOptions<'passage-ref-target', PerseusPassageRefTargetWidgetOptions>;
175
223
  export type VideoWidget = WidgetOptions<'video', PerseusVideoWidgetOptions>;
176
- export type AutoCorrectWidget = WidgetOptions<'deprecated-standin', PerseusWidgetOptions>;
224
+ export type AutoCorrectWidget = WidgetOptions<'deprecated-standin', object>;
177
225
  export type PerseusWidget = CategorizerWidget | CSProgramWidget | DefinitionWidget | DropdownWidget | ExplanationWidget | ExpressionWidget | GradedGroupSetWidget | GradedGroupWidget | GrapherWidget | GroupWidget | IFrameWidget | ImageWidget | InputNumberWidget | InteractionWidget | InteractiveGraphWidget | LabelImageWidget | MatcherWidget | MatrixWidget | MeasurerWidget | MoleculeRendererWidget | NumberLineWidget | NumericInputWidget | OrdererWidget | PassageRefWidget | PassageWidget | PhetSimulationWidget | PlotterWidget | PythonProgramWidget | RadioWidget | RefTargetWidget | SorterWidget | TableWidget | VideoWidget | AutoCorrectWidget;
226
+ /**
227
+ * A background image applied to various widgets.
228
+ */
178
229
  export type PerseusImageBackground = {
179
230
  url: string | null | undefined;
180
231
  width?: number;
@@ -334,8 +385,8 @@ export type PerseusImageLabel = {
334
385
  };
335
386
  export type PerseusInteractiveGraphWidgetOptions = {
336
387
  step: [number, number];
337
- gridStep: [number, number];
338
- snapStep: [number, number];
388
+ gridStep?: [x: number, y: number];
389
+ snapStep?: [x: number, y: number];
339
390
  backgroundImage?: PerseusImageBackground;
340
391
  /**
341
392
  * The type of markings to display on the graph.
@@ -344,7 +395,7 @@ export type PerseusInteractiveGraphWidgetOptions = {
344
395
  * - none: shows no markings
345
396
  */
346
397
  markings: "graph" | "grid" | "none";
347
- labels: ReadonlyArray<string>;
398
+ labels?: ReadonlyArray<string>;
348
399
  showProtractor: boolean;
349
400
  /**
350
401
  * Whether to show the Ruler tool overlayed on top of the graph.
@@ -621,7 +672,7 @@ export type PerseusNumericInputAnswerForm = {
621
672
  };
622
673
  export type PerseusNumericInputWidgetOptions = {
623
674
  answers: ReadonlyArray<PerseusNumericInputAnswer>;
624
- labelText: string;
675
+ labelText?: string | undefined;
625
676
  size: string;
626
677
  coefficient: boolean;
627
678
  rightAlign?: boolean;
@@ -630,7 +681,7 @@ export type PerseusNumericInputWidgetOptions = {
630
681
  };
631
682
  export type PerseusNumericInputAnswer = {
632
683
  message: string;
633
- value: number;
684
+ value?: number;
634
685
  status: string;
635
686
  answerForms?: ReadonlyArray<MathFormat>;
636
687
  strict: boolean;
@@ -192,9 +192,15 @@ declare class Renderer extends React.Component<Props, State> implements GetPromp
192
192
  blurPath: (path: FocusPath) => void;
193
193
  blur: () => void;
194
194
  serialize: () => Record<any, any>;
195
+ /**
196
+ * Returns an array of widget ids that are empty (meaning widgets where the
197
+ * learner has not interacted with the widget yet or has not filled in all
198
+ * fields). For example, the `interactive-graph` widget is considered
199
+ * empty if the graph is in the starting state.
200
+ */
195
201
  emptyWidgets(): ReadonlyArray<string>;
196
202
  _setWidgetProps: SetWidgetPropsFn;
197
- setInputValue: (path: FocusPath, newValue: string, focus?: () => unknown) => void;
203
+ setInputValue: (path: FocusPath, newValue: string, cb?: () => void) => void;
198
204
  /**
199
205
  * Returns an array of the widget `.getUserInput()` results
200
206
  *
package/dist/types.d.ts CHANGED
@@ -46,6 +46,12 @@ export interface Widget {
46
46
  } | boolean;
47
47
  getDOMNodeForPath?: (path: FocusPath) => Element | Text | null;
48
48
  deselectIncorrectSelectedChoices?: () => void;
49
+ /**
50
+ * Returns widget state that can be passed back to `restoreSerializedState`
51
+ * to put the widget back into exactly the same state. If the widget does
52
+ * not implement this function, the renderer simply returns all of the
53
+ * widget's props.
54
+ */
49
55
  getSerializedState?: () => SerializedState;
50
56
  restoreSerializedState?: (props: any, callback: () => void) => any;
51
57
  blurInputPath?: (path: FocusPath) => void;
@@ -103,7 +109,7 @@ export type ChangeHandler = (arg1: {
103
109
  selected?: number;
104
110
  plot?: any;
105
111
  graph?: PerseusGraphType;
106
- }, callback?: () => unknown | null | undefined, silent?: boolean) => unknown;
112
+ }, callback?: () => void, silent?: boolean) => unknown;
107
113
  export type ImageUploader = (file: File, callback: (url: string) => unknown) => unknown;
108
114
  export type Path = ReadonlyArray<string>;
109
115
  type StubTagEditorType = any;
@@ -297,6 +303,17 @@ type InitialRequestUrlInterface = {
297
303
  protocol: string;
298
304
  };
299
305
  export type VideoKind = "YOUTUBE_ID" | "READABLE_ID";
306
+ /**
307
+ * An object for dependency injection, to allow different clients
308
+ * to provide different methods for logging, translation, network
309
+ * requests, etc.
310
+ *
311
+ * NOTE: You should avoid adding new dependencies here as this type was added
312
+ * as a quick fix to get around the fact that some of the dependencies Perseus
313
+ * needs are used in places where neither `APIOptions` nor a React Context
314
+ * could be used. Aim to shrink the footprint of PerseusDependencies and try to
315
+ * use alternative methods where possible.
316
+ */
300
317
  export type PerseusDependencies = {
301
318
  JIPT: JIPT;
302
319
  graphieMovablesJiptLabels: JiptLabelStore;
@@ -353,6 +370,11 @@ type TrackingSequenceExtraArguments = {
353
370
  };
354
371
  export type Alignment = "default" | "block" | "inline-block" | "inline" | "float-left" | "float-right" | "full-width";
355
372
  type WidgetOptions = any;
373
+ /**
374
+ * A transform that maps the WidgetOptions (sometimes referred to as
375
+ * EditorProps) to the props used to render the widget. Often this is an
376
+ * identity transform.
377
+ */
356
378
  export type WidgetTransform = (arg1: WidgetOptions, strings: PerseusStrings, problemNumber?: number) => any;
357
379
  export type WidgetScorerFunction = (userInput: UserInput, rubric: Rubric, string?: PerseusStrings, locale?: string) => PerseusScore;
358
380
  export type WidgetExports<T extends React.ComponentType<any> & Widget = React.ComponentType<any>> = Readonly<{
@@ -364,11 +386,12 @@ export type WidgetExports<T extends React.ComponentType<any> & Widget = React.Co
364
386
  /** Supresses widget from showing up in the dropdown in the content editor */
365
387
  hidden?: boolean;
366
388
  /**
367
- The widget version. Any time the _major_ version changes, the widget
368
- should provide a new entry in the propUpgrades map to migrate from the
369
- older version to the current (new) version. Minor version changes must
370
- be backwards compatible with previous minor versions widget options.
371
- This key defaults to `{major: 0, minor: 0}` if not provided.
389
+ * The widget version. Any time the _major_ version changes, the widget
390
+ * should provide a new entry in the propUpgrades map to migrate from the
391
+ * older version to the current (new) version. Minor version changes must
392
+ * be backwards compatible with previous minor versions widget options.
393
+ *
394
+ * This key defaults to `{major: 0, minor: 0}` if not provided.
372
395
  */
373
396
  version?: Version;
374
397
  supportedAlignments?: ReadonlyArray<Alignment>;
@@ -377,25 +400,44 @@ export type WidgetExports<T extends React.ComponentType<any> & Widget = React.Co
377
400
  isLintable?: boolean;
378
401
  tracking?: Tracking;
379
402
  traverseChildWidgets?: any;
380
- /** transforms the widget options to the props used to render the widget */
403
+ /**
404
+ * Transforms the widget options to the props used to render the widget.
405
+ */
381
406
  transform?: WidgetTransform;
382
- /** transforms the widget options to the props used to render the widget for
383
- static renders */
407
+ /**
408
+ * Transforms the widget options to the props used to render the widget for
409
+ * static renders.
410
+ */
384
411
  staticTransform?: WidgetTransform;
412
+ /**
413
+ * A function that scores user input (the guess) for the widget.
414
+ */
385
415
  scorer?: WidgetScorerFunction;
386
416
  getOneCorrectAnswerFromRubric?: (rubric: Rubric) => string | null | undefined;
387
417
  /**
388
- A map of major version numbers (as a string, eg "1") to a function that
389
- migrates from the _previous_ major version.
390
- Example:
391
- propUpgrades: {'1': (options) => ({...options})}
392
- would migrate from major version 0 to 1.
393
- */
418
+ * A map of major version numbers (as a string, eg "1") to a function that
419
+ * migrates from the _previous_ major version.
420
+ *
421
+ * Example:
422
+ * ```
423
+ * propUpgrades: {'1': (options) => ({...options})}
424
+ * ```
425
+ *
426
+ * This configuration would migrate options from major version 0 to 1.
427
+ */
394
428
  propUpgrades?: {
395
- [key: string]: (arg1: any) => any;
429
+ [targetMajorVersion: string]: (arg1: any) => any;
396
430
  };
397
431
  }>;
398
432
  export type FilterCriterion = string | ((id: string, widgetInfo: PerseusWidget, widget?: Widget | null | undefined) => boolean);
433
+ /**
434
+ * The full set of props provided to all widgets when they are rendered. The
435
+ * `RenderProps` generic argument are the widget-specific props that originate
436
+ * from the stored PerseusItem. Note that they may not match the serialized
437
+ * widget options exactly as they are the result of running the options through
438
+ * any `propUpgrades` the widget defines as well as its `transform` or
439
+ * `staticTransform` functions (depending on the options `static` flag).
440
+ */
399
441
  export type WidgetProps<RenderProps, Rubric = Empty, TrackingExtraArgs = Empty> = RenderProps & {
400
442
  widgetId: string;
401
443
  alignment: string | null | undefined;
@@ -0,0 +1,2 @@
1
+ import type { PartialParser } from "../parser-types";
2
+ export declare const stringToNumber: PartialParser<string | number, number>;
@@ -27,7 +27,7 @@
27
27
  * } & Perseus<Widget>ValidationData;
28
28
  * ```
29
29
  */
30
- import type { GrapherAnswerTypes, PerseusDropdownChoice, PerseusExpressionAnswerForm, PerseusGradedGroupSetWidgetOptions, PerseusGradedGroupWidgetOptions, PerseusGraphType, PerseusGroupWidgetOptions, PerseusMatcherWidgetOptions, PerseusMatrixWidgetAnswers, PerseusNumberLineWidgetOptions, PerseusNumericInputAnswer, PerseusOrdererWidgetOptions, PerseusRadioChoice, PerseusGraphCorrectType } from "./perseus-types";
30
+ import type { GrapherAnswerTypes, PerseusDropdownChoice, PerseusExpressionAnswerForm, PerseusGradedGroupSetWidgetOptions, PerseusGradedGroupWidgetOptions, PerseusGraphType, PerseusGroupWidgetOptions, PerseusMatcherWidgetOptions, PerseusMatrixWidgetAnswers, PerseusNumericInputAnswer, PerseusOrdererWidgetOptions, PerseusRadioChoice, PerseusGraphCorrectType } from "./perseus-types";
31
31
  import type { InteractiveMarkerType } from "./widgets/label-image/types";
32
32
  import type { Relationship } from "./widgets/number-line/number-line";
33
33
  export type UserInputStatus = "correct" | "incorrect" | "incomplete";
@@ -57,6 +57,7 @@ export type PerseusExpressionRubric = {
57
57
  };
58
58
  export type PerseusExpressionUserInput = string;
59
59
  export type PerseusGroupRubric = PerseusGroupWidgetOptions;
60
+ export type PerseusGroupUserInput = UserInputMap;
60
61
  export type PerseusGradedGroupRubric = PerseusGradedGroupWidgetOptions;
61
62
  export type PerseusGradedGroupSetRubric = PerseusGradedGroupSetWidgetOptions;
62
63
  export type PerseusGrapherRubric = {
@@ -99,7 +100,11 @@ export type PerseusMatrixValidationData = Empty;
99
100
  export type PerseusMatrixUserInput = {
100
101
  answers: PerseusMatrixRubric["answers"];
101
102
  };
102
- export type PerseusNumberLineRubric = PerseusNumberLineWidgetOptions & {
103
+ export type PerseusNumberLineScoringData = {
104
+ correctRel: string | null | undefined;
105
+ correctX: number;
106
+ range: ReadonlyArray<number>;
107
+ initialX: number | null | undefined;
103
108
  isInequality: boolean;
104
109
  };
105
110
  export type PerseusNumberLineUserInput = {
@@ -144,7 +149,7 @@ export type PerseusTableRubric = {
144
149
  answers: ReadonlyArray<ReadonlyArray<string>>;
145
150
  };
146
151
  export type PerseusTableUserInput = ReadonlyArray<ReadonlyArray<string>>;
147
- export type Rubric = PerseusCategorizerScoringData | PerseusCSProgramRubric | PerseusDropdownRubric | PerseusExpressionRubric | PerseusGroupRubric | PerseusGradedGroupRubric | PerseusGradedGroupSetRubric | PerseusGrapherRubric | PerseusIFrameRubric | PerseusInputNumberRubric | PerseusInteractiveGraphRubric | PerseusLabelImageRubric | PerseusMatcherRubric | PerseusMatrixRubric | PerseusNumberLineRubric | PerseusNumericInputRubric | PerseusOrdererRubric | PerseusPlotterScoringData | PerseusRadioRubric | PerseusSorterRubric | PerseusTableRubric;
152
+ export type Rubric = PerseusCategorizerScoringData | PerseusCSProgramRubric | PerseusDropdownRubric | PerseusExpressionRubric | PerseusGroupRubric | PerseusGradedGroupRubric | PerseusGradedGroupSetRubric | PerseusGrapherRubric | PerseusIFrameRubric | PerseusInputNumberRubric | PerseusInteractiveGraphRubric | PerseusLabelImageRubric | PerseusMatcherRubric | PerseusMatrixRubric | PerseusNumberLineScoringData | PerseusNumericInputRubric | PerseusOrdererRubric | PerseusPlotterScoringData | PerseusRadioRubric | PerseusSorterRubric | PerseusTableRubric;
148
153
  export type UserInput = PerseusCategorizerUserInput | PerseusCSProgramUserInput | PerseusDropdownUserInput | PerseusExpressionUserInput | PerseusGrapherUserInput | PerseusIFrameUserInput | PerseusInputNumberUserInput | PerseusInteractiveGraphUserInput | PerseusLabelImageUserInput | PerseusMatcherUserInput | PerseusMatrixUserInput | PerseusNumberLineUserInput | PerseusNumericInputUserInput | PerseusOrdererUserInput | PerseusPlotterUserInput | PerseusRadioUserInput | PerseusSorterUserInput | PerseusTableUserInput;
149
154
  export type UserInputMap = {
150
155
  [widgetId: string]: UserInput | UserInputMap;
@@ -1,7 +1,7 @@
1
1
  import React from "react";
2
2
  import { PerseusI18nContext } from "../../components/i18n-context";
3
3
  import type { Widget } from "../../types";
4
- type Props = any;
4
+ type Props = object;
5
5
  declare class DeprecatedStandin extends React.Component<Props> implements Widget {
6
6
  static contextType: React.Context<{
7
7
  strings: import("../../strings").PerseusStrings;
@@ -1,6 +1,7 @@
1
1
  import * as React from "react";
2
2
  import { PerseusI18nContext } from "../../components/i18n-context";
3
3
  import Renderer from "../../renderer";
4
+ import scoreGroup from "./score-group";
4
5
  import type { PerseusGroupWidgetOptions } from "../../perseus-types";
5
6
  import type { ChangeFn, FocusPath, Widget, WidgetProps } from "../../types";
6
7
  import type { PerseusGroupRubric, UserInputArray } from "../../validation.types";
@@ -44,6 +45,7 @@ declare const _default: {
44
45
  displayName: string;
45
46
  widget: typeof Group;
46
47
  traverseChildWidgets: (props: any, traverseRenderer: any) => any;
48
+ scorer: typeof scoreGroup;
47
49
  hidden: true;
48
50
  isLintable: true;
49
51
  };
@@ -0,0 +1,5 @@
1
+ import type { PerseusStrings } from "../../strings";
2
+ import type { PerseusScore } from "../../types";
3
+ import type { PerseusGroupRubric, PerseusGroupUserInput } from "../../validation.types";
4
+ declare function scoreGroup(userInput: PerseusGroupUserInput, options: PerseusGroupRubric, strings: PerseusStrings, locale: string): PerseusScore;
5
+ export default scoreGroup;
@@ -4,17 +4,110 @@ import scoreInteractiveGraph from "./interactive-graphs/score-interactive-graph"
4
4
  import type { StatefulMafsGraphType } from "./interactive-graphs/stateful-mafs-graph";
5
5
  import type { QuadraticGraphState } from "./interactive-graphs/types";
6
6
  import type { Coord } from "../interactive2/types";
7
- import type { PerseusGraphType, PerseusGraphTypeAngle, PerseusGraphTypePoint, PerseusGraphTypePolygon, PerseusGraphTypeSegment, PerseusInteractiveGraphWidgetOptions } from "../perseus-types";
7
+ import type { PerseusGraphType, PerseusGraphTypeAngle, PerseusGraphTypePoint, PerseusGraphTypePolygon, PerseusGraphTypeSegment, GraphRange, LockedFigure, PerseusImageBackground } from "../perseus-types";
8
8
  import type { ChangeHandler, WidgetProps } from "../types";
9
9
  import type { QuadraticCoefficient, Range, SineCoefficient } from "../util/geometry";
10
10
  import type { PerseusInteractiveGraphRubric, PerseusInteractiveGraphUserInput } from "../validation.types";
11
11
  import type { InteractiveGraphPromptJSON } from "../widget-ai-utils/interactive-graph/interactive-graph-ai-utils";
12
12
  import type { UnsupportedWidgetPromptJSON } from "../widget-ai-utils/unsupported-widget";
13
- type RenderProps = PerseusInteractiveGraphWidgetOptions;
13
+ type RenderProps = {
14
+ /**
15
+ * Where the little black axis lines & labels (ticks) should render.
16
+ * Also known as the tick step. default [1, 1]
17
+ *
18
+ * NOTE(kevinb): perseus_data.go defines this as Array<number>
19
+ */
20
+ step: [number, number];
21
+ /**
22
+ * Where the grid lines on the graph will render. default [1, 1]
23
+ *
24
+ * NOTE(kevinb): perseus_data.go defines this as Array<number>
25
+ */
26
+ gridStep?: [x: number, y: number];
27
+ /**
28
+ * Where the graph points will lock to when they are dragged. default [0.5, 0.5]
29
+ *
30
+ * NOTE(kevinb): perseus_data.go defines this as Array<number>
31
+ */
32
+ snapStep?: [x: number, y: number];
33
+ /**
34
+ * An optional image to use in the background
35
+ */
36
+ backgroundImage?: PerseusImageBackground;
37
+ /**
38
+ * The type of markings to display on the graph.
39
+ * - graph: shows the axes and the grid lines
40
+ * - grid: shows only the grid lines
41
+ * - none: shows no markings
42
+ */
43
+ markings: "graph" | "grid" | "none";
44
+ /**
45
+ * How to label the X and Y axis. default: ["x", "y"]
46
+ */
47
+ labels: ReadonlyArray<string>;
48
+ /**
49
+ * Whether to show the Protractor tool overlaid on top of the graph
50
+ */
51
+ showProtractor: boolean;
52
+ /**
53
+ * Whether to show the Ruler tool overlaid on top of the graph.
54
+ * @deprecated - no longer used by the InteractiveGraph widget. The
55
+ * property is kept on this type to prevent its accidental reuse in future
56
+ * features, since it may appear in production data.
57
+ */
58
+ showRuler?: boolean;
59
+ /**
60
+ * Whether to show tooltips on the graph
61
+ */
62
+ showTooltips?: boolean;
63
+ /**
64
+ * The unit to show on the ruler. e.g. "mm", "cm", "m", "km", "in", "ft",
65
+ * "yd", "mi".
66
+ * @deprecated - no longer used by the InteractiveGraph widget. The
67
+ * property is kept on this type to prevent its accidental reuse in future
68
+ * features, since it may appear in production data.
69
+ */
70
+ rulerLabel?: string;
71
+ /**
72
+ * How many ticks to show on the ruler. e.g. 1, 2, 4, 8, 10, 16. Must be
73
+ * an integer.
74
+ * @deprecated - no longer used by the InteractiveGraph widget. The
75
+ * property is kept on this type to prevent its accidental reuse in future
76
+ * features, since it may appear in production data.
77
+ */
78
+ rulerTicks?: number;
79
+ /**
80
+ * The X and Y coordinate ranges for the view of the graph. default: [[-10, 10], [-10, 10]]
81
+ *
82
+ * NOTE(kevinb): perseus_data.go defines this as Array<Array<number>>
83
+ */
84
+ range: GraphRange;
85
+ /**
86
+ * The type of graph
87
+ */
88
+ graph: PerseusGraphType;
89
+ /**
90
+ * The correct kind of graph, if being used to select function type
91
+ */
92
+ correct: PerseusGraphType;
93
+ /**
94
+ * Shapes (points, chords, etc) displayed on the graph that cannot be moved
95
+ * by the user.
96
+ */
97
+ lockedFigures?: ReadonlyArray<LockedFigure>;
98
+ /**
99
+ * Aria label that applies to the entire graph.
100
+ */
101
+ fullGraphAriaLabel?: string;
102
+ /**
103
+ * Aria description that applies to the entire graph.
104
+ */
105
+ fullGraphAriaDescription?: string;
106
+ };
14
107
  type Props = WidgetProps<RenderProps, PerseusInteractiveGraphRubric>;
15
108
  type State = any;
16
109
  type DefaultProps = {
17
- labels: Props["labels"];
110
+ labels: ReadonlyArray<string>;
18
111
  range: Props["range"];
19
112
  step: Props["step"];
20
113
  backgroundImage: Props["backgroundImage"];
@@ -11,12 +11,12 @@ export type MafsGraphProps = {
11
11
  backgroundImage?: InteractiveGraphProps["backgroundImage"];
12
12
  lockedFigures?: InteractiveGraphProps["lockedFigures"];
13
13
  step: InteractiveGraphProps["step"];
14
- gridStep: InteractiveGraphProps["gridStep"];
14
+ gridStep: [x: number, y: number];
15
15
  containerSizeClass: InteractiveGraphProps["containerSizeClass"];
16
16
  markings: InteractiveGraphProps["markings"];
17
17
  showTooltips: Required<InteractiveGraphProps["showTooltips"]>;
18
18
  showProtractor: boolean;
19
- labels: InteractiveGraphProps["labels"];
19
+ labels: ReadonlyArray<string>;
20
20
  fullGraphAriaLabel?: InteractiveGraphProps["fullGraphAriaLabel"];
21
21
  fullGraphAriaDescription?: InteractiveGraphProps["fullGraphAriaDescription"];
22
22
  state: InteractiveGraphState;
@@ -11,15 +11,15 @@ export type StatefulMafsGraphProps = {
11
11
  correct: PerseusGraphType;
12
12
  lockedFigures?: InteractiveGraphProps["lockedFigures"];
13
13
  range: InteractiveGraphProps["range"];
14
- snapStep: InteractiveGraphProps["snapStep"];
14
+ snapStep: [x: number, y: number];
15
15
  step: InteractiveGraphProps["step"];
16
- gridStep: InteractiveGraphProps["gridStep"];
16
+ gridStep: [x: number, y: number];
17
17
  containerSizeClass: InteractiveGraphProps["containerSizeClass"];
18
18
  markings: InteractiveGraphProps["markings"];
19
19
  onChange: InteractiveGraphProps["onChange"];
20
20
  showTooltips: Required<InteractiveGraphProps["showTooltips"]>;
21
21
  showProtractor: boolean;
22
- labels: InteractiveGraphProps["labels"];
22
+ labels: ReadonlyArray<string>;
23
23
  fullGraphAriaLabel?: InteractiveGraphProps["fullGraphAriaLabel"];
24
24
  fullGraphAriaDescription?: InteractiveGraphProps["fullGraphAriaDescription"];
25
25
  readOnly: boolean;