@khanacademy/perseus 20.4.1 → 20.6.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.
@@ -57,7 +57,7 @@ export declare class Movable<Options extends Record<string, any>> {
57
57
  * Simulates a mouse grab event on the movable object.
58
58
  */
59
59
  grab(coord: Coord): void;
60
- _applyConstraints(current: Coord, previous: Coord, extraOptions?: ConstraintCallbacks): false | [number, number];
60
+ _applyConstraints(current: Coord, previous: Coord, extraOptions?: ConstraintCallbacks): false | Coord;
61
61
  toBack(): void;
62
62
  toFront(): void;
63
63
  /**
@@ -7,7 +7,7 @@
7
7
  */
8
8
  declare const _default: {
9
9
  pluck: (table: any, subKey: string) => any;
10
- mapObject: <K extends string, V, U>(obj: Partial<Record<K, V>>, lambda: (arg1: V, arg2: K) => U) => Partial<Record<K, U>>;
11
- mapObjectFromArray: <K_1 extends string, V_1>(arr: readonly K_1[], lambda: (arg1: K_1) => V_1) => Partial<Record<K_1, V_1>>;
10
+ mapObject: <K extends string, V, U>(obj: Record<K, V>, lambda: (arg1: V, arg2: K) => U) => Record<K, U>;
11
+ mapObjectFromArray: <K_1 extends string, V_1>(arr: readonly K_1[], lambda: (arg1: K_1) => V_1) => Record<K_1, V_1>;
12
12
  };
13
13
  export default _default;
@@ -3,7 +3,7 @@ import type { Interval, vec } from "mafs";
3
3
  export type Range = Interval;
4
4
  export type Size = [number, number];
5
5
  export type CollinearTuple = readonly [vec.Vector2, vec.Vector2];
6
- type StyleParams = {
6
+ export type StyleParams = {
7
7
  fill?: string;
8
8
  stroke?: string;
9
9
  };
@@ -1,3 +1,4 @@
1
+ /// <reference path="../../types/aphrodite.d.ts" />
1
2
  import type { StyleDeclaration } from "aphrodite";
2
3
  export declare const colors: {
3
4
  readonly white: "#FFFFFF";
@@ -1,3 +1,4 @@
1
+ /// <reference path="../../types/aphrodite.d.ts" />
1
2
  import type { StyleDeclaration } from "aphrodite";
2
3
  declare const _default: StyleDeclaration;
3
4
  export default _default;
package/dist/types.d.ts CHANGED
@@ -75,6 +75,11 @@ type TrackInteractionArgs = {
75
75
  id: string;
76
76
  correct?: boolean;
77
77
  } & Partial<TrackingGradedGroupExtraArguments> & Partial<TrackingSequenceExtraArguments>;
78
+ /**
79
+ * APIOptions provides different ways to customize the behaviour of Perseus.
80
+ *
81
+ * @see APIOptionsWithDefaults
82
+ */
78
83
  export type APIOptions = Readonly<{
79
84
  isArticle?: boolean;
80
85
  onInputError?: (widgetId: any, value: string, message?: string | null | undefined) => unknown;
@@ -87,25 +92,117 @@ export type APIOptions = Readonly<{
87
92
  interactionCallback?: (widgetData: {
88
93
  [widgetId: string]: any;
89
94
  }) => void;
95
+ /**
96
+ * A function that takes in the relative problem number (starts at
97
+ * 0 and is incremented for each group widget), and the ID of the
98
+ * group widget, then returns a react component that will be added
99
+ * immediately above the renderer in the group widget. If the
100
+ * function returns null, no annotation will be added.
101
+ */
90
102
  groupAnnotator?: (groupNumber: number, widgetId: string) => React.ReactNode;
103
+ /**
104
+ * If imagePlaceholder is set, Perseus will render the placeholder instead
105
+ * of the image node.
106
+ */
91
107
  imagePlaceholder?: React.ReactNode;
108
+ /**
109
+ * If widgetPlaceholder is set, Perseus will render the placeholder instead
110
+ * of the widget node.
111
+ */
92
112
  widgetPlaceholder?: React.ReactNode;
113
+ /**
114
+ * Base React elements that can be used in place of the standard DOM
115
+ * DOM elements. For example, when provided, <Link /> will be used
116
+ * in place of <a />. This allows clients to provide pre-styled
117
+ * components or components with custom behavior.
118
+ */
93
119
  baseElements?: {
120
+ /**
121
+ * The <Link /> component provided here must adhere to the same
122
+ * interface as React's base <a /> component.
123
+ */
94
124
  Link: React.ComponentType<any>;
95
125
  };
126
+ /**
127
+ * Function that takes dimensions and returns a React component
128
+ * to display while an image is loading.
129
+ */
96
130
  imagePreloader?: (dimensions: Dimensions) => React.ReactNode;
131
+ /**
132
+ * A function that is called when the user has interacted with a widget. It
133
+ * also includes any extra parameters that the originating widget provided.
134
+ * This is used for keeping track of widget interactions.
135
+ */
97
136
  trackInteraction?: (args: TrackInteractionArgs) => void;
137
+ /**
138
+ * A boolean that indicates whether or not a custom keypad is
139
+ * being used. For mobile web this will be the ProvidedKeypad
140
+ * component. In this situation we use the MathInput component
141
+ * from the math-input repo instead of the existing perseus math
142
+ * input components.
143
+ */
98
144
  customKeypad?: boolean;
145
+ /**
146
+ * If this is provided, it is called instead of appending an instance
147
+ * of `math-input`'s keypad to the body. This is used by the native
148
+ * apps so they can have the keypad be defined on the native side.
149
+ * It is called with an function that, when called, blurs the input,
150
+ * and is expected to return an object of the shape
151
+ * keypadElementPropType from math-input/src/prop-types.js.
152
+ */
99
153
  nativeKeypadProxy?: (blur: () => void) => KeypadAPI;
154
+ /** Indicates whether or not to use mobile styling. */
100
155
  isMobile?: boolean;
156
+ /** A function, called with a bool indicating whether use of the
157
+ * drawing area (scratchpad) should be allowed/disallowed.
158
+ *
159
+ * Previously handled by `Khan.scratchpad.enable/disable`
160
+ */
101
161
  setDrawingAreaAvailable?: (arg1: boolean) => unknown;
162
+ /** Whether to use the Draft.js editor or the legacy textarea */
102
163
  useDraftEditor?: boolean;
164
+ /** The color used for the hint progress indicator (eg. 1 / 3) */
103
165
  hintProgressColor?: string;
166
+ /**
167
+ * Whether this Renderer is allowed to auto-scroll the rest of the
168
+ * page. For example, if this is enabled, the most recently used
169
+ * radio widget will attempt to keep the "selected" answer in view
170
+ * after entering review mode.
171
+ *
172
+ * Defaults to `false`.
173
+ */
104
174
  canScrollPage?: boolean;
175
+ /** Whether or not we are rendering content inside of a modal. */
105
176
  inModal?: boolean;
177
+ /**
178
+ * Whether to enable the cross-out feature on multiple-choice radio
179
+ * widgets. This allows users to note which answers they believe to
180
+ * be incorrect, to find the answer by process of elimination.
181
+ *
182
+ * We plan to roll this out to all call sites eventually, but for
183
+ * now we have this flag, to add it to Generalized Test Prep first.
184
+ */
106
185
  crossOutEnabled?: boolean;
186
+ /**
187
+ * The value in milliseconds by which the local state of content
188
+ * in a editor is delayed before propagated to a prop. For example,
189
+ * when text is typed in the text area of an Editor component,
190
+ * there will be a delay equal to the value of `editorChangeDelay`
191
+ * before the change is propagated. This is added for better
192
+ * responsiveness of the editor when used in certain contexts such
193
+ * as StructuredItem exercises where constant re-rendering for each
194
+ * keystroke caused text typed in the text area to appear in it
195
+ * only after a good few seconds.
196
+ */
107
197
  editorChangeDelay?: number;
198
+ /** Feature flags that can be passed from consuming application. */
108
199
  flags?: Record<string, boolean | Record<string, boolean>>;
200
+ /**
201
+ * This is a callback function that returns all of the Widget props
202
+ * after they have been transformed by the widget's transform function.
203
+ * This is useful for when we need to know how a widget has shuffled its
204
+ * the available choices.
205
+ */
109
206
  onWidgetStartProps?: (widgets: PerseusWidgetsMap) => PerseusWidgetsMap;
110
207
  }>;
111
208
  type TeXProps = {
@@ -181,6 +278,11 @@ export type PerseusDependenciesV2 = {
181
278
  onAnalyticsEvent: AnalyticsEventHandlerFn;
182
279
  };
183
280
  };
281
+ /**
282
+ * APIOptionsWithDefaults represents the type that is provided to all widgets.
283
+ * The Renderer fills in these defaults when providing APIOptions to any
284
+ * widget.
285
+ */
184
286
  export type APIOptionsWithDefaults = Readonly<APIOptions & {
185
287
  GroupMetadataEditor: NonNullable<APIOptions["GroupMetadataEditor"]>;
186
288
  baseElements: NonNullable<APIOptions["baseElements"]>;
@@ -1,3 +1,4 @@
1
+ /// <reference path="../../types/aphrodite.d.ts" />
1
2
  import type { StyleDeclaration } from "aphrodite";
2
3
  declare const _default: StyleDeclaration;
3
4
  export default _default;
@@ -1,4 +1,4 @@
1
- import type { PerseusRenderer } from "../perseus-types";
1
+ import type { PerseusItem, PerseusRenderer } from "../perseus-types";
2
2
  /**
3
3
  * This function extracts the answers from the widgets.
4
4
  *
@@ -23,4 +23,11 @@ declare function getAnswersFromWidgets(widgets: PerseusRenderer["widgets"]): Rea
23
23
  * @returns
24
24
  */
25
25
  declare function injectWidgets(content: string, widgets: PerseusRenderer["widgets"]): string;
26
+ export declare const getWidgetTypeFromWidgetKey: (widgetKey: string) => string;
27
+ export declare const isWrongAnswerSupported: (widgetKeys: Array<string>) => boolean;
28
+ export declare const shouldHaveIndividualAnswer: (widgetKey: string) => boolean;
29
+ export declare const getAnswerFromUserInput: (widgetType: string, userInput: any) => any;
30
+ export declare const getCorrectAnswerForWidgetKey: (widgetKey: string, itemData: PerseusItem) => string | undefined;
31
+ export declare const isWidgetKeyInContent: (perseusItem: PerseusItem, widgetKey: string) => boolean;
32
+ export declare const getValidWidgetKeys: (perseusItem: PerseusItem) => Array<string>;
26
33
  export { getAnswersFromWidgets, injectWidgets };
@@ -0,0 +1,11 @@
1
+ /**
2
+ * Some helpers for CEDAR logging. CEDAR convention dictates
3
+ * that enum values should be upper case. Ex: for the
4
+ * PerseusWidgetUsedInProblemAttempt CEDAR event, we needed
5
+ * to: get the type and convert that to an enum value.
6
+ */
7
+ type WidgetName = "categorizer" | "cs-program" | "definition" | "deprecated-standin" | "dropdown" | "explanation" | "expression" | "graded-group-set" | "graded-group" | "grapher" | "group" | "iframe" | "image" | "input-number" | "interaction" | "interactive-graph" | "label-image" | "lights-puzzle" | "matcher" | "matrix" | "measurer" | "molecule-renderer" | "number-line" | "numeric-input" | "orderer" | "passage" | "passage-ref" | "passage-ref-target" | "plotter" | "python-program" | "reaction-diagram" | "radio" | "sequence" | "simulator" | "sorter" | "table" | "unit-input" | "video";
8
+ type WidgetEnum = "CATEGORIZER" | "CS_PROGRAM" | "DEFINITION" | "DEPRECATED_STANDIN" | "DROPDOWN" | "EXPLANATION" | "EXPRESSION" | "GRADED_GROUP" | "GRADED_GROUP_SET" | "GRAPHER" | "GROUP" | "IFRAME" | "IMAGE" | "INPUT_NUMBER" | "INTERACTIVE" | "INTERACTIVE_GRAPH" | "LABEL_IMAGE" | "LIGHTS_PUZZLE" | "MATCHER" | "MATRIX" | "MEASURER" | "MOLECULE" | "NUMBER_LINE" | "NUMERIC_INPUT" | "ORDERER" | "PASSAGE" | "PASSAGE_REF" | "PASSAGE_REF_TARGET" | "PLOTTER" | "PYTHON_PROGRAM" | "REACTION_DIAGRAM" | "RADIO" | "SEQUENCE" | "SIMULATOR" | "SORTER" | "TABLE" | "UNIT" | "VIDEO";
9
+ export declare function convertWidgetNameToEnum(name: WidgetName): WidgetEnum;
10
+ export declare function getWidgetTypeFromWidgetId(widgetId: string): WidgetName;
11
+ export {};
package/dist/util.d.ts CHANGED
@@ -190,7 +190,7 @@ declare function getWordBeforeCursor(textarea: HTMLTextAreaElement): WordAndPosi
190
190
  declare function moveCursor(textarea: HTMLTextAreaElement, pos: number): void;
191
191
  declare const Util: {
192
192
  readonly inputPathsEqual: typeof inputPathsEqual;
193
- readonly nestedMap: <T, M>(children: T | readonly T[], func: (arg1: T) => M, context: unknown) => M | readonly M[];
193
+ readonly nestedMap: <T, M>(children: T | ReadonlyArray<T>, func: (arg1: T) => M, context: unknown) => M | ReadonlyArray<M>;
194
194
  readonly rWidgetRule: RegExp;
195
195
  readonly rTypeFromWidgetId: RegExp;
196
196
  readonly rWidgetParts: RegExp;
@@ -21,7 +21,7 @@ type DefaultProps = {
21
21
  rulerTicks: Props["rulerTicks"];
22
22
  graph: Props["graph"];
23
23
  };
24
- declare class InteractiveGraph extends React.Component<Props, State> {
24
+ declare class LegacyInteractiveGraph extends React.Component<Props, State> {
25
25
  angle: any | null | undefined;
26
26
  circle: any | null | undefined;
27
27
  graphie: any | null | undefined;
@@ -39,7 +39,6 @@ declare class InteractiveGraph extends React.Component<Props, State> {
39
39
  trashCan: any | null | undefined;
40
40
  vertHairline: any | null | undefined;
41
41
  static defaultProps: DefaultProps;
42
- mafsRef: React.RefObject<Widget>;
43
42
  state: State;
44
43
  UNSAFE_componentWillMount(): void;
45
44
  componentDidMount(): void;
@@ -99,6 +98,14 @@ declare class InteractiveGraph extends React.Component<Props, State> {
99
98
  simpleValidate: (rubric: Rubric) => PerseusScore;
100
99
  focus: () => void;
101
100
  render(): React.ReactNode;
101
+ }
102
+ declare class InteractiveGraph extends React.Component<Props, State> {
103
+ legacyGraphRef: React.RefObject<LegacyInteractiveGraph>;
104
+ mafsRef: React.RefObject<Widget>;
105
+ static defaultProps: DefaultProps;
106
+ getUserInput: Widget["getUserInput"];
107
+ simpleValidate: (rubric: Rubric) => PerseusScore;
108
+ render(): JSX.Element;
102
109
  static getQuadraticCoefficients(coords: ReadonlyArray<Coord>): QuadraticCoefficient;
103
110
  static getSinusoidCoefficients(coords: ReadonlyArray<Coord>): SineCoefficient;
104
111
  /**
@@ -71,7 +71,7 @@ export declare const MafsGraph: React.ForwardRefExoticComponent<import("../..").
71
71
  onChange: import("../..").ChangeHandler;
72
72
  trackInteraction: (extraData?: {} | undefined) => void;
73
73
  isLastUsedWidget: boolean;
74
- linterContext: import("../../../../perseus-linter/src").LinterContextProps;
74
+ linterContext: import("@khanacademy/perseus-linter").LinterContextProps;
75
75
  containerSizeClass: import("../../util/sizing-utils").SizeClass;
76
76
  } & {
77
77
  children?: React.ReactNode;
@@ -1,3 +1,4 @@
1
+ /// <reference path="../../../types/aphrodite.d.ts" />
1
2
  /// <reference types="react" />
2
3
  import { type CSSProperties } from "aphrodite";
3
4
  export declare const AnswerPill: (props: {
@@ -3,6 +3,7 @@
3
3
  *
4
4
  * The target for labeling question image with answers.
5
5
  */
6
+ /// <reference path="../../../types/aphrodite.d.ts" />
6
7
  import * as React from "react";
7
8
  import type { InteractiveMarkerType } from "./types";
8
9
  import type { AnalyticsEventHandlerFn } from "@khanacademy/perseus-core";
@@ -1,3 +1,4 @@
1
+ /// <reference path="../../../../types/aphrodite.d.ts" />
1
2
  import type { StyleDeclaration } from "aphrodite";
2
3
  declare const CHOICE_ICON_SIZE = 24;
3
4
  declare const styles: StyleDeclaration;
@@ -1,4 +1,4 @@
1
- import Radio from "./radio/widget";
1
+ import Radio from "./radio/radio";
2
2
  declare const _default: Readonly<{
3
3
  name: string;
4
4
  displayName: string;
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": "20.4.1",
6
+ "version": "20.6.0",
7
7
  "publishConfig": {
8
8
  "access": "public"
9
9
  },
@@ -30,8 +30,8 @@
30
30
  "@khanacademy/math-input": "^17.3.0",
31
31
  "@khanacademy/perseus-core": "1.4.2",
32
32
  "@khanacademy/perseus-linter": "^0.3.12",
33
- "@khanacademy/pure-markdown": "^0.3.0",
34
- "@khanacademy/simple-markdown": "^0.11.3",
33
+ "@khanacademy/pure-markdown": "^0.3.1",
34
+ "@khanacademy/simple-markdown": "^0.11.4",
35
35
  "@khanacademy/wonder-blocks-banner": "^3.0.33",
36
36
  "mafs": "https://github.com/Khan/mafs/releases/download/v0.18.1%2Bbuild-cd8b2467893342ba0b02100073fe21f93f8b1125/mafs-0.18.1.tgz"
37
37
  },
File without changes