@khanacademy/perseus 66.4.0 → 67.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.
@@ -159,7 +159,6 @@ declare const _default: React.ForwardRefExoticComponent<Omit<Pick<SharedRenderer
159
159
  canScrollPage?: boolean;
160
160
  editorChangeDelay?: number;
161
161
  flags?: Record<"new-radio-widget", boolean>;
162
- onWidgetStartProps?: (widgets: import("@khanacademy/perseus-core").PerseusWidgetsMap) => void;
163
162
  }> | undefined;
164
163
  linterContext?: PerseusLinter.LinterContextProps | undefined;
165
164
  onRendered?: ((isRendered: boolean) => void) | undefined;
package/dist/types.d.ts CHANGED
@@ -224,16 +224,6 @@ export type APIOptions = Readonly<{
224
224
  * Define the feature flag name in packages/perseus-core/src/feature-flags.ts
225
225
  */
226
226
  flags?: Record<(typeof PerseusFeatureFlags)[number], boolean>;
227
- /**
228
- * This is a callback function that returns all of the Widget props
229
- * after they have been transformed by the widget's transform function.
230
- * This is useful for when we need to know how a widget has shuffled its
231
- * the available choices.
232
- *
233
- * @deprecated [LEMS-3185] this is externalizing an internal implementation
234
- * detail similar to serialized state
235
- */
236
- onWidgetStartProps?: (widgets: PerseusWidgetsMap) => void;
237
227
  }>;
238
228
  type TeXProps = {
239
229
  children: string;
@@ -33,7 +33,7 @@ export declare function sharedInitializeUserInput(widgetOptions: PerseusWidgetsM
33
33
  *
34
34
  * @deprecated - do not use in new code.
35
35
  */
36
- export declare function sharedRestoreUserInputFromSerializedState(serializedState: unknown, widgetsMap: PerseusWidgetsMap): UserInputMap;
36
+ export declare function deriveUserInputFromSerializedState(serializedState: unknown, widgetsMap: PerseusWidgetsMap): UserInputMap;
37
37
  /**
38
38
  * UserInputManager is a stateful wrapper for handling and storing user input.
39
39
  * Ideally we'll get to a place where widgets are functional components
@@ -101,7 +101,6 @@ export declare class Expression extends React.Component<Props> implements Widget
101
101
  canScrollPage?: boolean;
102
102
  editorChangeDelay?: number;
103
103
  flags?: Record<"new-radio-widget", boolean>;
104
- onWidgetStartProps?: (widgets: import("@khanacademy/perseus-core").PerseusWidgetsMap) => void;
105
104
  }> & {
106
105
  baseElements: NonNullable<import("../..").APIOptions["baseElements"]>;
107
106
  canScrollPage: NonNullable<import("../..").APIOptions["canScrollPage"]>;
@@ -194,7 +193,6 @@ declare const _default: {
194
193
  canScrollPage?: boolean;
195
194
  editorChangeDelay?: number;
196
195
  flags?: Record<"new-radio-widget", boolean>;
197
- onWidgetStartProps?: (widgets: import("@khanacademy/perseus-core").PerseusWidgetsMap) => void;
198
196
  }> & {
199
197
  baseElements: NonNullable<import("../..").APIOptions["baseElements"]>;
200
198
  canScrollPage: NonNullable<import("../..").APIOptions["canScrollPage"]>;
@@ -92,7 +92,6 @@ declare class Grapher extends React.Component<Props> implements Widget {
92
92
  canScrollPage?: boolean;
93
93
  editorChangeDelay?: number;
94
94
  flags?: Record<"new-radio-widget", boolean>;
95
- onWidgetStartProps?: (widgets: import("@khanacademy/perseus-core").PerseusWidgetsMap) => void;
96
95
  }> & {
97
96
  baseElements: NonNullable<import("../..").APIOptions["baseElements"]>;
98
97
  canScrollPage: NonNullable<import("../..").APIOptions["canScrollPage"]>;
@@ -6,7 +6,7 @@ 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
8
  import type { QuadraticCoefficient, SineCoefficient, Range } from "@khanacademy/kmath";
9
- import type { PerseusGraphType, PerseusGraphTypeAngle, PerseusGraphTypePoint, PerseusGraphTypeSegment, PerseusInteractiveGraphWidgetOptions, GraphRange, InteractiveGraphPublicWidgetOptions, LockedFigure, PerseusImageBackground, MarkingsType, PerseusInteractiveGraphUserInput, AxisLabelLocation } from "@khanacademy/perseus-core";
9
+ import type { PerseusGraphType, PerseusGraphTypeAngle, PerseusGraphTypePoint, PerseusGraphTypeSegment, PerseusInteractiveGraphWidgetOptions, GraphRange, InteractiveGraphPublicWidgetOptions, LockedFigure, PerseusImageBackground, MarkingsType, PerseusInteractiveGraphUserInput, AxisLabelLocation, ShowAxisArrows } from "@khanacademy/perseus-core";
10
10
  type RenderProps = {
11
11
  /**
12
12
  * Where the little black axis lines & labels (ticks) should render.
@@ -87,12 +87,7 @@ type RenderProps = {
87
87
  /**
88
88
  * Whether to show the arrows on the axis.
89
89
  */
90
- showAxisArrows: {
91
- xMin: boolean;
92
- xMax: boolean;
93
- yMin: boolean;
94
- yMax: boolean;
95
- };
90
+ showAxisArrows: ShowAxisArrows;
96
91
  /**
97
92
  * The type of graph
98
93
  */
@@ -153,12 +148,7 @@ declare class InteractiveGraph extends React.Component<Props, State> {
153
148
  rulerLabel?: string;
154
149
  rulerTicks?: number;
155
150
  range: GraphRange;
156
- showAxisArrows: {
157
- xMin: boolean;
158
- xMax: boolean;
159
- yMin: boolean;
160
- yMax: boolean;
161
- };
151
+ showAxisArrows: ShowAxisArrows;
162
152
  correct?: PerseusGraphType;
163
153
  lockedFigures: LockedFigure[];
164
154
  fullGraphAriaLabel?: string;
@@ -203,7 +193,6 @@ declare class InteractiveGraph extends React.Component<Props, State> {
203
193
  canScrollPage?: boolean;
204
194
  editorChangeDelay?: number;
205
195
  flags?: Record<"new-radio-widget", boolean>;
206
- onWidgetStartProps?: (widgets: import("@khanacademy/perseus-core").PerseusWidgetsMap) => void;
207
196
  }> & {
208
197
  baseElements: NonNullable<import("../..").APIOptions["baseElements"]>;
209
198
  canScrollPage: NonNullable<import("../..").APIOptions["canScrollPage"]>;
@@ -76,7 +76,6 @@ declare class MockWidgetComponent extends React.Component<Props> implements Widg
76
76
  canScrollPage?: boolean;
77
77
  editorChangeDelay?: number;
78
78
  flags?: Record<"new-radio-widget", boolean>;
79
- onWidgetStartProps?: (widgets: import("@khanacademy/perseus-core").PerseusWidgetsMap) => void;
80
79
  }> & {
81
80
  baseElements: NonNullable<import("../..").APIOptions["baseElements"]>;
82
81
  canScrollPage: NonNullable<import("../..").APIOptions["canScrollPage"]>;
@@ -121,7 +121,6 @@ declare class NumberLine extends React.Component<Props, State> implements Widget
121
121
  canScrollPage?: boolean;
122
122
  editorChangeDelay?: number;
123
123
  flags?: Record<"new-radio-widget", boolean>;
124
- onWidgetStartProps?: (widgets: import("@khanacademy/perseus-core").PerseusWidgetsMap) => void;
125
124
  }> & {
126
125
  baseElements: NonNullable<import("../..").APIOptions["baseElements"]>;
127
126
  canScrollPage: NonNullable<import("../..").APIOptions["canScrollPage"]>;
@@ -13,14 +13,6 @@ export type NumericInputProps = ExternalProps & {
13
13
  linterContext: NonNullable<ExternalProps["linterContext"]>;
14
14
  };
15
15
  type DefaultProps = Pick<NumericInputProps, "size" | "rightAlign" | "apiOptions" | "coefficient" | "answerForms" | "labelText" | "linterContext" | "userInput">;
16
- type RenderProps = {
17
- answerForms: ReadonlyArray<PerseusNumericInputAnswerForm>;
18
- labelText?: string;
19
- size: string;
20
- coefficient: boolean;
21
- rightAlign?: boolean;
22
- static: boolean;
23
- };
24
16
  /**
25
17
  * The NumericInput widget is a numeric input field that supports a variety of
26
18
  * answer forms, including integers, decimals, fractions, and mixed numbers.
@@ -47,7 +39,6 @@ export declare class NumericInput extends React.Component<NumericInputProps> imp
47
39
  */
48
40
  getSerializedState(): {
49
41
  currentValue: string;
50
- answers: import("@khanacademy/perseus-core").PerseusNumericInputAnswer[];
51
42
  labelText: string;
52
43
  size: string;
53
44
  coefficient: boolean;
@@ -92,7 +83,6 @@ export declare class NumericInput extends React.Component<NumericInputProps> imp
92
83
  canScrollPage?: boolean;
93
84
  editorChangeDelay?: number;
94
85
  flags?: Record<"new-radio-widget", boolean>;
95
- onWidgetStartProps?: (widgets: import("@khanacademy/perseus-core").PerseusWidgetsMap) => void;
96
86
  }> & {
97
87
  baseElements: NonNullable<import("../..").APIOptions["baseElements"]>;
98
88
  canScrollPage: NonNullable<import("../..").APIOptions["canScrollPage"]>;
@@ -132,7 +122,6 @@ declare const _default: {
132
122
  name: string;
133
123
  displayName: string;
134
124
  widget: typeof NumericInput;
135
- transform: (widgetOptions: PerseusNumericInputWidgetOptions) => RenderProps;
136
125
  isLintable: true;
137
126
  getOneCorrectAnswerFromRubric(rubric: PerseusNumericInputRubric): string | null | undefined;
138
127
  getStartUserInput: typeof getStartUserInput;
@@ -42,7 +42,6 @@ export declare const NumericInputComponent: React.ForwardRefExoticComponent<impo
42
42
  canScrollPage?: boolean;
43
43
  editorChangeDelay?: number;
44
44
  flags?: Record<"new-radio-widget", boolean>;
45
- onWidgetStartProps?: (widgets: import("@khanacademy/perseus-core").PerseusWidgetsMap) => void;
46
45
  }> & {
47
46
  baseElements: NonNullable<import("../..").APIOptions["baseElements"]>;
48
47
  canScrollPage: NonNullable<import("../..").APIOptions["canScrollPage"]>;
@@ -1,5 +1,5 @@
1
1
  import type { PerseusStrings } from "../../strings";
2
- import type { PerseusNumericInputAnswerForm } from "@khanacademy/perseus-core";
2
+ import type { PerseusNumericInputAnswerForm, PerseusNumericInputWidgetOptions } from "@khanacademy/perseus-core";
3
3
  /**
4
4
  * The full list of available strings for the numeric input widget,
5
5
  * based on whether the Content Creator has specified that the answer must be simplified.
@@ -23,3 +23,8 @@ export declare const shouldShowExamples: (answerForms: readonly PerseusNumericIn
23
23
  * `formExamples` forms from above.
24
24
  */
25
25
  export declare const unionAnswerForms: (answerFormsList: ReadonlyArray<ReadonlyArray<PerseusNumericInputAnswerForm>>) => ReadonlyArray<PerseusNumericInputAnswerForm>;
26
+ /**
27
+ * Filter out the correct answers and map them to the answer forms
28
+ * so that we can generate the examples for the widget.
29
+ */
30
+ export declare function normalizeCorrectAnswerForms(answers: PerseusNumericInputWidgetOptions["answers"]): ReadonlyArray<PerseusNumericInputAnswerForm>;
@@ -130,7 +130,6 @@ export declare class Plotter extends React.Component<Props, State> implements Wi
130
130
  canScrollPage?: boolean;
131
131
  editorChangeDelay?: number;
132
132
  flags?: Record<"new-radio-widget", boolean>;
133
- onWidgetStartProps?: (widgets: import("@khanacademy/perseus-core").PerseusWidgetsMap) => void;
134
133
  }> & {
135
134
  baseElements: NonNullable<import("../..").APIOptions["baseElements"]>;
136
135
  canScrollPage: NonNullable<import("../..").APIOptions["canScrollPage"]>;
@@ -1,11 +1,17 @@
1
- import * as React from "react";
2
- export type IndicatorProps = {
1
+ import React from "react";
2
+ export interface IndicatorContent {
3
+ visible: string;
4
+ screenReader: string;
5
+ labelledBy?: string;
6
+ describedBy?: string;
7
+ }
8
+ export interface IndicatorProps {
3
9
  buttonRef: React.Ref<HTMLButtonElement>;
4
10
  checked: boolean;
5
- content: string;
11
+ content: IndicatorContent;
6
12
  shape: "circle" | "square";
7
13
  showCorrectness?: "correct" | "wrong";
8
14
  updateChecked: (isChecked: boolean) => void;
9
- };
15
+ }
10
16
  declare const Indicator: (props: IndicatorProps) => React.JSX.Element;
11
17
  export default Indicator;
@@ -1,8 +1,9 @@
1
1
  import React from "react";
2
+ import type { IndicatorContent } from "./choice-indicator.new";
2
3
  export interface IndicatorProps {
3
4
  checked: boolean;
4
5
  children: React.ReactNode | React.ReactNode[];
5
- indicatorContent: string;
6
+ indicatorContent: IndicatorContent;
6
7
  isMultiSelect: boolean;
7
8
  showCorrectness?: "correct" | "wrong";
8
9
  updateChecked: (isChecked: boolean) => void;
@@ -1,4 +1,4 @@
1
- import * as React from "react";
1
+ import React from "react";
2
2
  import type { ChoiceType } from "./multiple-choice-widget.new";
3
3
  /**
4
4
  * Props for the MultipleChoiceComponent
@@ -20,6 +20,18 @@ export interface MultipleChoiceComponentProps {
20
20
  *
21
21
  * Supports both radio button (single select) and checkbox (multiple select) modes.
22
22
  *
23
+ * NOTE: This widget does not implement standard radio button or checkbox elements.
24
+ * The key difference is that the single-select (aka radio button) should
25
+ * allow the user to deselect a choice, whereas regular radio buttons
26
+ * can only be deselected by selecting another choice.
27
+ * Another difference is that keyboard navigation with single-select is
28
+ * done with the tab key, whereas regular radio buttons use the arrow keys,
29
+ * and the radio buttons are automatically selected when navigating to them.
30
+ * Since interactions with the single-select version of this widget don't
31
+ * follow the standard radio button behavior, we decided to use toggle
32
+ * button semantics for both versions of the widget,
33
+ * and implement additional ARIA attributes where needed.
34
+ *
23
35
  * Created as part of the Radio Revitalization Project (LEMS-2933).
24
36
  */
25
37
  declare const MultipleChoiceComponent: ({ choices, countChoices, multipleSelect, numCorrect, onChoiceChange, reviewMode, }: MultipleChoiceComponentProps) => React.ReactElement;
@@ -7,12 +7,16 @@ declare class RadioQuestionBuilder {
7
7
  private hasNoneOfTheAbove?;
8
8
  private multipleSelect?;
9
9
  private randomize?;
10
+ private static?;
11
+ private numCorrect?;
10
12
  build(): PerseusRenderer;
11
13
  withContent(content: string): RadioQuestionBuilder;
12
14
  withCountChoices(countChoices: boolean): RadioQuestionBuilder;
13
15
  withHasNoneOfTheAbove(hasNoneOfTheAbove: boolean): RadioQuestionBuilder;
14
16
  withMultipleSelect(multipleSelect: boolean): RadioQuestionBuilder;
15
17
  withRandomize(randomize: boolean): RadioQuestionBuilder;
18
+ withStatic(isStatic: boolean): RadioQuestionBuilder;
19
+ withNumCorrect(numCorrect: number): RadioQuestionBuilder;
16
20
  addChoice(content: string, options?: {
17
21
  correct?: boolean;
18
22
  rationale?: string;
@@ -78,7 +78,6 @@ declare class Radio extends RadioOld {
78
78
  canScrollPage?: boolean;
79
79
  editorChangeDelay?: number;
80
80
  flags?: Record<"new-radio-widget", boolean>;
81
- onWidgetStartProps?: (widgets: import("@khanacademy/perseus-core").PerseusWidgetsMap) => void;
82
81
  }> & {
83
82
  baseElements: NonNullable<import("../..").APIOptions["baseElements"]>;
84
83
  canScrollPage: NonNullable<import("../..").APIOptions["canScrollPage"]>;
@@ -85,7 +85,6 @@ declare class Table extends React.Component<Props> implements Widget {
85
85
  canScrollPage?: boolean;
86
86
  editorChangeDelay?: number;
87
87
  flags?: Record<"new-radio-widget", boolean>;
88
- onWidgetStartProps?: (widgets: import("@khanacademy/perseus-core").PerseusWidgetsMap) => void;
89
88
  }> & {
90
89
  baseElements: NonNullable<import("../..").APIOptions["baseElements"]>;
91
90
  canScrollPage: NonNullable<import("../..").APIOptions["canScrollPage"]>;
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": "66.4.0",
6
+ "version": "67.0.0",
7
7
  "publishConfig": {
8
8
  "access": "public"
9
9
  },
@@ -42,15 +42,15 @@
42
42
  "tiny-invariant": "1.3.1",
43
43
  "uuid": "^10.0.0",
44
44
  "@khanacademy/kas": "2.1.0",
45
- "@khanacademy/keypad-context": "3.1.3",
46
- "@khanacademy/kmath": "2.1.3",
47
- "@khanacademy/math-input": "26.1.4",
48
- "@khanacademy/perseus-core": "18.6.0",
49
- "@khanacademy/perseus-linter": "4.2.3",
50
- "@khanacademy/perseus-score": "7.6.0",
45
+ "@khanacademy/keypad-context": "3.1.5",
46
+ "@khanacademy/kmath": "2.1.5",
47
+ "@khanacademy/math-input": "26.1.6",
48
+ "@khanacademy/perseus-core": "18.8.0",
49
+ "@khanacademy/perseus-linter": "4.2.5",
50
+ "@khanacademy/perseus-score": "7.6.2",
51
51
  "@khanacademy/perseus-utils": "2.1.0",
52
- "@khanacademy/pure-markdown": "2.2.0",
53
- "@khanacademy/simple-markdown": "2.1.0"
52
+ "@khanacademy/simple-markdown": "2.1.0",
53
+ "@khanacademy/pure-markdown": "2.2.0"
54
54
  },
55
55
  "devDependencies": {
56
56
  "@khanacademy/wonder-blocks-banner": "4.2.14",