@khanacademy/perseus 61.2.1 → 62.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.
@@ -144,6 +144,7 @@ declare const ref: React.ForwardRefExoticComponent<Omit<Pick<SharedRendererProps
144
144
  customKeypad?: boolean;
145
145
  nativeKeypadProxy?: (blur: () => void) => KeypadAPI;
146
146
  isMobile?: boolean;
147
+ isMobileApp?: boolean;
147
148
  setDrawingAreaAvailable?: (arg1: boolean) => unknown;
148
149
  hintProgressColor?: string;
149
150
  canScrollPage?: boolean;
package/dist/types.d.ts CHANGED
@@ -186,6 +186,8 @@ export type APIOptions = Readonly<{
186
186
  nativeKeypadProxy?: (blur: () => void) => KeypadAPI;
187
187
  /** Indicates whether or not to use mobile styling. */
188
188
  isMobile?: boolean;
189
+ /** Indicates whether or not to use mobile app styling. */
190
+ isMobileApp?: boolean;
189
191
  /** A function, called with a bool indicating whether use of the
190
192
  * drawing area (scratchpad) should be allowed/disallowed.
191
193
  *
@@ -332,6 +334,7 @@ export type APIOptionsWithDefaults = Readonly<APIOptions & {
332
334
  groupAnnotator: NonNullable<APIOptions["groupAnnotator"]>;
333
335
  isArticle: NonNullable<APIOptions["isArticle"]>;
334
336
  isMobile: NonNullable<APIOptions["isMobile"]>;
337
+ isMobileApp: NonNullable<APIOptions["isMobileApp"]>;
335
338
  onFocusChange: NonNullable<APIOptions["onFocusChange"]>;
336
339
  readOnly: NonNullable<APIOptions["readOnly"]>;
337
340
  setDrawingAreaAvailable: NonNullable<APIOptions["setDrawingAreaAvailable"]>;
@@ -115,6 +115,7 @@ declare const _default: {
115
115
  customKeypad?: boolean;
116
116
  nativeKeypadProxy?: (blur: () => void) => import("@khanacademy/math-input").KeypadAPI;
117
117
  isMobile?: boolean;
118
+ isMobileApp?: boolean;
118
119
  setDrawingAreaAvailable?: (arg1: boolean) => unknown;
119
120
  hintProgressColor?: string;
120
121
  canScrollPage?: boolean;
@@ -130,6 +131,7 @@ declare const _default: {
130
131
  groupAnnotator: NonNullable<import("../..").APIOptions["groupAnnotator"]>;
131
132
  isArticle: NonNullable<import("../..").APIOptions["isArticle"]>;
132
133
  isMobile: NonNullable<import("../..").APIOptions["isMobile"]>;
134
+ isMobileApp: NonNullable<import("../..").APIOptions["isMobileApp"]>;
133
135
  onFocusChange: NonNullable<import("../..").APIOptions["onFocusChange"]>;
134
136
  readOnly: NonNullable<import("../..").APIOptions["readOnly"]>;
135
137
  setDrawingAreaAvailable: NonNullable<import("../..").APIOptions["setDrawingAreaAvailable"]>;
@@ -4,7 +4,7 @@ import type { Coord } from "../../interactive2/types";
4
4
  import type { Widget, WidgetProps } from "../../types";
5
5
  import type { GridDimensions } from "../../util";
6
6
  import type { GrapherPromptJSON } from "../../widget-ai-utils/grapher/grapher-ai-utils";
7
- import type { MarkingsType, PerseusGrapherWidgetOptions, PerseusGrapherUserInput, GrapherPublicWidgetOptions } from "@khanacademy/perseus-core";
7
+ import type { PerseusGrapherWidgetOptions, PerseusGrapherUserInput, GrapherPublicWidgetOptions } from "@khanacademy/perseus-core";
8
8
  import type { PropsFor } from "@khanacademy/wonder-blocks-core";
9
9
  type RenderProps = Pick<GrapherPublicWidgetOptions, "availableTypes" | "graph"> & {
10
10
  plot?: PerseusGrapherWidgetOptions["correct"];
@@ -12,7 +12,6 @@ type RenderProps = Pick<GrapherPublicWidgetOptions, "availableTypes" | "graph">
12
12
  type ExternalProps = WidgetProps<RenderProps>;
13
13
  type Props = ExternalProps & {
14
14
  plot: NonNullable<RenderProps["plot"]>;
15
- markings: MarkingsType;
16
15
  };
17
16
  type DefaultProps = {
18
17
  plot: RenderProps["plot"];
@@ -36,6 +36,7 @@ export declare const NumericInputComponent: React.ForwardRefExoticComponent<impo
36
36
  customKeypad?: boolean;
37
37
  nativeKeypadProxy?: (blur: () => void) => import("@khanacademy/math-input").KeypadAPI;
38
38
  isMobile?: boolean;
39
+ isMobileApp?: boolean;
39
40
  setDrawingAreaAvailable?: (arg1: boolean) => unknown;
40
41
  hintProgressColor?: string;
41
42
  canScrollPage?: boolean;
@@ -51,6 +52,7 @@ export declare const NumericInputComponent: React.ForwardRefExoticComponent<impo
51
52
  groupAnnotator: NonNullable<import("../..").APIOptions["groupAnnotator"]>;
52
53
  isArticle: NonNullable<import("../..").APIOptions["isArticle"]>;
53
54
  isMobile: NonNullable<import("../..").APIOptions["isMobile"]>;
55
+ isMobileApp: NonNullable<import("../..").APIOptions["isMobileApp"]>;
54
56
  onFocusChange: NonNullable<import("../..").APIOptions["onFocusChange"]>;
55
57
  readOnly: NonNullable<import("../..").APIOptions["readOnly"]>;
56
58
  setDrawingAreaAvailable: NonNullable<import("../..").APIOptions["setDrawingAreaAvailable"]>;
@@ -15,6 +15,7 @@ type State = {
15
15
  kind: "warning" | "critical";
16
16
  } | null;
17
17
  url: URL | null;
18
+ isFullScreen: boolean;
18
19
  };
19
20
  export declare class PhetSimulation extends React.Component<Props, State> implements Widget {
20
21
  static contextType: React.Context<import("../../components/i18n-context").I18nContextType>;
@@ -31,6 +32,25 @@ export declare class PhetSimulation extends React.Component<Props, State> implem
31
32
  displayLoadFailure: () => void;
32
33
  updateSimState(urlString: string): Promise<void>;
33
34
  showLocaleWarning(url: URL): Promise<boolean>;
35
+ /**
36
+ * Mobile App Fullscreen Implementation
37
+ *
38
+ * The mobile app environment doesn't support the standard browser fullscreen API.
39
+ * Instead, we implement a "fake" fullscreen mode with the following approach:
40
+ *
41
+ * 1. When fullscreen is toggled, we use a fixed position container that covers
42
+ * almost the entire viewport (appFullScreenWidgetContainer)
43
+ * 2. We leave space at the bottom for the mobile app's Check Answer bar (66px)
44
+ * 3. We position a close button in the top-right corner for exiting fullscreen
45
+ * 4. The iframe container expands to fill the available space
46
+ *
47
+ * This differs from the web implementation which uses the browser's
48
+ * native Fullscreen API via requestFullscreen().
49
+ *
50
+ * Note: Unfortunately, full screen is not supported in iOS mobile web due to
51
+ * the lack of support for the Fullscreen API.
52
+ */
53
+ toggleFullScreen: () => void;
34
54
  render(): React.ReactNode;
35
55
  }
36
56
  export declare const makeSafeUrl: (urlString: string, locale: string) => URL | null;
@@ -16,7 +16,6 @@ export type ChoiceType = {
16
16
  revealNoneOfTheAbove: boolean;
17
17
  disabled: boolean;
18
18
  };
19
- export type FocusFunction = (choiceIndex?: number | null | undefined) => boolean;
20
19
  type Props = {
21
20
  apiOptions: APIOptions;
22
21
  choices: ReadonlyArray<ChoiceType>;
@@ -32,7 +31,6 @@ type Props = {
32
31
  checked: ReadonlyArray<boolean>;
33
32
  crossedOut: ReadonlyArray<boolean>;
34
33
  }) => void;
35
- registerFocusFunction?: (arg1: FocusFunction) => void;
36
34
  isLastUsedWidget?: boolean;
37
35
  };
38
36
  /**
@@ -45,5 +43,5 @@ type Props = {
45
43
  *
46
44
  * TODO(LEMS-2994): Clean up this file.
47
45
  */
48
- declare const BaseRadio: ({ apiOptions, reviewModeRubric, reviewMode, choices, editMode, multipleSelect, labelWrap, countChoices, numCorrect, isLastUsedWidget, onChange, registerFocusFunction, }: Props) => React.ReactElement;
46
+ declare const BaseRadio: ({ apiOptions, reviewModeRubric, reviewMode, choices, editMode, multipleSelect, labelWrap, countChoices, numCorrect, isLastUsedWidget, onChange, }: Props) => React.ReactElement;
49
47
  export default BaseRadio;
@@ -1,5 +1,5 @@
1
1
  import * as React from "react";
2
- import type { ChoiceProps } from "./choice";
2
+ import type { ChoiceProps } from "./choice.new";
3
3
  declare const _default: React.ForwardRefExoticComponent<ChoiceProps & {
4
4
  showContent?: boolean;
5
5
  } & React.RefAttributes<HTMLButtonElement>>;
@@ -1,9 +1,7 @@
1
1
  import * as React from "react";
2
- import { PerseusI18nContext } from "../../components/i18n-context";
3
- import type { FocusFunction } from "./base-radio.new";
4
2
  import type { WidgetProps, ChoiceState, Widget } from "../../types";
5
3
  import type { RadioPromptJSON } from "../../widget-ai-utils/radio/radio-ai-utils";
6
- import type { PerseusRadioChoice, ShowSolutions, PerseusRadioRubric, PerseusRadioUserInput, RecursiveReadonly } from "@khanacademy/perseus-core";
4
+ import type { PerseusRadioChoice, ShowSolutions, PerseusRadioRubric, PerseusRadioUserInput, PerseusRadioWidgetOptions } from "@khanacademy/perseus-core";
7
5
  export type RenderProps = {
8
6
  numCorrect: number;
9
7
  hasNoneOfTheAbove?: boolean;
@@ -23,37 +21,26 @@ export type RadioChoiceWithMetadata = PerseusRadioChoice & {
23
21
  correct?: boolean;
24
22
  };
25
23
  /**
26
- * This component is a duplicate of the Radio component in radio.tsx
27
- * for the Radio Revitalization Project. (LEMS-2933)
28
- * This component will be split up to move the rendering logic to a new functional component.
29
- * This file will be renamed to radio.class.tsx and will supercede radio-component.tsx when
30
- * the feature flag is no longer needed.
24
+ * This component is holds the class methods for the radio widget, that were split
25
+ * out of radio-component.new.tsx for the Radio Revitalization Project. (LEMS-2933)
26
+ * This component will be the main entry point for the radio widget when the feature
27
+ * flag is no longer needed.
31
28
  *
32
29
  * TODO(LEMS-2994): Clean up this file.
33
30
  */
34
31
  declare class Radio extends React.Component<Props> implements Widget {
35
- static contextType: React.Context<import("../../components/i18n-context").I18nContextType>;
36
- context: React.ContextType<typeof PerseusI18nContext>;
37
- focusFunction: FocusFunction;
38
32
  static defaultProps: DefaultProps;
39
33
  static getUserInputFromProps(props: Props, unshuffle?: boolean): PerseusRadioUserInput;
40
- componentDidUpdate(prevProps: Props): void;
41
- _renderRenderer: (content?: string) => React.ReactElement;
42
- focus(choiceIndex?: number | null): boolean;
43
- registerFocusFunction(fun: FocusFunction): void;
44
- updateChoices: (newValueLists: Readonly<{
45
- checked: ReadonlyArray<boolean>;
46
- crossedOut: ReadonlyArray<boolean>;
47
- }>) => void;
48
34
  getUserInput(): PerseusRadioUserInput;
49
35
  getPromptJSON(): RadioPromptJSON;
50
36
  /**
51
37
  * Turn on rationale display for the currently selected choices. Note that
52
38
  * this leaves rationales on for choices that are already showing
53
39
  * rationales.
40
+ * TODO: LEMS-3077 Remove deprecated class function
54
41
  * @deprecated Internal only. Use `showSolutions` prop instead.
55
42
  */
56
- showRationalesForCurrentlySelectedChoices: (arg1: RecursiveReadonly<PerseusRadioRubric>) => void;
43
+ showRationalesForCurrentlySelectedChoices: (arg1: PerseusRadioWidgetOptions) => void;
57
44
  /**
58
45
  * Deselects any currently-selected choices that are not correct choices.
59
46
  */
@@ -1,6 +1,5 @@
1
1
  import * as React from "react";
2
2
  import RadioOld from "./radio-component";
3
- import RadioNew from "./radio-component.new";
4
3
  import type { RenderProps } from "./radio-component";
5
4
  import type { WidgetProps } from "../../types";
6
5
  import type { PerseusRadioRubric } from "@khanacademy/perseus-core";
@@ -16,7 +15,7 @@ type Props = WidgetProps<RenderProps, PerseusRadioRubric>;
16
15
  */
17
16
  declare class Radio extends RadioOld {
18
17
  ffIsOn: boolean;
19
- radioRef: React.RefObject<RadioOld | RadioNew>;
18
+ radioRef: React.RefObject<RadioOld>;
20
19
  constructor(props: Props);
21
20
  focus(choiceIndex?: number | null): boolean;
22
21
  render(): React.ReactNode;
@@ -0,0 +1,30 @@
1
+ import * as React from "react";
2
+ import type { WidgetProps, ChoiceState } from "../../types";
3
+ import type { PerseusRadioChoice, ShowSolutions, PerseusRadioRubric } from "@khanacademy/perseus-core";
4
+ export interface RadioChoiceWithMetadata extends PerseusRadioChoice {
5
+ originalIndex: number;
6
+ correct?: boolean;
7
+ }
8
+ export interface RenderProps {
9
+ numCorrect: number;
10
+ hasNoneOfTheAbove?: boolean;
11
+ multipleSelect?: boolean;
12
+ countChoices?: boolean;
13
+ deselectEnabled?: boolean;
14
+ choices: ReadonlyArray<RadioChoiceWithMetadata>;
15
+ selectedChoices: ReadonlyArray<PerseusRadioChoice["correct"]>;
16
+ showSolutions?: ShowSolutions;
17
+ choiceStates?: ReadonlyArray<ChoiceState>;
18
+ values?: ReadonlyArray<boolean>;
19
+ }
20
+ type RadioComponentProps = WidgetProps<RenderProps, PerseusRadioRubric>;
21
+ /**
22
+ * This component is a duplicate of the Radio component in radio.tsx
23
+ * for the Radio Revitalization Project. (LEMS-2933)
24
+ * This component has been split up to move the rendering logic to a new functional component.
25
+ * The class methods are now in radio.class.new.tsx.
26
+ *
27
+ * TODO(LEMS-2994): Clean up this file.
28
+ */
29
+ declare const RadioComponent: (props: RadioComponentProps) => React.JSX.Element;
30
+ export default RadioComponent;
package/dist/widgets.d.ts CHANGED
@@ -3,38 +3,38 @@ import type { Tracking, WidgetExports, WidgetTransform } from "./types";
3
3
  import type { PerseusWidget, Version } from "@khanacademy/perseus-core";
4
4
  import type * as React from "react";
5
5
  type Editor = any;
6
- export declare const registerWidget: (name: string, widget: WidgetExports) => void;
7
- export declare const registerWidgets: (widgets: ReadonlyArray<WidgetExports>) => void;
6
+ export declare const registerWidget: (type: string, widget: WidgetExports) => void;
7
+ export declare const registerWidgets: (widgetArr: ReadonlyArray<WidgetExports>) => void;
8
8
  /**
9
9
  *
10
- * @param name - the widget that you are trying to replace
11
- * @param replacementName - the name of the widget that takes its place
10
+ * @param type - the widget that you are trying to replace
11
+ * @param replacementType - the type of the widget that takes its place
12
12
  *
13
13
  * e.g. replaceWidget("transformer", "deprecated-standin") will make it so the
14
14
  * transformer widget is replaced by the always correct widget
15
15
  */
16
- export declare const replaceWidget: (name: string, replacementName: string) => void;
16
+ export declare const replaceWidget: (type: string, replacementType: string) => void;
17
17
  export declare const replaceDeprecatedWidgets: () => void;
18
18
  export declare const registerEditors: (editorsToRegister: ReadonlyArray<Editor>) => void;
19
19
  /**
20
20
  *
21
- * @param name - the widget that you are trying to replace
22
- * @param replacementName - the name of the widget that takes its place
21
+ * @param type - the widget that you are trying to replace
22
+ * @param replacementType - the type of the widget that takes its place
23
23
  *
24
24
  * e.g. replaceEditor("transformer", "deprecated-standin") will make it so the
25
25
  * transformer widget is replaced by the deprecated stand-in widget
26
26
  */
27
- export declare const replaceEditor: (name: string, replacementName: string) => void;
27
+ export declare const replaceEditor: (type: string, replacementType: string) => void;
28
28
  export declare const replaceDeprecatedEditors: () => void;
29
- export declare const getWidget: (name: string) => React.ComponentType<any> | null | undefined;
30
- export declare const getWidgetExport: (name: string) => WidgetExports | null;
31
- export declare const getEditor: (name: string) => Editor | null | undefined;
32
- export declare const getTransform: (name: string) => WidgetTransform | null | undefined;
33
- export declare const getVersion: (name: string) => Version | undefined;
29
+ export declare const getWidget: (type: string) => React.ComponentType<any> | null | undefined;
30
+ export declare const getWidgetExport: (type: string) => WidgetExports | null;
31
+ export declare const getEditor: (type: string) => Editor | null;
32
+ export declare const getTransform: (type: string) => WidgetTransform | null | undefined;
33
+ export declare const getVersion: (type: string) => Version | undefined;
34
34
  export declare const getVersionVector: () => {
35
35
  [key: string]: Version;
36
36
  };
37
- export declare const getPublicWidgets: () => ReadonlyArray<WidgetExports>;
37
+ export declare const getPublicWidgets: () => Record<string, WidgetExports>;
38
38
  export declare const isAccessible: (widgetInfo: PerseusWidget) => boolean;
39
39
  export declare const getAllWidgetTypes: () => ReadonlyArray<string>;
40
40
  export declare const getRendererPropsForWidgetInfo: (widgetInfo: PerseusWidget, strings: PerseusStrings, problemNum?: number) => PerseusWidget;
@@ -47,7 +47,7 @@ export declare const traverseChildWidgets: (widgetInfo: PerseusWidget, traverseR
47
47
  * A widget implicitly supports static mode if it exports a
48
48
  * staticTransform function.
49
49
  */
50
- export declare const supportsStaticMode: (type: string) => boolean;
50
+ export declare const supportsStaticMode: (type: string) => boolean | undefined;
51
51
  /**
52
52
  * Return the staticTransform function used to convert the editorProps to
53
53
  * the rendered widget state.
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": "61.2.1",
6
+ "version": "62.0.0",
7
7
  "publishConfig": {
8
8
  "access": "public"
9
9
  },
@@ -41,16 +41,16 @@
41
41
  "mafs": "0.19.0",
42
42
  "tiny-invariant": "^1.3.1",
43
43
  "uuid": "^10.0.0",
44
- "@khanacademy/kas": "2.0.3",
45
- "@khanacademy/keypad-context": "3.0.8",
46
- "@khanacademy/kmath": "2.0.8",
47
- "@khanacademy/math-input": "25.1.3",
48
- "@khanacademy/perseus-core": "10.1.0",
49
- "@khanacademy/perseus-linter": "3.0.8",
50
- "@khanacademy/perseus-score": "5.0.5",
51
- "@khanacademy/perseus-utils": "2.0.2",
52
- "@khanacademy/pure-markdown": "2.0.3",
53
- "@khanacademy/simple-markdown": "2.0.3"
44
+ "@khanacademy/kas": "2.0.4",
45
+ "@khanacademy/keypad-context": "3.0.9",
46
+ "@khanacademy/kmath": "2.0.9",
47
+ "@khanacademy/math-input": "25.1.4",
48
+ "@khanacademy/perseus-core": "11.0.0",
49
+ "@khanacademy/perseus-linter": "3.0.9",
50
+ "@khanacademy/perseus-score": "6.0.0",
51
+ "@khanacademy/perseus-utils": "2.0.3",
52
+ "@khanacademy/pure-markdown": "2.0.4",
53
+ "@khanacademy/simple-markdown": "2.0.4"
54
54
  },
55
55
  "devDependencies": {
56
56
  "@khanacademy/wonder-blocks-banner": "4.1.12",