@khanacademy/perseus 65.5.0 → 65.7.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.
- package/dist/es/index.css +1 -1
- package/dist/es/index.css.map +1 -1
- package/dist/es/index.js +57 -59
- package/dist/es/index.js.map +1 -1
- package/dist/index.css +1 -1
- package/dist/index.css.map +1 -1
- package/dist/index.js +56 -58
- package/dist/index.js.map +1 -1
- package/dist/widgets/interactive-graphs/graphs/components/angle-indicators.d.ts +11 -3
- package/dist/widgets/interactive-graphs/graphs/components/arrowhead.d.ts +1 -0
- package/dist/widgets/interactive-graphs/graphs/components/vector.d.ts +1 -0
- package/dist/widgets/interactive-graphs/interactive-graph-question-builder.d.ts +4 -0
- package/dist/widgets/python-program/python-program.d.ts +1 -2
- package/dist/widgets/radio/multiple-choice-component.new.d.ts +48 -0
- package/dist/widgets/radio/multiple-choice-widget.new.d.ts +117 -0
- package/dist/widgets/radio/utils/general-utils.d.ts +2 -2
- package/package.json +41 -41
- package/dist/widgets/radio/base-radio.new.d.ts +0 -45
- package/dist/widgets/radio/radio.class.new.d.ts +0 -40
- package/dist/widgets/radio/radio.new.d.ts +0 -30
|
@@ -6,12 +6,11 @@ import type { Interval } from "mafs";
|
|
|
6
6
|
interface PolygonAngleProps {
|
|
7
7
|
centerPoint: vec.Vector2;
|
|
8
8
|
endPoints: [vec.Vector2, vec.Vector2];
|
|
9
|
-
|
|
10
|
-
range: [Interval, Interval];
|
|
9
|
+
areEndPointsClockwise: boolean;
|
|
11
10
|
showAngles: boolean;
|
|
12
11
|
snapTo: SnapTo;
|
|
13
12
|
}
|
|
14
|
-
export declare const PolygonAngle: ({ centerPoint, endPoints,
|
|
13
|
+
export declare const PolygonAngle: ({ centerPoint, endPoints, showAngles, snapTo, areEndPointsClockwise, }: PolygonAngleProps) => React.JSX.Element | null;
|
|
15
14
|
interface AngleProps {
|
|
16
15
|
vertex: vec.Vector2;
|
|
17
16
|
coords: [vec.Vector2, vec.Vector2];
|
|
@@ -30,4 +29,13 @@ export declare const Angle: ({ vertex, coords, showAngles, allowReflexAngles, ra
|
|
|
30
29
|
* https://stackoverflow.com/questions/217578/how-can-i-determine-whether-a-2d-point-is-within-a-polygon
|
|
31
30
|
*/
|
|
32
31
|
export declare const shouldDrawArcOutside: (midpoint: vec.Vector2, vertex: vec.Vector2, range: [Interval, Interval], polygonLines: readonly CollinearTuple[]) => boolean;
|
|
32
|
+
/**
|
|
33
|
+
* Determines if an angle is an convex (false) or concave (true) angle.
|
|
34
|
+
* Uses the cross product to determine if the angle is outside the polygon.
|
|
35
|
+
* If the cross product is positive for a clockwise angle, the angle is concave.
|
|
36
|
+
* NOTE: This always has to take in clockwise endpoints. It cannot determine
|
|
37
|
+
* if the endpoints are clockwise itself - this has to be checked by the
|
|
38
|
+
* caller. This is because of edge cases involving concave polygons.
|
|
39
|
+
*/
|
|
40
|
+
export declare function shouldDrawArcOutsidePolygon(centerPoint: vec.Vector2, clockwiseEndpoints: [vec.Vector2, vec.Vector2]): boolean;
|
|
33
41
|
export {};
|
|
@@ -5,6 +5,7 @@ import type { AxisLabelLocation, CollinearTuple, LockedFigureColor, LockedFigure
|
|
|
5
5
|
export type LockedFunctionOptions = {
|
|
6
6
|
color?: LockedFigureColor;
|
|
7
7
|
strokeStyle?: LockedLineStyle;
|
|
8
|
+
weight?: StrokeWeight;
|
|
8
9
|
directionalAxis?: "x" | "y";
|
|
9
10
|
domain?: [min: number, max: number];
|
|
10
11
|
labels?: LockedFigureLabelOptions[];
|
|
@@ -123,12 +124,14 @@ declare class InteractiveGraphQuestionBuilder {
|
|
|
123
124
|
filled?: [boolean, boolean];
|
|
124
125
|
showPoint1?: boolean;
|
|
125
126
|
showPoint2?: boolean;
|
|
127
|
+
weight?: StrokeWeight;
|
|
126
128
|
labels?: LockedFigureLabelOptions[];
|
|
127
129
|
ariaLabel?: string;
|
|
128
130
|
}): InteractiveGraphQuestionBuilder;
|
|
129
131
|
addLockedVector(tail: vec.Vector2, tip: vec.Vector2, options?: {
|
|
130
132
|
color?: LockedFigureColor;
|
|
131
133
|
labels?: LockedFigureLabelOptions[];
|
|
134
|
+
weight?: StrokeWeight;
|
|
132
135
|
ariaLabel?: string;
|
|
133
136
|
}): InteractiveGraphQuestionBuilder;
|
|
134
137
|
addLockedEllipse(center: vec.Vector2, radius: [x: number, y: number], options?: {
|
|
@@ -136,6 +139,7 @@ declare class InteractiveGraphQuestionBuilder {
|
|
|
136
139
|
color?: LockedFigureColor;
|
|
137
140
|
fillStyle?: LockedFigureFillType;
|
|
138
141
|
strokeStyle?: "solid" | "dashed";
|
|
142
|
+
weight?: StrokeWeight;
|
|
139
143
|
labels?: LockedFigureLabelOptions[];
|
|
140
144
|
ariaLabel?: string;
|
|
141
145
|
}): InteractiveGraphQuestionBuilder;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as React from "react";
|
|
2
|
-
import type {
|
|
2
|
+
import type { Widget } from "../../types";
|
|
3
3
|
import type { UnsupportedWidgetPromptJSON } from "../../widget-ai-utils/unsupported-widget";
|
|
4
4
|
type Props = {
|
|
5
5
|
programID: string;
|
|
@@ -13,7 +13,6 @@ type DefaultProps = {
|
|
|
13
13
|
*/
|
|
14
14
|
declare class PythonProgram extends React.Component<Props> implements Widget {
|
|
15
15
|
static defaultProps: DefaultProps;
|
|
16
|
-
getDOMNodeForPath(path: FocusPath): null;
|
|
17
16
|
getPromptJSON(): UnsupportedWidgetPromptJSON;
|
|
18
17
|
render(): React.ReactNode;
|
|
19
18
|
}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { type PerseusRadioWidgetOptions } from "@khanacademy/perseus-core";
|
|
2
|
+
import * as React from "react";
|
|
3
|
+
import type { APIOptions } from "../../types";
|
|
4
|
+
/**
|
|
5
|
+
* Represents a single choice in the MultipleChoiceComponent
|
|
6
|
+
*/
|
|
7
|
+
export interface ChoiceType {
|
|
8
|
+
checked: boolean;
|
|
9
|
+
content: React.ReactNode;
|
|
10
|
+
rationale: React.ReactNode;
|
|
11
|
+
hasRationale: boolean;
|
|
12
|
+
showRationale: boolean;
|
|
13
|
+
showCorrectness: boolean;
|
|
14
|
+
correct: boolean;
|
|
15
|
+
isNoneOfTheAbove: boolean;
|
|
16
|
+
previouslyAnswered: boolean;
|
|
17
|
+
revealNoneOfTheAbove: boolean;
|
|
18
|
+
disabled: boolean;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Props for the MultipleChoiceComponent
|
|
22
|
+
*/
|
|
23
|
+
interface MultipleChoiceComponentProps {
|
|
24
|
+
apiOptions: APIOptions;
|
|
25
|
+
choices: ReadonlyArray<ChoiceType>;
|
|
26
|
+
countChoices: boolean | null | undefined;
|
|
27
|
+
editMode?: boolean;
|
|
28
|
+
isLastUsedWidget?: boolean;
|
|
29
|
+
labelWrap: boolean;
|
|
30
|
+
multipleSelect?: boolean;
|
|
31
|
+
numCorrect: number;
|
|
32
|
+
onChoiceChange: (choiceIndex: number, newCheckedState: boolean) => void;
|
|
33
|
+
reviewMode: boolean;
|
|
34
|
+
reviewModeRubric?: PerseusRadioWidgetOptions | null;
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* The MultipleChoiceComponent renders the UI for multiple choice questions.
|
|
38
|
+
*
|
|
39
|
+
* This component handles the presentation of choices, user interactions,
|
|
40
|
+
* and accessibility features, while the MultipleChoiceWidget manages the
|
|
41
|
+
* underlying logic and state.
|
|
42
|
+
*
|
|
43
|
+
* Supports both radio button (single select) and checkbox (multiple select) modes.
|
|
44
|
+
*
|
|
45
|
+
* Created as part of the Radio Revitalization Project (LEMS-2933).
|
|
46
|
+
*/
|
|
47
|
+
declare const MultipleChoiceComponent: ({ apiOptions, reviewModeRubric, reviewMode, editMode, multipleSelect, labelWrap, countChoices, numCorrect, isLastUsedWidget, choices, onChoiceChange, }: MultipleChoiceComponentProps) => React.ReactElement;
|
|
48
|
+
export default MultipleChoiceComponent;
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
import type { ChoiceType } from "./multiple-choice-component.new";
|
|
3
|
+
import type { PerseusStrings } from "../../strings";
|
|
4
|
+
import type { WidgetProps, ChoiceState, Widget } from "../../types";
|
|
5
|
+
import type { RadioPromptJSON } from "../../widget-ai-utils/radio/radio-ai-utils";
|
|
6
|
+
import type { PerseusRadioChoice, PerseusRadioRubric, PerseusRadioUserInput } from "@khanacademy/perseus-core";
|
|
7
|
+
export type RenderProps = {
|
|
8
|
+
numCorrect: number;
|
|
9
|
+
hasNoneOfTheAbove?: boolean;
|
|
10
|
+
multipleSelect?: boolean;
|
|
11
|
+
countChoices?: boolean;
|
|
12
|
+
deselectEnabled?: boolean;
|
|
13
|
+
choices: ReadonlyArray<RadioChoiceWithMetadata>;
|
|
14
|
+
selectedChoices: ReadonlyArray<PerseusRadioChoice["correct"]>;
|
|
15
|
+
choiceStates?: ReadonlyArray<ChoiceState>;
|
|
16
|
+
values?: ReadonlyArray<boolean>;
|
|
17
|
+
strings?: PerseusStrings;
|
|
18
|
+
editMode?: boolean;
|
|
19
|
+
labelWrap?: boolean;
|
|
20
|
+
};
|
|
21
|
+
/**
|
|
22
|
+
* RadioChoiceWithMetadata is used for server-side scoring
|
|
23
|
+
*/
|
|
24
|
+
export interface RadioChoiceWithMetadata extends PerseusRadioChoice {
|
|
25
|
+
originalIndex: number;
|
|
26
|
+
correct?: boolean;
|
|
27
|
+
}
|
|
28
|
+
type Props = WidgetProps<RenderProps, PerseusRadioUserInput, PerseusRadioRubric>;
|
|
29
|
+
type DefaultProps = Required<Pick<Props, "choices" | "multipleSelect" | "countChoices" | "deselectEnabled" | "linterContext" | "showSolutions">>;
|
|
30
|
+
/**
|
|
31
|
+
* MultipleChoiceWidget implements the Widget interface for multiple choice questions.
|
|
32
|
+
*
|
|
33
|
+
* It handles Perseus-specific logic and state management while delegating
|
|
34
|
+
* UI rendering to the MultipleChoiceComponent.
|
|
35
|
+
*
|
|
36
|
+
* This class is exported as "Radio" for backwards compatibility with existing content,
|
|
37
|
+
* though it supports both radio-button (single select) and checkbox (multiple select) modes.
|
|
38
|
+
* Eventually, when Content Backfills are set up, we will officially rename the Radio Widget to MultipleChoiceWidget.
|
|
39
|
+
*
|
|
40
|
+
* Created as part of the Radio Revitalization Project (LEMS-2933).
|
|
41
|
+
*/
|
|
42
|
+
declare class MultipleChoiceWidget extends React.Component<Props> implements Widget {
|
|
43
|
+
static defaultProps: DefaultProps;
|
|
44
|
+
/**
|
|
45
|
+
* DEPRECATED: Gets the current user input from this widget.
|
|
46
|
+
*
|
|
47
|
+
* Implements the required Widget interface method that Perseus uses
|
|
48
|
+
* to retrieve the user's current selections.
|
|
49
|
+
*
|
|
50
|
+
* @returns The user's selections as {choicesSelected: [boolean]}
|
|
51
|
+
*
|
|
52
|
+
* TODO: remove this when everything is pulling from Renderer state
|
|
53
|
+
* @deprecated get user input from Renderer state
|
|
54
|
+
*/
|
|
55
|
+
getUserInput(): PerseusRadioUserInput;
|
|
56
|
+
/**
|
|
57
|
+
* Gets the JSON representation of the User Input for AI assistance.
|
|
58
|
+
*
|
|
59
|
+
* This method is used to provide structured data about the widget's state
|
|
60
|
+
* to AI systems that can help users with answering questions.
|
|
61
|
+
*
|
|
62
|
+
* @returns A structured JSON object representing the widget's prompt
|
|
63
|
+
*/
|
|
64
|
+
getPromptJSON(): RadioPromptJSON;
|
|
65
|
+
/**
|
|
66
|
+
* Renders content that may contain nested widgets (currently only passage-refs).
|
|
67
|
+
* Parses the content, extracts any widgets, and returns a Renderer component
|
|
68
|
+
* configured with the appropriate context.
|
|
69
|
+
*
|
|
70
|
+
* @param content - The content to render (defaults to empty string)
|
|
71
|
+
* @returns A React element with the rendered content
|
|
72
|
+
*/
|
|
73
|
+
renderContent: (content?: string) => React.ReactNode;
|
|
74
|
+
/**
|
|
75
|
+
* Handles a user's selection of a choice.
|
|
76
|
+
*
|
|
77
|
+
* Updates choice states based on the selection, handles single/multiple
|
|
78
|
+
* selection logic, and notifies Perseus of the interaction.
|
|
79
|
+
*
|
|
80
|
+
* @param choiceIndex - The index of the choice that changed
|
|
81
|
+
* @param newCheckedState - Whether the choice is now selected
|
|
82
|
+
*/
|
|
83
|
+
handleChoiceChange: (choiceIndex: number, newCheckedState: boolean) => void;
|
|
84
|
+
/**
|
|
85
|
+
* Transforms choice states into component-ready props for the MultipleChoiceComponent.
|
|
86
|
+
*
|
|
87
|
+
* This method:
|
|
88
|
+
* 1. Processes each choice's content
|
|
89
|
+
* 2. Maps state properties (selected, rationaleShown, etc.) to component props
|
|
90
|
+
* 3. Renders content and rationales with nested widget support
|
|
91
|
+
* 4. Determines correctness display based on choice data or review rubric
|
|
92
|
+
*
|
|
93
|
+
* @param choiceStates - The current state of each choice
|
|
94
|
+
* @returns An array of formatted choice props ready for the MultipleChoiceComponent
|
|
95
|
+
*/
|
|
96
|
+
buildChoiceProps: (choiceStates: ReadonlyArray<ChoiceState>) => ReadonlyArray<ChoiceType>;
|
|
97
|
+
/**
|
|
98
|
+
* Prepares the choice props for rendering in the MultipleChoiceComponent.
|
|
99
|
+
*
|
|
100
|
+
* This method:
|
|
101
|
+
* 1. Uses getChoiceStates() to determine the appropriate state for each choice
|
|
102
|
+
* based on widget mode (review/static) and user selections
|
|
103
|
+
* 2. Transforms these states into component props via buildChoiceProps(),
|
|
104
|
+
* including rendered content, correctness indicators, and rationales
|
|
105
|
+
*
|
|
106
|
+
* @returns An array of choice props ready for the component
|
|
107
|
+
*/
|
|
108
|
+
prepareChoicesProps: () => readonly ChoiceType[];
|
|
109
|
+
/**
|
|
110
|
+
* Renders the MultipleChoiceComponent with the current props.
|
|
111
|
+
*
|
|
112
|
+
* @returns The rendered React component
|
|
113
|
+
*/
|
|
114
|
+
render(): React.ReactNode;
|
|
115
|
+
}
|
|
116
|
+
declare const Radio: typeof MultipleChoiceWidget;
|
|
117
|
+
export default Radio;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { type ShowSolutions } from "@khanacademy/perseus-core";
|
|
2
1
|
import type { ChoiceState } from "../../../types";
|
|
3
|
-
import type { RadioChoiceWithMetadata } from "../
|
|
2
|
+
import type { RadioChoiceWithMetadata } from "../multiple-choice-widget.new";
|
|
3
|
+
import type { ShowSolutions } from "@khanacademy/perseus-core";
|
|
4
4
|
interface GetChoiceStatesProps {
|
|
5
5
|
choices: ReadonlyArray<RadioChoiceWithMetadata>;
|
|
6
6
|
isStatic?: boolean | null;
|
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": "65.
|
|
6
|
+
"version": "65.7.0",
|
|
7
7
|
"publishConfig": {
|
|
8
8
|
"access": "public"
|
|
9
9
|
},
|
|
@@ -42,36 +42,36 @@
|
|
|
42
42
|
"tiny-invariant": "1.3.1",
|
|
43
43
|
"uuid": "^10.0.0",
|
|
44
44
|
"@khanacademy/kas": "2.0.9",
|
|
45
|
-
"@khanacademy/keypad-context": "3.0.
|
|
46
|
-
"@khanacademy/kmath": "2.0.
|
|
47
|
-
"@khanacademy/math-input": "26.0.
|
|
48
|
-
"@khanacademy/perseus-core": "
|
|
49
|
-
"@khanacademy/perseus-linter": "4.0.
|
|
50
|
-
"@khanacademy/perseus-score": "7.1.
|
|
45
|
+
"@khanacademy/keypad-context": "3.0.26",
|
|
46
|
+
"@khanacademy/kmath": "2.0.26",
|
|
47
|
+
"@khanacademy/math-input": "26.0.15",
|
|
48
|
+
"@khanacademy/perseus-core": "18.1.0",
|
|
49
|
+
"@khanacademy/perseus-linter": "4.0.13",
|
|
50
|
+
"@khanacademy/perseus-score": "7.1.13",
|
|
51
51
|
"@khanacademy/perseus-utils": "2.0.5",
|
|
52
52
|
"@khanacademy/pure-markdown": "2.0.10",
|
|
53
53
|
"@khanacademy/simple-markdown": "2.0.10"
|
|
54
54
|
},
|
|
55
55
|
"devDependencies": {
|
|
56
|
-
"@khanacademy/wonder-blocks-banner": "4.2.
|
|
57
|
-
"@khanacademy/wonder-blocks-button": "10.2.
|
|
58
|
-
"@khanacademy/wonder-blocks-clickable": "7.1.
|
|
56
|
+
"@khanacademy/wonder-blocks-banner": "4.2.7",
|
|
57
|
+
"@khanacademy/wonder-blocks-button": "10.2.11",
|
|
58
|
+
"@khanacademy/wonder-blocks-clickable": "7.1.15",
|
|
59
59
|
"@khanacademy/wonder-blocks-core": "12.3.0",
|
|
60
60
|
"@khanacademy/wonder-blocks-data": "14.1.4",
|
|
61
|
-
"@khanacademy/wonder-blocks-dropdown": "10.2.
|
|
62
|
-
"@khanacademy/wonder-blocks-form": "7.
|
|
63
|
-
"@khanacademy/wonder-blocks-icon-button": "10.3.
|
|
64
|
-
"@khanacademy/wonder-blocks-icon": "5.2.
|
|
65
|
-
"@khanacademy/wonder-blocks-labeled-field": "3.
|
|
66
|
-
"@khanacademy/wonder-blocks-layout": "3.1.
|
|
67
|
-
"@khanacademy/wonder-blocks-link": "9.1.
|
|
68
|
-
"@khanacademy/wonder-blocks-pill": "3.1.
|
|
69
|
-
"@khanacademy/wonder-blocks-popover": "6.1.
|
|
70
|
-
"@khanacademy/wonder-blocks-progress-spinner": "3.1.
|
|
71
|
-
"@khanacademy/wonder-blocks-switch": "3.3.
|
|
72
|
-
"@khanacademy/wonder-blocks-tokens": "11.
|
|
73
|
-
"@khanacademy/wonder-blocks-tooltip": "4.1.
|
|
74
|
-
"@khanacademy/wonder-blocks-typography": "4.2.
|
|
61
|
+
"@khanacademy/wonder-blocks-dropdown": "10.2.5",
|
|
62
|
+
"@khanacademy/wonder-blocks-form": "7.2.2",
|
|
63
|
+
"@khanacademy/wonder-blocks-icon-button": "10.3.10",
|
|
64
|
+
"@khanacademy/wonder-blocks-icon": "5.2.9",
|
|
65
|
+
"@khanacademy/wonder-blocks-labeled-field": "3.1.1",
|
|
66
|
+
"@khanacademy/wonder-blocks-layout": "3.1.26",
|
|
67
|
+
"@khanacademy/wonder-blocks-link": "9.1.15",
|
|
68
|
+
"@khanacademy/wonder-blocks-pill": "3.1.30",
|
|
69
|
+
"@khanacademy/wonder-blocks-popover": "6.1.18",
|
|
70
|
+
"@khanacademy/wonder-blocks-progress-spinner": "3.1.26",
|
|
71
|
+
"@khanacademy/wonder-blocks-switch": "3.3.8",
|
|
72
|
+
"@khanacademy/wonder-blocks-tokens": "11.3.1",
|
|
73
|
+
"@khanacademy/wonder-blocks-tooltip": "4.1.32",
|
|
74
|
+
"@khanacademy/wonder-blocks-typography": "4.2.11",
|
|
75
75
|
"@khanacademy/wonder-stuff-core": "1.5.5",
|
|
76
76
|
"@phosphor-icons/core": "2.0.2",
|
|
77
77
|
"@popperjs/core": "2.10.2",
|
|
@@ -90,25 +90,25 @@
|
|
|
90
90
|
"raphael": "1.5.4"
|
|
91
91
|
},
|
|
92
92
|
"peerDependencies": {
|
|
93
|
-
"@khanacademy/wonder-blocks-banner": "^4.2.
|
|
94
|
-
"@khanacademy/wonder-blocks-button": "^10.2.
|
|
95
|
-
"@khanacademy/wonder-blocks-clickable": "^7.1.
|
|
93
|
+
"@khanacademy/wonder-blocks-banner": "^4.2.7",
|
|
94
|
+
"@khanacademy/wonder-blocks-button": "^10.2.11",
|
|
95
|
+
"@khanacademy/wonder-blocks-clickable": "^7.1.15",
|
|
96
96
|
"@khanacademy/wonder-blocks-core": "^12.3.0",
|
|
97
97
|
"@khanacademy/wonder-blocks-data": "^14.1.4",
|
|
98
|
-
"@khanacademy/wonder-blocks-dropdown": "^10.2.
|
|
99
|
-
"@khanacademy/wonder-blocks-form": "^7.
|
|
100
|
-
"@khanacademy/wonder-blocks-icon": "^5.2.
|
|
101
|
-
"@khanacademy/wonder-blocks-icon-button": "^10.3.
|
|
102
|
-
"@khanacademy/wonder-blocks-labeled-field": "^3.
|
|
103
|
-
"@khanacademy/wonder-blocks-layout": "^3.1.
|
|
104
|
-
"@khanacademy/wonder-blocks-link": "^9.1.
|
|
105
|
-
"@khanacademy/wonder-blocks-pill": "^3.1.
|
|
106
|
-
"@khanacademy/wonder-blocks-popover": "^6.1.
|
|
107
|
-
"@khanacademy/wonder-blocks-progress-spinner": "^3.1.
|
|
108
|
-
"@khanacademy/wonder-blocks-switch": "^3.3.
|
|
109
|
-
"@khanacademy/wonder-blocks-tokens": "^11.
|
|
110
|
-
"@khanacademy/wonder-blocks-tooltip": "^4.1.
|
|
111
|
-
"@khanacademy/wonder-blocks-typography": "^4.2.
|
|
98
|
+
"@khanacademy/wonder-blocks-dropdown": "^10.2.5",
|
|
99
|
+
"@khanacademy/wonder-blocks-form": "^7.2.2",
|
|
100
|
+
"@khanacademy/wonder-blocks-icon": "^5.2.9",
|
|
101
|
+
"@khanacademy/wonder-blocks-icon-button": "^10.3.10",
|
|
102
|
+
"@khanacademy/wonder-blocks-labeled-field": "^3.1.1",
|
|
103
|
+
"@khanacademy/wonder-blocks-layout": "^3.1.26",
|
|
104
|
+
"@khanacademy/wonder-blocks-link": "^9.1.15",
|
|
105
|
+
"@khanacademy/wonder-blocks-pill": "^3.1.30",
|
|
106
|
+
"@khanacademy/wonder-blocks-popover": "^6.1.18",
|
|
107
|
+
"@khanacademy/wonder-blocks-progress-spinner": "^3.1.26",
|
|
108
|
+
"@khanacademy/wonder-blocks-switch": "^3.3.8",
|
|
109
|
+
"@khanacademy/wonder-blocks-tokens": "^11.3.1",
|
|
110
|
+
"@khanacademy/wonder-blocks-tooltip": "^4.1.32",
|
|
111
|
+
"@khanacademy/wonder-blocks-typography": "^4.2.11",
|
|
112
112
|
"@khanacademy/wonder-stuff-core": "^1.5.5",
|
|
113
113
|
"@phosphor-icons/core": "^2.0.2",
|
|
114
114
|
"@popperjs/core": "^2.10.2",
|
|
@@ -1,45 +0,0 @@
|
|
|
1
|
-
import { type PerseusRadioWidgetOptions } from "@khanacademy/perseus-core";
|
|
2
|
-
import * as React from "react";
|
|
3
|
-
import type { APIOptions } from "../../types";
|
|
4
|
-
export interface ChoiceType {
|
|
5
|
-
checked: boolean;
|
|
6
|
-
content: React.ReactNode;
|
|
7
|
-
rationale: React.ReactNode;
|
|
8
|
-
hasRationale: boolean;
|
|
9
|
-
showRationale: boolean;
|
|
10
|
-
showCorrectness: boolean;
|
|
11
|
-
correct: boolean;
|
|
12
|
-
isNoneOfTheAbove: boolean;
|
|
13
|
-
highlighted: boolean;
|
|
14
|
-
previouslyAnswered: boolean;
|
|
15
|
-
revealNoneOfTheAbove: boolean;
|
|
16
|
-
disabled: boolean;
|
|
17
|
-
}
|
|
18
|
-
interface BaseRadioProps {
|
|
19
|
-
apiOptions: APIOptions;
|
|
20
|
-
choices: ReadonlyArray<ChoiceType>;
|
|
21
|
-
deselectEnabled?: boolean;
|
|
22
|
-
editMode?: boolean;
|
|
23
|
-
labelWrap: boolean;
|
|
24
|
-
countChoices: boolean | null | undefined;
|
|
25
|
-
numCorrect: number;
|
|
26
|
-
multipleSelect?: boolean;
|
|
27
|
-
reviewModeRubric?: PerseusRadioWidgetOptions | null;
|
|
28
|
-
reviewMode: boolean;
|
|
29
|
-
onChange: (newValues: {
|
|
30
|
-
checked: ReadonlyArray<boolean>;
|
|
31
|
-
}) => void;
|
|
32
|
-
isLastUsedWidget?: boolean;
|
|
33
|
-
}
|
|
34
|
-
/**
|
|
35
|
-
* The BaseRadio component is the core component for the radio widget.
|
|
36
|
-
* It is responsible for rendering the radio choices and handling user interactions.
|
|
37
|
-
*
|
|
38
|
-
* This component is a duplicate of the BaseRadio component in base-radio.tsx for the
|
|
39
|
-
* Radio Revitalization Project. (LEMS-2933) This component will eventually replace
|
|
40
|
-
* base-radio.tsx when the feature flag is no longer needed.
|
|
41
|
-
*
|
|
42
|
-
* TODO(LEMS-2994): Clean up this file.
|
|
43
|
-
*/
|
|
44
|
-
declare const BaseRadio: ({ apiOptions, reviewModeRubric, reviewMode, choices, editMode, multipleSelect, labelWrap, countChoices, numCorrect, isLastUsedWidget, onChange, }: BaseRadioProps) => React.ReactElement;
|
|
45
|
-
export default BaseRadio;
|
|
@@ -1,40 +0,0 @@
|
|
|
1
|
-
import * as React from "react";
|
|
2
|
-
import type { WidgetProps, ChoiceState, Widget } from "../../types";
|
|
3
|
-
import type { RadioPromptJSON } from "../../widget-ai-utils/radio/radio-ai-utils";
|
|
4
|
-
import type { PerseusRadioChoice, PerseusRadioRubric, PerseusRadioUserInput } from "@khanacademy/perseus-core";
|
|
5
|
-
export type RenderProps = {
|
|
6
|
-
numCorrect: number;
|
|
7
|
-
hasNoneOfTheAbove?: boolean;
|
|
8
|
-
multipleSelect?: boolean;
|
|
9
|
-
countChoices?: boolean;
|
|
10
|
-
deselectEnabled?: boolean;
|
|
11
|
-
choices: ReadonlyArray<RadioChoiceWithMetadata>;
|
|
12
|
-
selectedChoices: ReadonlyArray<PerseusRadioChoice["correct"]>;
|
|
13
|
-
choiceStates?: ReadonlyArray<ChoiceState>;
|
|
14
|
-
values?: ReadonlyArray<boolean>;
|
|
15
|
-
};
|
|
16
|
-
type Props = WidgetProps<RenderProps, PerseusRadioUserInput, PerseusRadioRubric>;
|
|
17
|
-
type DefaultProps = Required<Pick<Props, "choices" | "multipleSelect" | "countChoices" | "deselectEnabled" | "linterContext" | "showSolutions">>;
|
|
18
|
-
export interface RadioChoiceWithMetadata extends PerseusRadioChoice {
|
|
19
|
-
originalIndex: number;
|
|
20
|
-
correct?: boolean;
|
|
21
|
-
}
|
|
22
|
-
/**
|
|
23
|
-
* This component is holds the class methods for the radio widget, that were split
|
|
24
|
-
* out of radio-component.new.tsx for the Radio Revitalization Project. (LEMS-2933)
|
|
25
|
-
* This component will be the main entry point for the radio widget when the feature
|
|
26
|
-
* flag is no longer needed.
|
|
27
|
-
*
|
|
28
|
-
* TODO(LEMS-2994): Clean up this file.
|
|
29
|
-
*/
|
|
30
|
-
declare class Radio extends React.Component<Props> implements Widget {
|
|
31
|
-
static defaultProps: DefaultProps;
|
|
32
|
-
/**
|
|
33
|
-
* TODO: remove this when everything is pulling from Renderer state
|
|
34
|
-
* @deprecated get user input from Renderer state
|
|
35
|
-
*/
|
|
36
|
-
getUserInput(): PerseusRadioUserInput;
|
|
37
|
-
getPromptJSON(): RadioPromptJSON;
|
|
38
|
-
render(): React.ReactNode;
|
|
39
|
-
}
|
|
40
|
-
export default Radio;
|
|
@@ -1,30 +0,0 @@
|
|
|
1
|
-
import * as React from "react";
|
|
2
|
-
import type { WidgetProps, ChoiceState } from "../../types";
|
|
3
|
-
import type { PerseusRadioChoice, ShowSolutions, PerseusRadioRubric, PerseusRadioUserInput } 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, PerseusRadioUserInput, 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: ({ choices, multipleSelect, countChoices, deselectEnabled, linterContext, showSolutions, static: isStatic, reviewModeRubric, reviewMode, apiOptions, isLastUsedWidget, questionCompleted, findWidgets, onChange, trackInteraction, numCorrect, choiceStates, values, }: RadioComponentProps) => React.ReactElement;
|
|
30
|
-
export default RadioComponent;
|