@khanacademy/perseus 17.0.0 → 17.1.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/CHANGELOG.md +59 -0
- package/dist/dependencies.d.ts +1 -0
- package/dist/es/index.css +20 -0
- package/dist/es/index.js +443 -338
- package/dist/es/index.js.map +1 -1
- package/dist/index.css +20 -0
- package/dist/index.js +444 -340
- package/dist/index.js.map +1 -1
- package/dist/perseus-types.d.ts +1 -0
- package/dist/strings.js +1 -0
- package/dist/widgets/label-image/answer-pill.d.ts +10 -0
- package/dist/widgets/label-image/hide-answers-toggle.d.ts +6 -0
- package/dist/widgets/label-image/marker.d.ts +6 -9
- package/dist/widgets/label-image/types.d.ts +1 -0
- package/dist/widgets/label-image.d.ts +101 -12
- package/package.json +30 -22
- package/src/__tests__/__snapshots__/renderer.test.tsx.snap +3 -3
- package/src/dependencies.ts +4 -0
- package/src/perseus-types.ts +2 -0
- package/src/styles/widgets/label-image.less +32 -0
- package/src/widgets/__stories__/label-image.stories.tsx +73 -3
- package/src/widgets/__testdata__/label-image.testdata.ts +118 -1
- package/src/widgets/__tests__/__snapshots__/dropdown.test.ts.snap +2 -2
- package/src/widgets/label-image/__stories__/answer-pill.stories.tsx +62 -0
- package/src/widgets/label-image/__tests__/answer-pill.test.tsx +83 -0
- package/src/widgets/label-image/__tests__/hide-answers-toggle.test.tsx +39 -0
- package/src/widgets/label-image/answer-choices.tsx +7 -1
- package/src/widgets/label-image/answer-pill.tsx +89 -0
- package/src/widgets/label-image/hide-answers-toggle.tsx +40 -0
- package/src/widgets/label-image/marker.tsx +116 -174
- package/src/widgets/label-image/types.ts +1 -0
- package/src/widgets/label-image.test.ts +142 -52
- package/src/widgets/label-image.tsx +212 -135
- package/tsconfig-build.tsbuildinfo +1 -1
package/dist/perseus-types.d.ts
CHANGED
package/dist/strings.js
CHANGED
|
@@ -20,6 +20,7 @@ module.exports = [
|
|
|
20
20
|
i18n.$_("[Marker for question %(number)s]", {}),
|
|
21
21
|
i18n.$_("[Sentence %(number)s]", {}),
|
|
22
22
|
i18n._("**Your answer should be** ", {}),
|
|
23
|
+
i18n.ngettext("%(num)s answer","%(num)s answers", {}),
|
|
23
24
|
i18n._("a *proper* fraction, like $1/2$ or $6/10$", {}),
|
|
24
25
|
i18n._("a *simplified improper* fraction, like $7/4$", {}),
|
|
25
26
|
i18n._("a *simplified proper* fraction, like $3/5$", {}),
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/// <reference types="react" />
|
|
2
|
+
import { type CSSProperties } from "aphrodite";
|
|
3
|
+
export declare const AnswerPill: (props: {
|
|
4
|
+
selectedAnswers: readonly string[];
|
|
5
|
+
showCorrectness?: "correct" | "incorrect";
|
|
6
|
+
markerRef?: HTMLElement;
|
|
7
|
+
side: "top" | "bottom" | "left" | "right";
|
|
8
|
+
onClick: () => void;
|
|
9
|
+
style?: CSSProperties;
|
|
10
|
+
}) => JSX.Element;
|
|
@@ -8,20 +8,17 @@ import type { InteractiveMarkerType } from "./types";
|
|
|
8
8
|
type Props = InteractiveMarkerType & {
|
|
9
9
|
showSelected: boolean;
|
|
10
10
|
showPulsate: boolean;
|
|
11
|
-
onClick: (e: MouseEvent) => void;
|
|
12
|
-
onKeyDown: (e: KeyboardEvent) => void;
|
|
11
|
+
onClick: (e: React.MouseEvent) => void;
|
|
12
|
+
onKeyDown: (e: React.KeyboardEvent) => void;
|
|
13
|
+
onFocus: () => void;
|
|
14
|
+
onBlur: () => void;
|
|
15
|
+
focused: boolean;
|
|
13
16
|
};
|
|
14
|
-
|
|
15
|
-
isFocused: boolean;
|
|
16
|
-
};
|
|
17
|
-
export default class Marker extends React.Component<Props, State> {
|
|
17
|
+
export default class Marker extends React.Component<Props> {
|
|
18
18
|
_icon: HTMLElement | null | undefined;
|
|
19
19
|
static defaultProps: {
|
|
20
20
|
selected: ReadonlyArray<any>;
|
|
21
21
|
};
|
|
22
|
-
state: State;
|
|
23
|
-
handleFocus(): void;
|
|
24
|
-
handleBlur(): void;
|
|
25
22
|
renderIcon(): React.ReactElement<React.ComponentProps<"div">>;
|
|
26
23
|
render(): React.ReactNode;
|
|
27
24
|
}
|
|
@@ -10,8 +10,10 @@ import * as React from "react";
|
|
|
10
10
|
import AnswerChoices from "./label-image/answer-choices";
|
|
11
11
|
import Marker from "./label-image/marker";
|
|
12
12
|
import type { InteractiveMarkerType, InteractiveMarkerScore } from "./label-image/types";
|
|
13
|
+
import type { DependencyProps } from "../dependencies";
|
|
13
14
|
import type { ChangeableProps } from "../mixins/changeable";
|
|
14
15
|
import type { APIOptions, PerseusScore } from "../types";
|
|
16
|
+
export type PreferredPopoverDirection = "NONE" | "UP" | "DOWN" | "LEFT" | "RIGHT";
|
|
15
17
|
type MarkersState = {
|
|
16
18
|
markers: ReadonlyArray<InteractiveMarkerType>;
|
|
17
19
|
};
|
|
@@ -33,7 +35,7 @@ type Point = {
|
|
|
33
35
|
x: number;
|
|
34
36
|
y: number;
|
|
35
37
|
};
|
|
36
|
-
type LabelImageProps = ChangeableProps & {
|
|
38
|
+
type LabelImageProps = ChangeableProps & DependencyProps & {
|
|
37
39
|
apiOptions: APIOptions;
|
|
38
40
|
choices: ReadonlyArray<string>;
|
|
39
41
|
imageAlt: string;
|
|
@@ -44,12 +46,15 @@ type LabelImageProps = ChangeableProps & {
|
|
|
44
46
|
multipleAnswers: boolean;
|
|
45
47
|
hideChoicesFromInstructions: boolean;
|
|
46
48
|
questionCompleted: boolean;
|
|
49
|
+
preferredPopoverDirection?: PreferredPopoverDirection;
|
|
47
50
|
};
|
|
48
51
|
type LabelImageState = {
|
|
49
|
-
|
|
52
|
+
activeMarkerIndex: number;
|
|
50
53
|
markersInteracted: boolean;
|
|
54
|
+
focusedMarkerIndex: number;
|
|
55
|
+
hideAnswers: boolean;
|
|
51
56
|
};
|
|
52
|
-
declare class LabelImage extends React.Component<LabelImageProps, LabelImageState> {
|
|
57
|
+
export declare class LabelImage extends React.Component<LabelImageProps, LabelImageState> {
|
|
53
58
|
_markers: Array<Marker | null | undefined>;
|
|
54
59
|
_selectedMarkerPopup: Popover | null | undefined;
|
|
55
60
|
_answerChoices: AnswerChoices | null | undefined;
|
|
@@ -64,7 +69,7 @@ declare class LabelImage extends React.Component<LabelImageProps, LabelImageStat
|
|
|
64
69
|
/**
|
|
65
70
|
* Determine the image side given a marker position (as percent of size).
|
|
66
71
|
*/
|
|
67
|
-
static imageSideForMarkerPosition(x: number, y: number): "bottom" | "left" | "right" | "top" | "center";
|
|
72
|
+
static imageSideForMarkerPosition(x: number, y: number, preferredDirection: PreferredPopoverDirection | undefined): "bottom" | "left" | "right" | "top" | "center";
|
|
68
73
|
/**
|
|
69
74
|
* Calculate the next marker to navigate to, from the "this marker".
|
|
70
75
|
*
|
|
@@ -73,17 +78,13 @@ declare class LabelImage extends React.Component<LabelImageProps, LabelImageStat
|
|
|
73
78
|
*/
|
|
74
79
|
static navigateToMarkerIndex(navigateDirection: Direction, markers: ReadonlyArray<InteractiveMarkerType>, thisIndex: number): number;
|
|
75
80
|
constructor(props: LabelImageProps);
|
|
76
|
-
componentDidMount(): void;
|
|
77
|
-
componentWillUnmount(): void;
|
|
78
81
|
simpleValidate(rubric: LabelImageProps): PerseusScore;
|
|
79
82
|
getUserInput(): MarkersState;
|
|
80
83
|
showRationalesForCurrentlySelectedChoices(rubric: LabelImageProps): void;
|
|
81
84
|
dismissMarkerPopup(): void;
|
|
82
|
-
handleDocumentClick: (e: MouseEvent) => void;
|
|
83
|
-
handleDocumentKeyDown: (e: KeyboardEvent) => void;
|
|
84
85
|
handleMarkerChange(index: number, marker: InteractiveMarkerType): void;
|
|
85
|
-
|
|
86
|
-
handleMarkerKeyDown(index: number, e: KeyboardEvent): void;
|
|
86
|
+
activateMarker(index: number): void;
|
|
87
|
+
handleMarkerKeyDown(index: number, e: React.KeyboardEvent): void;
|
|
87
88
|
handleAnswerChoicesChangeForMarker(index: number, selection: ReadonlyArray<boolean>): void;
|
|
88
89
|
renderAnswerChoicesForMarker(index: number, marker: InteractiveMarkerType): React.ReactElement<React.ComponentProps<"div">>;
|
|
89
90
|
renderMarkers(): ReadonlyArray<React.ReactNode>;
|
|
@@ -93,7 +94,51 @@ declare class LabelImage extends React.Component<LabelImageProps, LabelImageStat
|
|
|
93
94
|
declare const _default: Readonly<{
|
|
94
95
|
name: string;
|
|
95
96
|
displayName: string;
|
|
96
|
-
getWidget?: (() =>
|
|
97
|
+
getWidget?: (() => React.ForwardRefExoticComponent<Omit<ChangeableProps & Partial<import("../types").PerseusDependenciesV2> & {
|
|
98
|
+
apiOptions: Readonly<{
|
|
99
|
+
isArticle?: boolean | undefined;
|
|
100
|
+
onInputError?: ((widgetId: any, value: string, message?: string | null | undefined) => unknown) | undefined;
|
|
101
|
+
onFocusChange?: ((newFocusPath: import("../types").FocusPath, oldFocusPath: import("../types").FocusPath, keypadElement?: Element | Text | null | undefined, focusedElement?: HTMLElement | undefined) => unknown) | undefined;
|
|
102
|
+
GroupMetadataEditor?: React.ComponentType<any> | undefined;
|
|
103
|
+
showAlignmentOptions?: boolean | undefined;
|
|
104
|
+
readOnly?: boolean | undefined;
|
|
105
|
+
answerableCallback?: ((arg1: boolean) => unknown) | undefined;
|
|
106
|
+
getAnotherHint?: (() => unknown) | undefined;
|
|
107
|
+
interactionCallback?: (() => unknown) | undefined;
|
|
108
|
+
groupAnnotator?: ((groupNumber: number, widgetId: string) => React.ReactNode) | undefined;
|
|
109
|
+
imagePlaceholder?: React.ReactNode;
|
|
110
|
+
widgetPlaceholder?: React.ReactNode;
|
|
111
|
+
baseElements?: {
|
|
112
|
+
Link: React.ComponentType<any>;
|
|
113
|
+
} | undefined;
|
|
114
|
+
imagePreloader?: ((dimensions: import("../types").Dimensions) => React.ReactNode) | undefined;
|
|
115
|
+
trackInteraction?: ((args: {
|
|
116
|
+
type: string;
|
|
117
|
+
id: string;
|
|
118
|
+
correct?: boolean | undefined;
|
|
119
|
+
} & Partial<import("../types").TrackingGradedGroupExtraArguments> & Partial<import("../types").TrackingSequenceExtraArguments>) => void) | undefined;
|
|
120
|
+
customKeypad?: boolean | undefined;
|
|
121
|
+
nativeKeypadProxy?: ((blur: () => void) => import("@khanacademy/math-input").KeypadAPI) | undefined;
|
|
122
|
+
isMobile?: boolean | undefined;
|
|
123
|
+
setDrawingAreaAvailable?: ((arg1: boolean) => unknown) | undefined;
|
|
124
|
+
useDraftEditor?: boolean | undefined;
|
|
125
|
+
hintProgressColor?: string | undefined;
|
|
126
|
+
canScrollPage?: boolean | undefined;
|
|
127
|
+
inModal?: boolean | undefined;
|
|
128
|
+
crossOutEnabled?: boolean | undefined;
|
|
129
|
+
editorChangeDelay?: number | undefined;
|
|
130
|
+
}>;
|
|
131
|
+
choices: readonly string[];
|
|
132
|
+
imageAlt: string;
|
|
133
|
+
imageUrl: string;
|
|
134
|
+
imageWidth: number;
|
|
135
|
+
imageHeight: number;
|
|
136
|
+
markers: readonly InteractiveMarkerType[];
|
|
137
|
+
multipleAnswers: boolean;
|
|
138
|
+
hideChoicesFromInstructions: boolean;
|
|
139
|
+
questionCompleted: boolean;
|
|
140
|
+
preferredPopoverDirection?: PreferredPopoverDirection | undefined;
|
|
141
|
+
}, "analytics"> & React.RefAttributes<LabelImage>>) | undefined;
|
|
97
142
|
accessible?: boolean | ((props: any) => boolean) | undefined;
|
|
98
143
|
hidden?: boolean | undefined;
|
|
99
144
|
version?: import("../types").Version | undefined;
|
|
@@ -108,6 +153,50 @@ declare const _default: Readonly<{
|
|
|
108
153
|
propUpgrades?: {
|
|
109
154
|
[key: string]: (arg1: any) => any;
|
|
110
155
|
} | undefined;
|
|
111
|
-
widget:
|
|
156
|
+
widget: React.ForwardRefExoticComponent<Omit<ChangeableProps & Partial<import("../types").PerseusDependenciesV2> & {
|
|
157
|
+
apiOptions: Readonly<{
|
|
158
|
+
isArticle?: boolean | undefined;
|
|
159
|
+
onInputError?: ((widgetId: any, value: string, message?: string | null | undefined) => unknown) | undefined;
|
|
160
|
+
onFocusChange?: ((newFocusPath: import("../types").FocusPath, oldFocusPath: import("../types").FocusPath, keypadElement?: Element | Text | null | undefined, focusedElement?: HTMLElement | undefined) => unknown) | undefined;
|
|
161
|
+
GroupMetadataEditor?: React.ComponentType<any> | undefined;
|
|
162
|
+
showAlignmentOptions?: boolean | undefined;
|
|
163
|
+
readOnly?: boolean | undefined;
|
|
164
|
+
answerableCallback?: ((arg1: boolean) => unknown) | undefined;
|
|
165
|
+
getAnotherHint?: (() => unknown) | undefined;
|
|
166
|
+
interactionCallback?: (() => unknown) | undefined;
|
|
167
|
+
groupAnnotator?: ((groupNumber: number, widgetId: string) => React.ReactNode) | undefined;
|
|
168
|
+
imagePlaceholder?: React.ReactNode;
|
|
169
|
+
widgetPlaceholder?: React.ReactNode;
|
|
170
|
+
baseElements?: {
|
|
171
|
+
Link: React.ComponentType<any>;
|
|
172
|
+
} | undefined;
|
|
173
|
+
imagePreloader?: ((dimensions: import("../types").Dimensions) => React.ReactNode) | undefined;
|
|
174
|
+
trackInteraction?: ((args: {
|
|
175
|
+
type: string;
|
|
176
|
+
id: string;
|
|
177
|
+
correct?: boolean | undefined;
|
|
178
|
+
} & Partial<import("../types").TrackingGradedGroupExtraArguments> & Partial<import("../types").TrackingSequenceExtraArguments>) => void) | undefined;
|
|
179
|
+
customKeypad?: boolean | undefined;
|
|
180
|
+
nativeKeypadProxy?: ((blur: () => void) => import("@khanacademy/math-input").KeypadAPI) | undefined;
|
|
181
|
+
isMobile?: boolean | undefined;
|
|
182
|
+
setDrawingAreaAvailable?: ((arg1: boolean) => unknown) | undefined;
|
|
183
|
+
useDraftEditor?: boolean | undefined;
|
|
184
|
+
hintProgressColor?: string | undefined;
|
|
185
|
+
canScrollPage?: boolean | undefined;
|
|
186
|
+
inModal?: boolean | undefined;
|
|
187
|
+
crossOutEnabled?: boolean | undefined;
|
|
188
|
+
editorChangeDelay?: number | undefined;
|
|
189
|
+
}>;
|
|
190
|
+
choices: readonly string[];
|
|
191
|
+
imageAlt: string;
|
|
192
|
+
imageUrl: string;
|
|
193
|
+
imageWidth: number;
|
|
194
|
+
imageHeight: number;
|
|
195
|
+
markers: readonly InteractiveMarkerType[];
|
|
196
|
+
multipleAnswers: boolean;
|
|
197
|
+
hideChoicesFromInstructions: boolean;
|
|
198
|
+
questionCompleted: boolean;
|
|
199
|
+
preferredPopoverDirection?: PreferredPopoverDirection | undefined;
|
|
200
|
+
}, "analytics"> & React.RefAttributes<LabelImage>>;
|
|
112
201
|
}>;
|
|
113
202
|
export default _default;
|
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": "17.
|
|
6
|
+
"version": "17.1.0",
|
|
7
7
|
"publishConfig": {
|
|
8
8
|
"access": "public"
|
|
9
9
|
},
|
|
@@ -22,33 +22,36 @@
|
|
|
22
22
|
"test": "bash -c 'yarn --silent --cwd \"../..\" test ${@:0} $($([[ ${@: -1} = -* ]] || [[ ${@: -1} = bash ]]) && echo $PWD)'"
|
|
23
23
|
},
|
|
24
24
|
"dependencies": {
|
|
25
|
-
"@khanacademy/kas": "^0.3.
|
|
26
|
-
"@khanacademy/kmath": "^0.1.
|
|
27
|
-
"@khanacademy/math-input": "^16.1.
|
|
28
|
-
"@khanacademy/perseus-core": "1.4.
|
|
29
|
-
"@khanacademy/perseus-linter": "^0.3.
|
|
30
|
-
"@khanacademy/pure-markdown": "^0.2.
|
|
31
|
-
"@khanacademy/simple-markdown": "^0.11.
|
|
25
|
+
"@khanacademy/kas": "^0.3.7",
|
|
26
|
+
"@khanacademy/kmath": "^0.1.8",
|
|
27
|
+
"@khanacademy/math-input": "^16.1.2",
|
|
28
|
+
"@khanacademy/perseus-core": "1.4.1",
|
|
29
|
+
"@khanacademy/perseus-linter": "^0.3.10",
|
|
30
|
+
"@khanacademy/pure-markdown": "^0.2.13",
|
|
31
|
+
"@khanacademy/simple-markdown": "^0.11.2"
|
|
32
32
|
},
|
|
33
33
|
"devDependencies": {
|
|
34
|
-
"@khanacademy/wonder-blocks-button": "^6.2.
|
|
34
|
+
"@khanacademy/wonder-blocks-button": "^6.2.4",
|
|
35
35
|
"@khanacademy/wonder-blocks-clickable": "^4.0.11",
|
|
36
36
|
"@khanacademy/wonder-blocks-color": "^3.0.0",
|
|
37
37
|
"@khanacademy/wonder-blocks-core": "^6.3.0",
|
|
38
38
|
"@khanacademy/wonder-blocks-data": "^13.0.5",
|
|
39
|
-
"@khanacademy/wonder-blocks-dropdown": "^
|
|
40
|
-
"@khanacademy/wonder-blocks-form": "^4.3.
|
|
39
|
+
"@khanacademy/wonder-blocks-dropdown": "^4.0.0",
|
|
40
|
+
"@khanacademy/wonder-blocks-form": "^4.3.18",
|
|
41
41
|
"@khanacademy/wonder-blocks-i18n": "^2.0.2",
|
|
42
42
|
"@khanacademy/wonder-blocks-layout": "^2.0.24",
|
|
43
|
-
"@khanacademy/wonder-blocks-link": "^6.0.
|
|
44
|
-
"@khanacademy/wonder-blocks-modal": "^4.0.
|
|
45
|
-
"@khanacademy/wonder-blocks-
|
|
43
|
+
"@khanacademy/wonder-blocks-link": "^6.0.4",
|
|
44
|
+
"@khanacademy/wonder-blocks-modal": "^4.0.38",
|
|
45
|
+
"@khanacademy/wonder-blocks-pill": "^1.0.14",
|
|
46
|
+
"@khanacademy/wonder-blocks-popover": "^3.0.19",
|
|
46
47
|
"@khanacademy/wonder-blocks-progress-spinner": "^2.0.24",
|
|
47
48
|
"@khanacademy/wonder-blocks-spacing": "^4.0.1",
|
|
48
|
-
"@khanacademy/wonder-blocks-
|
|
49
|
+
"@khanacademy/wonder-blocks-switch": "^1.1.8",
|
|
50
|
+
"@khanacademy/wonder-blocks-tooltip": "^2.1.21",
|
|
49
51
|
"@khanacademy/wonder-blocks-typography": "^2.1.9",
|
|
50
52
|
"@khanacademy/wonder-stuff-core": "^1.5.1",
|
|
51
53
|
"@phosphor-icons/core": "^2.0.2",
|
|
54
|
+
"@popperjs/core": "^2.10.1",
|
|
52
55
|
"aphrodite": "^1.2.5",
|
|
53
56
|
"classnames": "^1.1.4",
|
|
54
57
|
"create-react-class": "^15.6.3",
|
|
@@ -63,27 +66,31 @@
|
|
|
63
66
|
"prop-types": "^15.6.1",
|
|
64
67
|
"react": "16.14.0",
|
|
65
68
|
"react-dom": "16.14.0",
|
|
69
|
+
"react-popper": "^2.0.0",
|
|
66
70
|
"underscore": "^1.4.4"
|
|
67
71
|
},
|
|
68
72
|
"peerDependencies": {
|
|
69
|
-
"@khanacademy/wonder-blocks-button": "^6.2.
|
|
73
|
+
"@khanacademy/wonder-blocks-button": "^6.2.4",
|
|
70
74
|
"@khanacademy/wonder-blocks-clickable": "^4.0.11",
|
|
71
75
|
"@khanacademy/wonder-blocks-color": "^3.0.0",
|
|
72
76
|
"@khanacademy/wonder-blocks-core": "^6.3.0",
|
|
73
77
|
"@khanacademy/wonder-blocks-data": "^13.0.5",
|
|
74
|
-
"@khanacademy/wonder-blocks-dropdown": "^
|
|
75
|
-
"@khanacademy/wonder-blocks-form": "^4.3.
|
|
78
|
+
"@khanacademy/wonder-blocks-dropdown": "^4.0.0",
|
|
79
|
+
"@khanacademy/wonder-blocks-form": "^4.3.18",
|
|
76
80
|
"@khanacademy/wonder-blocks-i18n": "^2.0.2",
|
|
77
81
|
"@khanacademy/wonder-blocks-layout": "^2.0.24",
|
|
78
|
-
"@khanacademy/wonder-blocks-link": "^6.0.
|
|
79
|
-
"@khanacademy/wonder-blocks-modal": "^4.0.
|
|
80
|
-
"@khanacademy/wonder-blocks-
|
|
82
|
+
"@khanacademy/wonder-blocks-link": "^6.0.4",
|
|
83
|
+
"@khanacademy/wonder-blocks-modal": "^4.0.38",
|
|
84
|
+
"@khanacademy/wonder-blocks-pill": "^1.0.14",
|
|
85
|
+
"@khanacademy/wonder-blocks-popover": "^3.0.19",
|
|
81
86
|
"@khanacademy/wonder-blocks-progress-spinner": "^2.0.24",
|
|
82
87
|
"@khanacademy/wonder-blocks-spacing": "^4.0.1",
|
|
83
|
-
"@khanacademy/wonder-blocks-
|
|
88
|
+
"@khanacademy/wonder-blocks-switch": "^1.1.8",
|
|
89
|
+
"@khanacademy/wonder-blocks-tooltip": "^2.1.21",
|
|
84
90
|
"@khanacademy/wonder-blocks-typography": "^2.1.9",
|
|
85
91
|
"@khanacademy/wonder-stuff-core": "^1.5.1",
|
|
86
92
|
"@phosphor-icons/core": "^2.0.2",
|
|
93
|
+
"@popperjs/core": "^2.10.1",
|
|
87
94
|
"aphrodite": "^1.2.5",
|
|
88
95
|
"classnames": "^1.1.4",
|
|
89
96
|
"create-react-class": "^15.6.3",
|
|
@@ -93,6 +100,7 @@
|
|
|
93
100
|
"prop-types": "^15.6.1",
|
|
94
101
|
"react": "16.14.0",
|
|
95
102
|
"react-dom": "16.14.0",
|
|
103
|
+
"react-popper": "^2.0.0",
|
|
96
104
|
"underscore": "^1.4.4"
|
|
97
105
|
},
|
|
98
106
|
"keywords": []
|
|
@@ -369,7 +369,7 @@ exports[`renderer snapshots correct answer: correct answer 1`] = `
|
|
|
369
369
|
</span>
|
|
370
370
|
<span
|
|
371
371
|
aria-hidden="true"
|
|
372
|
-
class="
|
|
372
|
+
class="svg_1q6jc65-o_O-icon_eocf2p-o_O-caret_ntkmq-o_O-inlineStyles_u7ovp6"
|
|
373
373
|
/>
|
|
374
374
|
</button>
|
|
375
375
|
</div>
|
|
@@ -434,7 +434,7 @@ exports[`renderer snapshots incorrect answer: incorrect answer 1`] = `
|
|
|
434
434
|
</span>
|
|
435
435
|
<span
|
|
436
436
|
aria-hidden="true"
|
|
437
|
-
class="
|
|
437
|
+
class="svg_1q6jc65-o_O-icon_eocf2p-o_O-caret_ntkmq-o_O-inlineStyles_u7ovp6"
|
|
438
438
|
/>
|
|
439
439
|
</button>
|
|
440
440
|
</div>
|
|
@@ -499,7 +499,7 @@ exports[`renderer snapshots initial render: initial render 1`] = `
|
|
|
499
499
|
</span>
|
|
500
500
|
<span
|
|
501
501
|
aria-hidden="true"
|
|
502
|
-
class="
|
|
502
|
+
class="svg_1q6jc65-o_O-icon_eocf2p-o_O-caret_ntkmq-o_O-inlineStyles_u7ovp6"
|
|
503
503
|
/>
|
|
504
504
|
</button>
|
|
505
505
|
</div>
|
package/src/dependencies.ts
CHANGED
|
@@ -22,6 +22,10 @@ export const getDependencies = (): PerseusDependencies => {
|
|
|
22
22
|
);
|
|
23
23
|
};
|
|
24
24
|
|
|
25
|
+
export type DependencyProps = Partial<
|
|
26
|
+
React.ContextType<typeof DependenciesContext>
|
|
27
|
+
>;
|
|
28
|
+
|
|
25
29
|
export const DependenciesContext = React.createContext<PerseusDependenciesV2>({
|
|
26
30
|
analytics: {onAnalyticsEvent: async () => {}},
|
|
27
31
|
});
|
package/src/perseus-types.ts
CHANGED
|
@@ -73,6 +73,8 @@ export type PerseusAnswerArea = {
|
|
|
73
73
|
calculator: boolean;
|
|
74
74
|
// The user might benefit from using a Periodic Table of Elements. Provided on Khan Academy when true
|
|
75
75
|
periodicTable: boolean;
|
|
76
|
+
// The user might benefit from using a Periodic Table of Elements with key. Provided on Khan Academy when true
|
|
77
|
+
periodicTableWithKey?: boolean;
|
|
76
78
|
};
|
|
77
79
|
|
|
78
80
|
type Widget<Type extends string, Options> = {
|
|
@@ -5,6 +5,38 @@
|
|
|
5
5
|
margin: 0;
|
|
6
6
|
}
|
|
7
7
|
}
|
|
8
|
+
button[id*="perseus-label-image-widget-answer-pill"],
|
|
9
|
+
div[id*="perseus-label-image-widget-answer-pill"] {
|
|
10
|
+
// Reset text content.
|
|
11
|
+
div.paragraph {
|
|
12
|
+
all: revert;
|
|
13
|
+
}
|
|
14
|
+
// Allow for padding around math content. Accounting for the negative margin here:
|
|
15
|
+
// https://github.com/Khan/perseus/blob/bafd35daee723456bf259a39b88e7638d91c8c3b/packages/perseus/src/renderer.tsx#L1176
|
|
16
|
+
div.perseus-block-math-inner {
|
|
17
|
+
margin: -5px 0 !important;
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
// Reset mobile text content for answer pills.
|
|
23
|
+
@media (max-width: 767px) {
|
|
24
|
+
[id*="perseus-label-image-widget-answer-pill"] {
|
|
25
|
+
div.paragraph {
|
|
26
|
+
all: revert;
|
|
27
|
+
}
|
|
28
|
+
> div.perseus-renderer-responsive {
|
|
29
|
+
all: revert;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
.framework-perseus.perseus-mobile
|
|
34
|
+
[id*="perseus-label-image-widget-answer-pill"] {
|
|
35
|
+
.perseus-renderer > .paragraph,
|
|
36
|
+
.perseus-renderer > .paragraph .paragraph {
|
|
37
|
+
all: revert;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
8
40
|
}
|
|
9
41
|
|
|
10
42
|
.framework-perseus:not(.perseus-article).perseus-mobile {
|
|
@@ -1,12 +1,44 @@
|
|
|
1
1
|
import * as React from "react";
|
|
2
2
|
|
|
3
3
|
import {RendererWithDebugUI} from "../../../../../testing/renderer-with-debug-ui";
|
|
4
|
-
import {
|
|
4
|
+
import {
|
|
5
|
+
textQuestion,
|
|
6
|
+
mathQuestion,
|
|
7
|
+
numberline,
|
|
8
|
+
} from "../__testdata__/label-image.testdata";
|
|
5
9
|
|
|
10
|
+
import type {PerseusRenderer} from "../../perseus-types";
|
|
6
11
|
import type {APIOptions} from "../../types";
|
|
7
12
|
|
|
13
|
+
const applyStoryArgs = (
|
|
14
|
+
question: PerseusRenderer,
|
|
15
|
+
args: StoryArgs,
|
|
16
|
+
): PerseusRenderer => {
|
|
17
|
+
const q = {
|
|
18
|
+
...question,
|
|
19
|
+
widgets: {},
|
|
20
|
+
} as const;
|
|
21
|
+
|
|
22
|
+
for (const [widgetId, widget] of Object.entries(question.widgets)) {
|
|
23
|
+
const modified = {
|
|
24
|
+
...widget,
|
|
25
|
+
options: {
|
|
26
|
+
...widget.options,
|
|
27
|
+
preferredPopoverDirection: args.preferredPopoverDirection,
|
|
28
|
+
},
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
q.widgets[widgetId] = {
|
|
32
|
+
...modified,
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
return q;
|
|
37
|
+
};
|
|
38
|
+
|
|
8
39
|
type StoryArgs = {
|
|
9
40
|
isMobile: boolean;
|
|
41
|
+
preferredPopoverDirection: string;
|
|
10
42
|
};
|
|
11
43
|
|
|
12
44
|
type ImageStory = {
|
|
@@ -14,17 +46,55 @@ type ImageStory = {
|
|
|
14
46
|
args: StoryArgs;
|
|
15
47
|
};
|
|
16
48
|
|
|
17
|
-
export const
|
|
49
|
+
export const LabelWidgetWithText = (args: StoryArgs): React.ReactElement => {
|
|
50
|
+
const apiOptions: APIOptions = {
|
|
51
|
+
isMobile: args.isMobile,
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
return (
|
|
55
|
+
<RendererWithDebugUI
|
|
56
|
+
question={applyStoryArgs(textQuestion, args)}
|
|
57
|
+
apiOptions={apiOptions}
|
|
58
|
+
/>
|
|
59
|
+
);
|
|
60
|
+
};
|
|
61
|
+
|
|
62
|
+
export const LabelWidgetWithMath = (args: StoryArgs): React.ReactElement => {
|
|
18
63
|
const apiOptions: APIOptions = {
|
|
19
64
|
isMobile: args.isMobile,
|
|
20
65
|
};
|
|
21
66
|
|
|
22
|
-
return
|
|
67
|
+
return (
|
|
68
|
+
<RendererWithDebugUI
|
|
69
|
+
question={applyStoryArgs(mathQuestion, args)}
|
|
70
|
+
apiOptions={apiOptions}
|
|
71
|
+
/>
|
|
72
|
+
);
|
|
73
|
+
};
|
|
74
|
+
|
|
75
|
+
export const LabelImageNumberline = (args: StoryArgs): React.ReactElement => {
|
|
76
|
+
const apiOptions: APIOptions = {
|
|
77
|
+
isMobile: args.isMobile,
|
|
78
|
+
};
|
|
79
|
+
|
|
80
|
+
return (
|
|
81
|
+
<RendererWithDebugUI
|
|
82
|
+
question={applyStoryArgs(numberline, args)}
|
|
83
|
+
apiOptions={apiOptions}
|
|
84
|
+
/>
|
|
85
|
+
);
|
|
23
86
|
};
|
|
24
87
|
|
|
25
88
|
export default {
|
|
26
89
|
title: "Perseus/Widgets/Label Image",
|
|
27
90
|
args: {
|
|
28
91
|
isMobile: false,
|
|
92
|
+
preferredPopoverDirection: "NONE",
|
|
93
|
+
},
|
|
94
|
+
argTypes: {
|
|
95
|
+
preferredPopoverDirection: {
|
|
96
|
+
control: "select",
|
|
97
|
+
options: ["NONE", "UP", "DOWN", "LEFT", "RIGHT"],
|
|
98
|
+
},
|
|
29
99
|
},
|
|
30
100
|
} as ImageStory;
|