@khanacademy/perseus 74.0.2 → 75.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.
@@ -0,0 +1,16 @@
1
+ import * as React from "react";
2
+ import type { APIOptions } from "../types";
3
+ import type { PerseusArticle } from "@khanacademy/perseus-core";
4
+ import type { LinterContextProps } from "@khanacademy/perseus-linter";
5
+ type Props = {
6
+ title?: string;
7
+ /**
8
+ * The Perseus Article to render. Under the hood this has been named
9
+ * `json`, but it is the article. Trust me.
10
+ */
11
+ json: PerseusArticle;
12
+ apiOptions?: APIOptions;
13
+ linterContext?: LinterContextProps;
14
+ };
15
+ export declare const ArticleRendererWithDebugUI: ({ title, json, apiOptions, linterContext, }: Props) => React.ReactElement;
16
+ export {};
@@ -0,0 +1,13 @@
1
+ import * as React from "react";
2
+ import type { PerseusItem, PerseusScore, UserInputMap } from "@khanacademy/perseus-core";
3
+ type DebugAccordionUIProps = {
4
+ score: PerseusScore | undefined;
5
+ userInput: UserInputMap | undefined;
6
+ perseusItem: PerseusItem;
7
+ updateJson: (json: string) => boolean;
8
+ };
9
+ /**
10
+ * A component that renders the debug accordion UI for Perseus items
11
+ */
12
+ export declare const DebugAccordionUI: ({ score, userInput, perseusItem, updateJson, }: DebugAccordionUIProps) => React.ReactElement;
13
+ export {};
@@ -0,0 +1,20 @@
1
+ import * as React from "react";
2
+ import type { PerseusScore, ShowSolutions } from "@khanacademy/perseus-core";
3
+ type DebugCheckAnswerFooterProps = {
4
+ score: PerseusScore | undefined;
5
+ showSolutions: ShowSolutions;
6
+ popover: {
7
+ isOpen: boolean;
8
+ setOpen: (open: boolean) => void;
9
+ };
10
+ actions: {
11
+ reset: () => void;
12
+ skip: () => void;
13
+ check: () => void;
14
+ };
15
+ };
16
+ /**
17
+ * A component that renders the debug check answer footer for Perseus items
18
+ */
19
+ export declare const DebugCheckAnswerFooter: ({ score, showSolutions, popover, actions, }: DebugCheckAnswerFooterProps) => React.ReactElement;
20
+ export {};
@@ -0,0 +1,13 @@
1
+ import * as React from "react";
2
+ type DebugHeaderProps = {
3
+ title: string;
4
+ isMobile: boolean;
5
+ isRtl: boolean;
6
+ onToggleMobile: (isMobile: boolean) => void;
7
+ onToggleRtl: (isRtl: boolean) => void;
8
+ };
9
+ /**
10
+ * A component that renders the header for the debug UI
11
+ */
12
+ export declare const DebugHeader: ({ title, isMobile, isRtl, onToggleMobile, onToggleRtl, }: DebugHeaderProps) => React.ReactElement;
13
+ export {};
@@ -0,0 +1,10 @@
1
+ import type { PerseusRenderer } from "@khanacademy/perseus-core";
2
+ /**
3
+ * Contract test helper that verifies widget ID extraction implementations
4
+ * produce identical results. Tests both the Renderer component method and
5
+ * the standalone utility function against the same scenarios to ensure
6
+ * behavioral consistency.
7
+ */
8
+ export declare function testWidgetIdExtraction(name: string, runExtractor: (r: PerseusRenderer, options?: {
9
+ inline?: boolean;
10
+ }) => readonly string[]): void;
@@ -0,0 +1,15 @@
1
+ declare const DEFAULT_FEATURE_FLAGS: {
2
+ "new-radio-widget": boolean;
3
+ "image-widget-upgrade": boolean;
4
+ "image-widget-upgrade-alignment": boolean;
5
+ };
6
+ /** Utility to get feature flags with optional overrides for testing.
7
+ * sample usage:
8
+ * getFeatureFlags({"image-widget-upgrade": true})
9
+ */
10
+ export declare function getFeatureFlags(overrides?: Partial<typeof DEFAULT_FEATURE_FLAGS>): {
11
+ "new-radio-widget": boolean;
12
+ "image-widget-upgrade": boolean;
13
+ "image-widget-upgrade-alignment": boolean;
14
+ };
15
+ export {};
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Mocks image loading done by the ImageLoader component to immediately trigger
3
+ * the load event.
4
+ * @returns A function to unmock the image loading
5
+ */
6
+ export declare const mockImageLoading: (options?: {
7
+ naturalWidth?: number;
8
+ naturalHeight?: number;
9
+ }) => () => void;
@@ -0,0 +1,51 @@
1
+ import * as React from "react";
2
+ import type { ServerItemRenderer } from "../server-item-renderer";
3
+ import type { APIOptions } from "../types";
4
+ import type { PerseusItem, ShowSolutions } from "@khanacademy/perseus-core";
5
+ /**
6
+ * Custom hook to manage the Server Item Renderer With Debug UI state
7
+ */
8
+ export declare const useItemRenderer: (item: PerseusItem, apiOptions?: APIOptions, startAnswerless?: boolean, reviewMode?: boolean, showSolutions?: ShowSolutions) => {
9
+ ref: React.RefObject<ServerItemRenderer>;
10
+ state: import("./item-renderer-reducer").ItemRendererState;
11
+ options: {
12
+ isMobile: boolean;
13
+ customKeypad: boolean;
14
+ showSolutions: ShowSolutions | undefined;
15
+ interactionCallback: () => void;
16
+ isArticle?: boolean;
17
+ onFocusChange?: (newFocusPath: import("..").FocusPath, oldFocusPath: import("..").FocusPath, keypadHeight?: number, focusedElement?: HTMLElement) => unknown;
18
+ showAlignmentOptions?: boolean;
19
+ readOnly?: boolean;
20
+ editingDisabled?: boolean;
21
+ answerableCallback?: (arg1: boolean) => unknown;
22
+ getAnotherHint?: () => unknown;
23
+ imagePlaceholder?: React.ReactNode;
24
+ widgetPlaceholder?: React.ReactNode;
25
+ baseElements?: {
26
+ Link: React.ComponentType<any>;
27
+ };
28
+ imagePreloader?: (dimensions: import("../types").Dimensions) => React.ReactNode;
29
+ trackInteraction?: (args: {
30
+ type: string;
31
+ id: string;
32
+ correct?: boolean;
33
+ } & Partial<import("../types").TrackingGradedGroupExtraArguments> & Partial<{
34
+ visible: number;
35
+ }>) => void;
36
+ nativeKeypadProxy?: (blur: () => void) => import("@khanacademy/math-input").KeypadAPI;
37
+ isMobileApp?: boolean;
38
+ setDrawingAreaAvailable?: (arg1: boolean) => unknown;
39
+ hintProgressColor?: string;
40
+ canScrollPage?: boolean;
41
+ editorChangeDelay?: number;
42
+ flags?: Record<"new-radio-widget" | "image-widget-upgrade" | "image-widget-upgrade-alignment", boolean>;
43
+ };
44
+ toggleMobile: (isMobile: boolean) => void;
45
+ toggleRtl: (isRtl: boolean) => void;
46
+ updateJson: (json: string) => boolean;
47
+ handleReset: () => void;
48
+ handleSkip: () => void;
49
+ handleCheck: () => void;
50
+ setShowPopover: (show: boolean) => void;
51
+ };
@@ -0,0 +1,48 @@
1
+ import type { PerseusItem, ShowSolutions, PerseusScore, UserInputMap } from "@khanacademy/perseus-core";
2
+ export type ItemRendererState = {
3
+ isMobile: boolean;
4
+ isRtl: boolean;
5
+ perseusItem: PerseusItem;
6
+ originalItem: PerseusItem;
7
+ answerless: boolean;
8
+ startAnswerless: boolean;
9
+ score: PerseusScore | undefined;
10
+ userInput: UserInputMap | undefined;
11
+ showPopover: boolean;
12
+ showSolutions: ShowSolutions | undefined;
13
+ hintsVisible: number;
14
+ key: number;
15
+ reviewMode: boolean;
16
+ };
17
+ export type ItemRendererAction = {
18
+ type: "TOGGLE_MOBILE";
19
+ payload: boolean;
20
+ } | {
21
+ type: "TOGGLE_RTL";
22
+ payload: boolean;
23
+ } | {
24
+ type: "UPDATE_ITEM";
25
+ payload: PerseusItem;
26
+ } | {
27
+ type: "SET_SCORE";
28
+ score: PerseusScore;
29
+ userInput: UserInputMap;
30
+ } | {
31
+ type: "TOGGLE_POPOVER";
32
+ payload: boolean;
33
+ } | {
34
+ type: "SET_SHOW_SOLUTIONS";
35
+ payload: ShowSolutions | undefined;
36
+ } | {
37
+ type: "SET_HINTS_VISIBLE";
38
+ payload: number;
39
+ } | {
40
+ type: "SET_ANSWERLESS";
41
+ payload: boolean;
42
+ } | {
43
+ type: "RESET_STATE";
44
+ } | {
45
+ type: "SKIP_TO_SOLUTION";
46
+ };
47
+ export declare const createInitialState: (item: PerseusItem, startAnswerless?: boolean, isMobile?: boolean, isRtl?: boolean, reviewMode?: boolean, showSolutions?: ShowSolutions) => ItemRendererState;
48
+ export declare const itemRendererReducer: (state: ItemRendererState, action: ItemRendererAction) => ItemRendererState;
@@ -0,0 +1 @@
1
+ export declare const clone: <T>(obj: T) => T;
@@ -0,0 +1,9 @@
1
+ import * as Perseus from "../index";
2
+ import type { APIOptions } from "../types";
3
+ import type { PerseusRenderer } from "@khanacademy/perseus-core";
4
+ /**
5
+ * Renders the given question using Cypress. Waits until all assets have been
6
+ * "rendered/loaded" before it returns.
7
+ */
8
+ declare const renderQuestion: (question: PerseusRenderer, apiOptions?: APIOptions, reviewMode?: boolean) => (() => Perseus.Renderer);
9
+ export default renderQuestion;
@@ -0,0 +1,18 @@
1
+ import * as React from "react";
2
+ import type { APIOptions } from "../types";
3
+ import type { PerseusItem, ShowSolutions } from "@khanacademy/perseus-core";
4
+ import type { LinterContextProps } from "@khanacademy/perseus-linter";
5
+ type Props = {
6
+ title?: string;
7
+ item: PerseusItem;
8
+ apiOptions?: APIOptions;
9
+ linterContext?: LinterContextProps;
10
+ startAnswerless?: boolean;
11
+ reviewMode?: boolean;
12
+ showSolutions?: ShowSolutions;
13
+ };
14
+ /**
15
+ * ServerItemRendererWithDebugUI is a component that renders a Perseus item with debug UI controls
16
+ */
17
+ export declare const ServerItemRendererWithDebugUI: ({ title, item, apiOptions, linterContext, reviewMode, startAnswerless, showSolutions, }: Props) => React.ReactElement;
18
+ export {};
@@ -0,0 +1,13 @@
1
+ import * as React from "react";
2
+ type Props = {
3
+ rendererTitle: React.ReactNode;
4
+ renderer: React.ReactNode;
5
+ JSONTitle?: string;
6
+ jsonObject: any;
7
+ };
8
+ /**
9
+ * This component is used in Storybook to render both the renderer and the JSON object in a split view.
10
+ * Currently, the renderer is displayed above the JSON object.
11
+ */
12
+ declare const SplitView: ({ rendererTitle, renderer, JSONTitle, jsonObject, }: Props) => React.ReactElement;
13
+ export default SplitView;
@@ -0,0 +1,7 @@
1
+ import type { PerseusDependencies, PerseusDependenciesV2 } from "../types";
2
+ export declare const testDependencies: PerseusDependencies;
3
+ export declare const testDependenciesV2: PerseusDependenciesV2;
4
+ export declare const storybookTestDependencies: PerseusDependencies;
5
+ export declare const storybookDependenciesV2: PerseusDependenciesV2;
6
+ export declare const cypressTestDependencies: PerseusDependencies;
7
+ export declare const cypressDependenciesV2: PerseusDependenciesV2;
@@ -0,0 +1,10 @@
1
+ import * as React from "react";
2
+ type Props = {
3
+ children: React.ReactElement;
4
+ /**
5
+ * Whether we need to offset the keypad to account for the footer.
6
+ */
7
+ hasFooter?: boolean;
8
+ };
9
+ declare const TestKeypadContextWrapper: ({ children, hasFooter, }: Props) => React.ReactElement;
10
+ export default TestKeypadContextWrapper;
@@ -0,0 +1,10 @@
1
+ import * as React from "react";
2
+ import "@khanacademy/mathjax-renderer/src/css/mathjax.css";
3
+ import "@khanacademy/mathjax-renderer/src/css/safari-hacks.css";
4
+ import "@khanacademy/mathjax-renderer/src/css/selectable.css";
5
+ type Props = {
6
+ children: string;
7
+ onRender?: (root?: any) => unknown;
8
+ };
9
+ export declare function TestMathjax({ children: tex, onRender }: Props): React.JSX.Element;
10
+ export {};
@@ -0,0 +1,7 @@
1
+ import * as React from "react";
2
+ import type { UserInputMap } from "@khanacademy/perseus-core";
3
+ type Props = {
4
+ userInput: UserInputMap;
5
+ };
6
+ export default function UserInputUI({ userInput }: Props): React.JSX.Element;
7
+ export {};
@@ -0,0 +1,27 @@
1
+ type WaitOptions = {
2
+ /**
3
+ * The time in milliseconds to wait on each wait.
4
+ * Defaults to 0. Any number less than 0 will be treated as 0.
5
+ */
6
+ delay?: number;
7
+ /**
8
+ * The number of times to wait.
9
+ * Defaults to 1. Any number below 1 will be treated as 1.
10
+ */
11
+ count?: number;
12
+ };
13
+ /**
14
+ * Wait for the given delay as many times as indicated.
15
+ *
16
+ * This will throw if jest.useRealTimers() is not used.
17
+ */
18
+ export declare const wait: (options?: WaitOptions) => Promise<void>;
19
+ /**
20
+ * Waits for the initial Graphie render.
21
+ *
22
+ * @returns a Promise<void> that resolves when the Graphie graph has renderred.
23
+ * The behaviour is undefined if there are multiple Graphies on the page (which
24
+ * is unlikely in tests).
25
+ */
26
+ export declare function waitForInitialGraphieRender(): Promise<void>;
27
+ export {};
package/dist/util.d.ts CHANGED
@@ -69,8 +69,6 @@ declare function gridDimensionConfig(absTickStep: number, extent: Coordinates, d
69
69
  * getGridStep([[-10, 10], [-10, 10]], [1, 1], 340)
70
70
  *
71
71
  * Returns: [1, 1]
72
- *
73
- * TODO(somewhatabstract, FEI-3464): Consolidate query string parsing functions.
74
72
  */
75
73
  declare function getGridStep(range: [Coordinates, Coordinates], step: Coordinates, boxSize: number): Coordinates;
76
74
  declare function snapStepFromGridStep(gridStep: [number, number]): [number, number];
@@ -17,7 +17,6 @@
17
17
  * convertTree; the computed position of this atom is added to this
18
18
  * object in place, in addition to being returned in the layout
19
19
  * instruction.
20
- * TODO(colin): refactor so that we don't need to modify this in place
21
20
  * atoms: the list of all atoms, as returned from convertTree, used to
22
21
  * position this atom appropriately relative to its neighbors
23
22
  * bonds: the list of all bonds, as returned from convertTree, used to
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": "74.0.2",
6
+ "version": "75.0.0",
7
7
  "publishConfig": {
8
8
  "access": "public"
9
9
  },
@@ -42,47 +42,45 @@
42
42
  "tiny-invariant": "1.3.1",
43
43
  "uuid": "^10.0.0",
44
44
  "@khanacademy/kas": "2.1.7",
45
- "@khanacademy/keypad-context": "3.2.30",
46
- "@khanacademy/kmath": "2.2.30",
47
- "@khanacademy/math-input": "26.3.11",
48
- "@khanacademy/perseus-core": "23.0.0",
49
- "@khanacademy/perseus-linter": "4.7.0",
50
- "@khanacademy/perseus-score": "8.2.7",
45
+ "@khanacademy/keypad-context": "3.2.31",
46
+ "@khanacademy/kmath": "2.2.31",
47
+ "@khanacademy/math-input": "26.3.12",
48
+ "@khanacademy/perseus-core": "23.0.1",
49
+ "@khanacademy/perseus-linter": "4.7.1",
50
+ "@khanacademy/perseus-score": "8.2.8",
51
51
  "@khanacademy/perseus-utils": "2.1.4",
52
52
  "@khanacademy/pure-markdown": "2.2.5",
53
53
  "@khanacademy/simple-markdown": "2.2.0"
54
54
  },
55
55
  "devDependencies": {
56
56
  "@khanacademy/wonder-blocks-announcer": "1.0.6",
57
- "@khanacademy/wonder-blocks-banner": "5.0.13",
58
- "@khanacademy/wonder-blocks-button": "11.3.2",
59
- "@khanacademy/wonder-blocks-clickable": "8.1.2",
57
+ "@khanacademy/wonder-blocks-banner": "5.0.15",
58
+ "@khanacademy/wonder-blocks-button": "11.3.4",
59
+ "@khanacademy/wonder-blocks-clickable": "8.1.3",
60
60
  "@khanacademy/wonder-blocks-core": "12.4.3",
61
61
  "@khanacademy/wonder-blocks-data": "15.0.1",
62
- "@khanacademy/wonder-blocks-dropdown": "10.6.7",
63
- "@khanacademy/wonder-blocks-form": "7.5.3",
64
- "@khanacademy/wonder-blocks-icon-button": "11.1.3",
62
+ "@khanacademy/wonder-blocks-dropdown": "10.7.1",
63
+ "@khanacademy/wonder-blocks-form": "7.5.4",
64
+ "@khanacademy/wonder-blocks-icon-button": "11.1.4",
65
65
  "@khanacademy/wonder-blocks-icon": "5.3.7",
66
66
  "@khanacademy/wonder-blocks-labeled-field": "4.0.14",
67
67
  "@khanacademy/wonder-blocks-layout": "3.1.44",
68
- "@khanacademy/wonder-blocks-link": "10.1.3",
69
- "@khanacademy/wonder-blocks-modal": "8.5.14",
70
- "@khanacademy/wonder-blocks-pill": "3.1.53",
71
- "@khanacademy/wonder-blocks-popover": "6.1.52",
68
+ "@khanacademy/wonder-blocks-link": "10.1.5",
69
+ "@khanacademy/wonder-blocks-modal": "8.5.15",
70
+ "@khanacademy/wonder-blocks-pill": "3.1.55",
71
+ "@khanacademy/wonder-blocks-popover": "6.1.53",
72
72
  "@khanacademy/wonder-blocks-progress-spinner": "3.1.44",
73
- "@khanacademy/wonder-blocks-switch": "3.3.27",
73
+ "@khanacademy/wonder-blocks-switch": "3.3.28",
74
74
  "@khanacademy/wonder-blocks-timing": "7.0.4",
75
75
  "@khanacademy/wonder-blocks-tokens": "15.0.0",
76
- "@khanacademy/wonder-blocks-tooltip": "4.1.65",
76
+ "@khanacademy/wonder-blocks-tooltip": "4.1.66",
77
77
  "@khanacademy/wonder-blocks-typography": "4.2.29",
78
78
  "@khanacademy/wonder-stuff-core": "3.0.0",
79
79
  "@phosphor-icons/core": "2.0.2",
80
80
  "@popperjs/core": "2.10.2",
81
81
  "aphrodite": "1.2.5",
82
82
  "classnames": "1.1.4",
83
- "intersection-observer": "^0.12.0",
84
83
  "jquery": "2.1.1",
85
- "lodash.debounce": "^4.0.8",
86
84
  "prop-types": "15.8.1",
87
85
  "react": "18.2.0",
88
86
  "react-dom": "18.2.0",
@@ -93,35 +91,33 @@
93
91
  },
94
92
  "peerDependencies": {
95
93
  "@khanacademy/wonder-blocks-announcer": "^1.0.6",
96
- "@khanacademy/wonder-blocks-banner": "^5.0.13",
97
- "@khanacademy/wonder-blocks-button": "^11.3.2",
98
- "@khanacademy/wonder-blocks-clickable": "^8.1.2",
94
+ "@khanacademy/wonder-blocks-banner": "^5.0.15",
95
+ "@khanacademy/wonder-blocks-button": "^11.3.4",
96
+ "@khanacademy/wonder-blocks-clickable": "^8.1.3",
99
97
  "@khanacademy/wonder-blocks-core": "^12.4.3",
100
98
  "@khanacademy/wonder-blocks-data": "^15.0.1",
101
- "@khanacademy/wonder-blocks-dropdown": "^10.6.7",
102
- "@khanacademy/wonder-blocks-form": "^7.5.3",
99
+ "@khanacademy/wonder-blocks-dropdown": "^10.7.1",
100
+ "@khanacademy/wonder-blocks-form": "^7.5.4",
103
101
  "@khanacademy/wonder-blocks-icon": "^5.3.7",
104
- "@khanacademy/wonder-blocks-icon-button": "^11.1.3",
102
+ "@khanacademy/wonder-blocks-icon-button": "^11.1.4",
105
103
  "@khanacademy/wonder-blocks-labeled-field": "^4.0.14",
106
104
  "@khanacademy/wonder-blocks-layout": "^3.1.44",
107
- "@khanacademy/wonder-blocks-link": "^10.1.3",
108
- "@khanacademy/wonder-blocks-modal": "^8.5.14",
109
- "@khanacademy/wonder-blocks-pill": "^3.1.53",
110
- "@khanacademy/wonder-blocks-popover": "^6.1.52",
105
+ "@khanacademy/wonder-blocks-link": "^10.1.5",
106
+ "@khanacademy/wonder-blocks-modal": "^8.5.15",
107
+ "@khanacademy/wonder-blocks-pill": "^3.1.55",
108
+ "@khanacademy/wonder-blocks-popover": "^6.1.53",
111
109
  "@khanacademy/wonder-blocks-progress-spinner": "^3.1.44",
112
- "@khanacademy/wonder-blocks-switch": "^3.3.27",
110
+ "@khanacademy/wonder-blocks-switch": "^3.3.28",
113
111
  "@khanacademy/wonder-blocks-timing": "^7.0.4",
114
112
  "@khanacademy/wonder-blocks-tokens": "^15.0.0",
115
- "@khanacademy/wonder-blocks-tooltip": "^4.1.65",
113
+ "@khanacademy/wonder-blocks-tooltip": "^4.1.66",
116
114
  "@khanacademy/wonder-blocks-typography": "^4.2.29",
117
115
  "@khanacademy/wonder-stuff-core": "^3.0.0",
118
116
  "@phosphor-icons/core": "^2.0.2",
119
117
  "@popperjs/core": "^2.10.2",
120
118
  "aphrodite": "^1.2.5",
121
119
  "classnames": "^1.1.4",
122
- "intersection-observer": "^0.12.0",
123
120
  "jquery": "^2.1.1",
124
- "lodash.debounce": "^4.0.8",
125
121
  "prop-types": "^15.8.1",
126
122
  "react": "^18.2.0",
127
123
  "react-dom": "^18.2.0",
@@ -130,7 +126,7 @@
130
126
  },
131
127
  "keywords": [],
132
128
  "khan": {
133
- "catalogHash": "cfe9661d5f76c8a2"
129
+ "catalogHash": "cb75588f4bb498b6"
134
130
  },
135
131
  "scripts": {}
136
132
  }
@@ -1 +0,0 @@
1
- export declare const isItemRenderableByVersion: (itemData: any, rendererContentVersion: any) => boolean;