@khanacademy/perseus 45.0.0 → 46.0.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
  *
@@ -226,7 +232,6 @@ declare class Renderer extends React.Component<Props, State> implements GetPromp
226
232
  * @deprecated use scorePerseusItem
227
233
  */
228
234
  guessAndScore: () => [UserInputArray, PerseusScore];
229
- examples: () => ReadonlyArray<string> | null | undefined;
230
235
  handletranslationLintErrors: (lintErrors: ReadonlyArray<string>) => void;
231
236
  render(): React.ReactNode;
232
237
  }
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;
@@ -55,7 +61,6 @@ export interface Widget {
55
61
  getUserInputMap?: () => UserInputMap | undefined;
56
62
  getUserInput?: () => UserInputArray | UserInput | undefined;
57
63
  showRationalesForCurrentlySelectedChoices?: (options?: any) => void;
58
- examples?: () => ReadonlyArray<string>;
59
64
  getPromptJSON?: () => WidgetPromptJSON;
60
65
  }
61
66
  export type ImageDict = {
@@ -103,7 +108,7 @@ export type ChangeHandler = (arg1: {
103
108
  selected?: number;
104
109
  plot?: any;
105
110
  graph?: PerseusGraphType;
106
- }, callback?: () => unknown | null | undefined, silent?: boolean) => unknown;
111
+ }, callback?: () => void, silent?: boolean) => unknown;
107
112
  export type ImageUploader = (file: File, callback: (url: string) => unknown) => unknown;
108
113
  export type Path = ReadonlyArray<string>;
109
114
  type StubTagEditorType = any;
@@ -297,6 +302,17 @@ type InitialRequestUrlInterface = {
297
302
  protocol: string;
298
303
  };
299
304
  export type VideoKind = "YOUTUBE_ID" | "READABLE_ID";
305
+ /**
306
+ * An object for dependency injection, to allow different clients
307
+ * to provide different methods for logging, translation, network
308
+ * requests, etc.
309
+ *
310
+ * NOTE: You should avoid adding new dependencies here as this type was added
311
+ * as a quick fix to get around the fact that some of the dependencies Perseus
312
+ * needs are used in places where neither `APIOptions` nor a React Context
313
+ * could be used. Aim to shrink the footprint of PerseusDependencies and try to
314
+ * use alternative methods where possible.
315
+ */
300
316
  export type PerseusDependencies = {
301
317
  JIPT: JIPT;
302
318
  graphieMovablesJiptLabels: JiptLabelStore;
@@ -353,6 +369,11 @@ type TrackingSequenceExtraArguments = {
353
369
  };
354
370
  export type Alignment = "default" | "block" | "inline-block" | "inline" | "float-left" | "float-right" | "full-width";
355
371
  type WidgetOptions = any;
372
+ /**
373
+ * A transform that maps the WidgetOptions (sometimes referred to as
374
+ * EditorProps) to the props used to render the widget. Often this is an
375
+ * identity transform.
376
+ */
356
377
  export type WidgetTransform = (arg1: WidgetOptions, strings: PerseusStrings, problemNumber?: number) => any;
357
378
  export type WidgetScorerFunction = (userInput: UserInput, rubric: Rubric, string?: PerseusStrings, locale?: string) => PerseusScore;
358
379
  export type WidgetExports<T extends React.ComponentType<any> & Widget = React.ComponentType<any>> = Readonly<{
@@ -364,11 +385,12 @@ export type WidgetExports<T extends React.ComponentType<any> & Widget = React.Co
364
385
  /** Supresses widget from showing up in the dropdown in the content editor */
365
386
  hidden?: boolean;
366
387
  /**
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.
388
+ * The widget version. Any time the _major_ version changes, the widget
389
+ * should provide a new entry in the propUpgrades map to migrate from the
390
+ * older version to the current (new) version. Minor version changes must
391
+ * be backwards compatible with previous minor versions widget options.
392
+ *
393
+ * This key defaults to `{major: 0, minor: 0}` if not provided.
372
394
  */
373
395
  version?: Version;
374
396
  supportedAlignments?: ReadonlyArray<Alignment>;
@@ -377,25 +399,44 @@ export type WidgetExports<T extends React.ComponentType<any> & Widget = React.Co
377
399
  isLintable?: boolean;
378
400
  tracking?: Tracking;
379
401
  traverseChildWidgets?: any;
380
- /** transforms the widget options to the props used to render the widget */
402
+ /**
403
+ * Transforms the widget options to the props used to render the widget.
404
+ */
381
405
  transform?: WidgetTransform;
382
- /** transforms the widget options to the props used to render the widget for
383
- static renders */
406
+ /**
407
+ * Transforms the widget options to the props used to render the widget for
408
+ * static renders.
409
+ */
384
410
  staticTransform?: WidgetTransform;
411
+ /**
412
+ * A function that scores user input (the guess) for the widget.
413
+ */
385
414
  scorer?: WidgetScorerFunction;
386
415
  getOneCorrectAnswerFromRubric?: (rubric: Rubric) => string | null | undefined;
387
416
  /**
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
- */
417
+ * A map of major version numbers (as a string, eg "1") to a function that
418
+ * migrates from the _previous_ major version.
419
+ *
420
+ * Example:
421
+ * ```
422
+ * propUpgrades: {'1': (options) => ({...options})}
423
+ * ```
424
+ *
425
+ * This configuration would migrate options from major version 0 to 1.
426
+ */
394
427
  propUpgrades?: {
395
- [key: string]: (arg1: any) => any;
428
+ [targetMajorVersion: string]: (arg1: any) => any;
396
429
  };
397
430
  }>;
398
431
  export type FilterCriterion = string | ((id: string, widgetInfo: PerseusWidget, widget?: Widget | null | undefined) => boolean);
432
+ /**
433
+ * The full set of props provided to all widgets when they are rendered. The
434
+ * `RenderProps` generic argument are the widget-specific props that originate
435
+ * from the stored PerseusItem. Note that they may not match the serialized
436
+ * widget options exactly as they are the result of running the options through
437
+ * any `propUpgrades` the widget defines as well as its `transform` or
438
+ * `staticTransform` functions (depending on the options `static` flag).
439
+ */
399
440
  export type WidgetProps<RenderProps, Rubric = Empty, TrackingExtraArgs = Empty> = RenderProps & {
400
441
  widgetId: string;
401
442
  alignment: string | null | undefined;
@@ -0,0 +1,2 @@
1
+ import type { PartialParser } from "../parser-types";
2
+ export declare const stringToNumber: PartialParser<string | number, number>;
@@ -0,0 +1,20 @@
1
+ import type { PerseusScore } from "../types";
2
+ import type { UserInputArray } from "../validation.types";
3
+ import type { KEScore } from "@khanacademy/perseus-core";
4
+ /**
5
+ * If a widget says that it is empty once it is graded.
6
+ * Trying to encapsulate references to the score format.
7
+ */
8
+ export declare function scoreIsEmpty(score: PerseusScore): boolean;
9
+ /**
10
+ * Combine two score objects.
11
+ *
12
+ * Given two score objects for two different widgets, combine them so that
13
+ * if one is wrong, the total score is wrong, etc.
14
+ */
15
+ export declare function combineScores(scoreA: PerseusScore, scoreB: PerseusScore): PerseusScore;
16
+ export declare function flattenScores(widgetScoreMap: {
17
+ [widgetId: string]: PerseusScore;
18
+ }): PerseusScore;
19
+ export declare function isCorrect(score: PerseusScore): boolean;
20
+ export declare function keScoreFromPerseusScore(score: PerseusScore, guess: UserInputArray | [UserInputArray, []], state: any): KEScore;
package/dist/util.d.ts CHANGED
@@ -1,9 +1,6 @@
1
1
  import * as GraphieUtil from "./util.graphie";
2
2
  import type { Range } from "./perseus-types";
3
3
  import type { PerseusStrings } from "./strings";
4
- import type { PerseusScore } from "./types";
5
- import type { UserInputArray } from "./validation.types";
6
- import type { KEScore } from "@khanacademy/perseus-core";
7
4
  import type * as React from "react";
8
5
  type WordPosition = {
9
6
  start: number;
@@ -41,18 +38,6 @@ type TouchHandlers = {
41
38
  */
42
39
  declare function inputPathsEqual(a?: ReadonlyArray<string> | null, b?: ReadonlyArray<string> | null): boolean;
43
40
  declare function shuffle<T>(array: ReadonlyArray<T>, randomSeed: number | RNG, ensurePermuted?: boolean): ReadonlyArray<T>;
44
- /**
45
- * Combine two score objects.
46
- *
47
- * Given two score objects for two different widgets, combine them so that
48
- * if one is wrong, the total score is wrong, etc.
49
- */
50
- declare function combineScores(scoreA: PerseusScore, scoreB: PerseusScore): PerseusScore;
51
- declare function flattenScores(widgetScoreMap: {
52
- [widgetId: string]: PerseusScore;
53
- }): PerseusScore;
54
- export declare function isCorrect(score: PerseusScore): boolean;
55
- declare function keScoreFromPerseusScore(score: PerseusScore, guess: UserInputArray | [UserInputArray, []], state: any): KEScore;
56
41
  /**
57
42
  * Return the first valid interpretation of 'text' as a number, in the form
58
43
  * {value: 2.3, exact: true}.
@@ -156,11 +141,6 @@ declare function updateQueryString(uri: string, key: string, value: string): str
156
141
  * CC-BY-SA 2.5 license.
157
142
  */
158
143
  declare function strongEncodeURIComponent(str: string): string;
159
- /**
160
- * If a widget says that it is empty once it is graded.
161
- * Trying to encapsulate references to the score format.
162
- */
163
- declare function scoreIsEmpty(score: PerseusScore): boolean;
164
144
  declare function resetTouchHandlers(): void;
165
145
  /**
166
146
  * Extracts the location of a touch or mouse event, allowing you to pass
@@ -197,18 +177,9 @@ declare const Util: {
197
177
  readonly rTypeFromWidgetId: RegExp;
198
178
  readonly rWidgetParts: RegExp;
199
179
  readonly snowman: "☃";
200
- readonly noScore: {
201
- type: "points";
202
- earned: number;
203
- total: number;
204
- message?: string | null | undefined;
205
- };
206
180
  readonly seededRNG: (seed: number) => RNG;
207
181
  readonly shuffle: typeof shuffle;
208
182
  readonly split: (str: string, r: RegExp) => ReadonlyArray<string>;
209
- readonly combineScores: typeof combineScores;
210
- readonly flattenScores: typeof flattenScores;
211
- readonly keScoreFromPerseusScore: typeof keScoreFromPerseusScore;
212
183
  readonly firstNumericalParse: typeof firstNumericalParse;
213
184
  readonly stringArrayOfSize: typeof stringArrayOfSize;
214
185
  readonly gridDimensionConfig: typeof gridDimensionConfig;
@@ -224,7 +195,6 @@ declare const Util: {
224
195
  readonly parseQueryString: typeof parseQueryString;
225
196
  readonly updateQueryString: typeof updateQueryString;
226
197
  readonly strongEncodeURIComponent: typeof strongEncodeURIComponent;
227
- readonly scoreIsEmpty: typeof scoreIsEmpty;
228
198
  readonly touchHandlers: TouchHandlers;
229
199
  readonly resetTouchHandlers: typeof resetTouchHandlers;
230
200
  readonly extractPointerLocation: typeof extractPointerLocation;
@@ -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;
@@ -50,7 +50,7 @@ declare class InputNumber extends React.Component<Props> implements Widget {
50
50
  setInputValue: (arg1: Path, arg2: string, arg3: () => void) => void;
51
51
  getUserInput(): PerseusInputNumberUserInput;
52
52
  getPromptJSON(): InputNumberPromptJSON;
53
- examples: () => ReadonlyArray<string>;
53
+ examples(): ReadonlyArray<string>;
54
54
  render(): React.ReactNode;
55
55
  }
56
56
  declare const _default: {