@khanacademy/perseus 17.2.0 → 17.3.1
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 +19 -0
- package/dist/es/index.css +1 -13
- package/dist/es/index.js +37 -9
- package/dist/es/index.js.map +1 -1
- package/dist/index.css +1 -13
- package/dist/index.d.ts +2 -2
- package/dist/index.js +36 -8
- package/dist/index.js.map +1 -1
- package/dist/perseus-types.d.ts +2 -8
- package/dist/question-paragraph.d.ts +1 -0
- package/dist/renderer.d.ts +1 -0
- package/package.json +2 -2
- package/src/__testdata__/graphie.testdata.ts +8 -8
- package/src/__testdata__/server-item-renderer.testdata.ts +10 -12
- package/src/__tests__/mock-asset-loading-widget.tsx +5 -8
- package/src/index.ts +2 -0
- package/src/perseus-types.ts +18 -11
- package/src/question-paragraph.tsx +6 -1
- package/src/renderer.tsx +14 -7
- package/src/styles/widgets/label-image.less +1 -18
- package/src/widgets/__stories__/label-image.stories.tsx +30 -0
- package/src/widgets/__testdata__/expression.testdata.ts +13 -15
- package/src/widgets/__testdata__/label-image.testdata.ts +128 -0
- package/src/widgets/__tests__/expression-mobile.test.tsx +29 -0
- package/src/widgets/label-image/__stories__/answer-pill.stories.tsx +3 -3
- package/src/widgets/label-image/answer-pill.tsx +1 -1
- package/src/widgets/label-image.tsx +1 -1
- package/src/widgets/passage-ref-target.tsx +5 -2
- package/tsconfig-build.tsbuildinfo +1 -1
package/dist/perseus-types.d.ts
CHANGED
|
@@ -30,14 +30,8 @@ export type PerseusImageDetail = {
|
|
|
30
30
|
width: number;
|
|
31
31
|
height: number;
|
|
32
32
|
};
|
|
33
|
-
export
|
|
34
|
-
|
|
35
|
-
chi2Table: boolean;
|
|
36
|
-
tTable: boolean;
|
|
37
|
-
calculator: boolean;
|
|
38
|
-
periodicTable: boolean;
|
|
39
|
-
periodicTableWithKey?: boolean;
|
|
40
|
-
};
|
|
33
|
+
export declare const ItemExtras: readonly ["calculator", "chi2Table", "financialCalculatorMonthlyPayment", "financialCalculatorTotalAmount", "financialCalculatorTimeToPayOff", "periodicTable", "periodicTableWithKey", "tTable", "zTable"];
|
|
34
|
+
export type PerseusAnswerArea = Record<typeof ItemExtras[number], boolean>;
|
|
41
35
|
type Widget<Type extends string, Options> = {
|
|
42
36
|
type: Type;
|
|
43
37
|
static?: boolean;
|
package/dist/renderer.d.ts
CHANGED
|
@@ -59,6 +59,7 @@ type Props = Partial<React.ContextType<typeof DependenciesContext>> & {
|
|
|
59
59
|
linterContext: LinterContextProps;
|
|
60
60
|
legacyPerseusLint?: ReadonlyArray<string>;
|
|
61
61
|
widgets: PerseusRenderer["widgets"];
|
|
62
|
+
inline?: boolean;
|
|
62
63
|
};
|
|
63
64
|
type State = {
|
|
64
65
|
translationLintErrors: ReadonlyArray<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": "17.
|
|
6
|
+
"version": "17.3.1",
|
|
7
7
|
"publishConfig": {
|
|
8
8
|
"access": "public"
|
|
9
9
|
},
|
|
@@ -24,7 +24,7 @@
|
|
|
24
24
|
"dependencies": {
|
|
25
25
|
"@khanacademy/kas": "^0.3.7",
|
|
26
26
|
"@khanacademy/kmath": "^0.1.8",
|
|
27
|
-
"@khanacademy/math-input": "^16.
|
|
27
|
+
"@khanacademy/math-input": "^16.4.0",
|
|
28
28
|
"@khanacademy/perseus-core": "1.4.1",
|
|
29
29
|
"@khanacademy/perseus-linter": "^0.3.10",
|
|
30
30
|
"@khanacademy/pure-markdown": "^0.2.13",
|
|
@@ -1,13 +1,13 @@
|
|
|
1
|
-
import
|
|
1
|
+
import {
|
|
2
|
+
ItemExtras,
|
|
3
|
+
type PerseusAnswerArea,
|
|
4
|
+
type PerseusItem,
|
|
5
|
+
} from "../perseus-types";
|
|
2
6
|
|
|
3
7
|
export const itemWithPieChart: PerseusItem = {
|
|
4
|
-
answerArea:
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
periodicTable: false,
|
|
8
|
-
tTable: false,
|
|
9
|
-
zTable: false,
|
|
10
|
-
},
|
|
8
|
+
answerArea: Object.fromEntries(
|
|
9
|
+
ItemExtras.map((extra) => [extra, false]),
|
|
10
|
+
) as PerseusAnswerArea,
|
|
11
11
|
hints: [],
|
|
12
12
|
itemDataVersion: {
|
|
13
13
|
major: 0,
|
|
@@ -1,8 +1,10 @@
|
|
|
1
|
-
import
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
1
|
+
import {
|
|
2
|
+
ItemExtras,
|
|
3
|
+
type InputNumberWidget,
|
|
4
|
+
type LabelImageWidget,
|
|
5
|
+
type PerseusItem,
|
|
6
|
+
type PerseusRenderer,
|
|
7
|
+
type PerseusAnswerArea,
|
|
6
8
|
} from "../perseus-types";
|
|
7
9
|
|
|
8
10
|
export const itemWithInput: PerseusItem = {
|
|
@@ -37,13 +39,9 @@ export const itemWithInput: PerseusItem = {
|
|
|
37
39
|
};
|
|
38
40
|
|
|
39
41
|
export const labelImageItem: PerseusItem = {
|
|
40
|
-
answerArea:
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
periodicTable: false,
|
|
44
|
-
tTable: false,
|
|
45
|
-
zTable: false,
|
|
46
|
-
},
|
|
42
|
+
answerArea: Object.fromEntries(
|
|
43
|
+
ItemExtras.map((extra) => [extra, false]),
|
|
44
|
+
) as PerseusAnswerArea,
|
|
47
45
|
_multi: null,
|
|
48
46
|
answer: null,
|
|
49
47
|
hints: [],
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import * as React from "react";
|
|
2
2
|
|
|
3
3
|
import AssetContext from "../asset-context";
|
|
4
|
+
import {ItemExtras} from "../perseus-types";
|
|
4
5
|
|
|
5
|
-
import type {PerseusItem} from "../perseus-types";
|
|
6
|
+
import type {PerseusAnswerArea, PerseusItem} from "../perseus-types";
|
|
6
7
|
import type {WidgetExports} from "../types";
|
|
7
8
|
|
|
8
9
|
export const mockedAssetItem: PerseusItem = {
|
|
@@ -20,13 +21,9 @@ export const mockedAssetItem: PerseusItem = {
|
|
|
20
21
|
},
|
|
21
22
|
},
|
|
22
23
|
},
|
|
23
|
-
answerArea:
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
periodicTable: false,
|
|
27
|
-
tTable: false,
|
|
28
|
-
zTable: false,
|
|
29
|
-
},
|
|
24
|
+
answerArea: Object.fromEntries(
|
|
25
|
+
ItemExtras.map((extra) => [extra, false]),
|
|
26
|
+
) as PerseusAnswerArea,
|
|
30
27
|
itemDataVersion: {major: 0, minor: 1},
|
|
31
28
|
hints: [],
|
|
32
29
|
_multi: null,
|
package/src/index.ts
CHANGED
|
@@ -64,6 +64,7 @@ export {default as PerseusMarkdown} from "./perseus-markdown";
|
|
|
64
64
|
export {
|
|
65
65
|
PerseusExpressionAnswerFormConsidered,
|
|
66
66
|
plotterPlotTypes,
|
|
67
|
+
ItemExtras,
|
|
67
68
|
} from "./perseus-types";
|
|
68
69
|
export {traverse} from "./traversal";
|
|
69
70
|
export {isItemRenderableByVersion} from "./renderability";
|
|
@@ -127,6 +128,7 @@ export type {
|
|
|
127
128
|
PerseusExpressionWidgetOptions,
|
|
128
129
|
PerseusPlotterWidgetOptions,
|
|
129
130
|
PerseusRenderer,
|
|
131
|
+
PerseusAnswerArea,
|
|
130
132
|
} from "./perseus-types";
|
|
131
133
|
export type {Coord} from "./interactive2/types";
|
|
132
134
|
export type {MarkerType} from "./widgets/label-image/types";
|
package/src/perseus-types.ts
CHANGED
|
@@ -62,20 +62,27 @@ export type PerseusImageDetail = {
|
|
|
62
62
|
height: number;
|
|
63
63
|
};
|
|
64
64
|
|
|
65
|
-
export
|
|
66
|
-
// The user might benefit from using a statistics Z Table like https://www.ztable.net/
|
|
67
|
-
zTable: boolean;
|
|
68
|
-
// The user might benefit from using a statistics Chi Squared Table like https://people.richland.edu/james/lecture/m170/tbl-chi.html
|
|
69
|
-
chi2Table: boolean;
|
|
70
|
-
// The user might benefit from using a statistics T Table like https://www.statisticshowto.com/tables/t-distribution-table/
|
|
71
|
-
tTable: boolean;
|
|
65
|
+
export const ItemExtras = [
|
|
72
66
|
// The user might benefit from using a Scientific Calculator. Provided on Khan Academy when true
|
|
73
|
-
calculator
|
|
67
|
+
"calculator",
|
|
68
|
+
// The user might benefit from using a statistics Chi Squared Table like https://people.richland.edu/james/lecture/m170/tbl-chi.html
|
|
69
|
+
"chi2Table",
|
|
70
|
+
// The user might benefit from a monthly payments calculator. Provided on Khan Academy when true
|
|
71
|
+
"financialCalculatorMonthlyPayment",
|
|
72
|
+
// The user might benefit from a total amount calculator. Provided on Khan Academy when true
|
|
73
|
+
"financialCalculatorTotalAmount",
|
|
74
|
+
// The user might benefit from a time to pay off calculator. Provided on Khan Academy when true
|
|
75
|
+
"financialCalculatorTimeToPayOff",
|
|
74
76
|
// The user might benefit from using a Periodic Table of Elements. Provided on Khan Academy when true
|
|
75
|
-
periodicTable
|
|
77
|
+
"periodicTable",
|
|
76
78
|
// The user might benefit from using a Periodic Table of Elements with key. Provided on Khan Academy when true
|
|
77
|
-
periodicTableWithKey
|
|
78
|
-
|
|
79
|
+
"periodicTableWithKey",
|
|
80
|
+
// The user might benefit from using a statistics T Table like https://www.statisticshowto.com/tables/t-distribution-table/
|
|
81
|
+
"tTable",
|
|
82
|
+
// The user might benefit from using a statistics Z Table like https://www.ztable.net/
|
|
83
|
+
"zTable",
|
|
84
|
+
] as const;
|
|
85
|
+
export type PerseusAnswerArea = Record<typeof ItemExtras[number], boolean>;
|
|
79
86
|
|
|
80
87
|
type Widget<Type extends string, Options> = {
|
|
81
88
|
// The "type" of widget which will define what the Options field looks like
|
|
@@ -5,6 +5,7 @@ type Props = {
|
|
|
5
5
|
translationIndex: number;
|
|
6
6
|
paragraphIndex?: number;
|
|
7
7
|
children?: React.ReactNode;
|
|
8
|
+
inline?: boolean;
|
|
8
9
|
};
|
|
9
10
|
|
|
10
11
|
class QuestionParagraph extends React.Component<Props> {
|
|
@@ -16,7 +17,11 @@ class QuestionParagraph extends React.Component<Props> {
|
|
|
16
17
|
// to attach some metadata to top-level QuestionParagraphs:
|
|
17
18
|
return (
|
|
18
19
|
<div
|
|
19
|
-
className={
|
|
20
|
+
className={
|
|
21
|
+
this.props.inline
|
|
22
|
+
? this.props.className ?? undefined
|
|
23
|
+
: className
|
|
24
|
+
}
|
|
20
25
|
data-perseus-component-index={this.props.translationIndex}
|
|
21
26
|
data-perseus-paragraph-index={this.props.paragraphIndex}
|
|
22
27
|
>
|
package/src/renderer.tsx
CHANGED
|
@@ -172,6 +172,8 @@ type Props = Partial<React.ContextType<typeof DependenciesContext>> & {
|
|
|
172
172
|
linterContext: LinterContextProps;
|
|
173
173
|
legacyPerseusLint?: ReadonlyArray<string>;
|
|
174
174
|
widgets: PerseusRenderer["widgets"];
|
|
175
|
+
// Skip adding paragraph class
|
|
176
|
+
inline?: boolean;
|
|
175
177
|
};
|
|
176
178
|
|
|
177
179
|
type State = {
|
|
@@ -1060,6 +1062,7 @@ class Renderer extends React.Component<Props, State> {
|
|
|
1060
1062
|
className={className}
|
|
1061
1063
|
translationIndex={this.translationIndex}
|
|
1062
1064
|
paragraphIndex={state.paragraphIndex}
|
|
1065
|
+
inline={this.props.inline}
|
|
1063
1066
|
>
|
|
1064
1067
|
<ErrorBoundary>{output}</ErrorBoundary>
|
|
1065
1068
|
</QuestionParagraph>
|
|
@@ -1919,13 +1922,17 @@ class Renderer extends React.Component<Props, State> {
|
|
|
1919
1922
|
this._isTwoColumn = false;
|
|
1920
1923
|
|
|
1921
1924
|
// Parse the string of markdown to a parse tree
|
|
1922
|
-
const parsedMarkdown =
|
|
1923
|
-
|
|
1924
|
-
|
|
1925
|
-
|
|
1926
|
-
|
|
1927
|
-
|
|
1928
|
-
|
|
1925
|
+
const parsedMarkdown = this.props.inline
|
|
1926
|
+
? PerseusMarkdown.parseInline(content, {
|
|
1927
|
+
// Recognize crowdin IDs while translating articles
|
|
1928
|
+
// (This should never be hit by exercises, though if you
|
|
1929
|
+
// decide you want to add a check that this is an article,
|
|
1930
|
+
// go for it.)
|
|
1931
|
+
isJipt: this.translationIndex != null,
|
|
1932
|
+
})
|
|
1933
|
+
: PerseusMarkdown.parse(content, {
|
|
1934
|
+
isJipt: this.translationIndex != null,
|
|
1935
|
+
});
|
|
1929
1936
|
|
|
1930
1937
|
// Optionally apply the linter to the parse tree
|
|
1931
1938
|
if (this.props.linterContext.highlightLint) {
|
|
@@ -5,35 +5,18 @@
|
|
|
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
8
|
}
|
|
21
9
|
|
|
22
10
|
// Reset mobile text content for answer pills.
|
|
23
11
|
@media (max-width: 767px) {
|
|
24
12
|
[id*="perseus-label-image-widget-answer-pill"] {
|
|
25
|
-
div.paragraph {
|
|
26
|
-
all: revert;
|
|
27
|
-
}
|
|
28
13
|
> div.perseus-renderer-responsive {
|
|
29
14
|
all: revert;
|
|
30
15
|
}
|
|
31
16
|
}
|
|
32
|
-
|
|
33
17
|
.framework-perseus.perseus-mobile
|
|
34
18
|
[id*="perseus-label-image-widget-answer-pill"] {
|
|
35
|
-
|
|
36
|
-
.perseus-renderer > .paragraph .paragraph {
|
|
19
|
+
mjx-container {
|
|
37
20
|
all: revert;
|
|
38
21
|
}
|
|
39
22
|
}
|
|
@@ -5,6 +5,8 @@ import {
|
|
|
5
5
|
textQuestion,
|
|
6
6
|
mathQuestion,
|
|
7
7
|
numberline,
|
|
8
|
+
longTextFromArticle,
|
|
9
|
+
mixedContentQuestion,
|
|
8
10
|
} from "../__testdata__/label-image.testdata";
|
|
9
11
|
|
|
10
12
|
import type {PerseusRenderer} from "../../perseus-types";
|
|
@@ -59,6 +61,21 @@ export const LabelWidgetWithText = (args: StoryArgs): React.ReactElement => {
|
|
|
59
61
|
);
|
|
60
62
|
};
|
|
61
63
|
|
|
64
|
+
export const LabelWidgetWithLongText = (
|
|
65
|
+
args: StoryArgs,
|
|
66
|
+
): React.ReactElement => {
|
|
67
|
+
const apiOptions: APIOptions = {
|
|
68
|
+
isMobile: args.isMobile,
|
|
69
|
+
};
|
|
70
|
+
|
|
71
|
+
return (
|
|
72
|
+
<RendererWithDebugUI
|
|
73
|
+
question={applyStoryArgs(longTextFromArticle, args)}
|
|
74
|
+
apiOptions={apiOptions}
|
|
75
|
+
/>
|
|
76
|
+
);
|
|
77
|
+
};
|
|
78
|
+
|
|
62
79
|
export const LabelWidgetWithMath = (args: StoryArgs): React.ReactElement => {
|
|
63
80
|
const apiOptions: APIOptions = {
|
|
64
81
|
isMobile: args.isMobile,
|
|
@@ -85,6 +102,19 @@ export const LabelImageNumberline = (args: StoryArgs): React.ReactElement => {
|
|
|
85
102
|
);
|
|
86
103
|
};
|
|
87
104
|
|
|
105
|
+
export const LabelImageMixedContent = (args: StoryArgs): React.ReactElement => {
|
|
106
|
+
const apiOptions: APIOptions = {
|
|
107
|
+
isMobile: args.isMobile,
|
|
108
|
+
};
|
|
109
|
+
|
|
110
|
+
return (
|
|
111
|
+
<RendererWithDebugUI
|
|
112
|
+
question={applyStoryArgs(mixedContentQuestion, args)}
|
|
113
|
+
apiOptions={apiOptions}
|
|
114
|
+
/>
|
|
115
|
+
);
|
|
116
|
+
};
|
|
117
|
+
|
|
88
118
|
export default {
|
|
89
119
|
title: "Perseus/Widgets/Label Image",
|
|
90
120
|
args: {
|
|
@@ -1,3 +1,13 @@
|
|
|
1
|
+
import {
|
|
2
|
+
ItemExtras,
|
|
3
|
+
type PerseusExpressionWidgetOptions,
|
|
4
|
+
type Version,
|
|
5
|
+
type PerseusItem,
|
|
6
|
+
type PerseusRenderer,
|
|
7
|
+
type ExpressionWidget,
|
|
8
|
+
type PerseusAnswerArea,
|
|
9
|
+
} from "../../perseus-types";
|
|
10
|
+
|
|
1
11
|
import {
|
|
2
12
|
arrayOfLength,
|
|
3
13
|
randomBoolean,
|
|
@@ -8,14 +18,6 @@ import {
|
|
|
8
18
|
randomWord,
|
|
9
19
|
} from "./randomizers";
|
|
10
20
|
|
|
11
|
-
import type {
|
|
12
|
-
PerseusExpressionWidgetOptions,
|
|
13
|
-
Version,
|
|
14
|
-
PerseusItem,
|
|
15
|
-
PerseusRenderer,
|
|
16
|
-
ExpressionWidget,
|
|
17
|
-
} from "../../perseus-types";
|
|
18
|
-
|
|
19
21
|
const createItemJson = (
|
|
20
22
|
widgetOptions: PerseusExpressionWidgetOptions,
|
|
21
23
|
version: Version,
|
|
@@ -35,13 +37,9 @@ const createItemJson = (
|
|
|
35
37
|
},
|
|
36
38
|
_multi: null,
|
|
37
39
|
answer: null,
|
|
38
|
-
answerArea:
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
tTable: false,
|
|
42
|
-
calculator: false,
|
|
43
|
-
periodicTable: false,
|
|
44
|
-
},
|
|
40
|
+
answerArea: Object.fromEntries(
|
|
41
|
+
ItemExtras.map((extra) => [extra, false]),
|
|
42
|
+
) as PerseusAnswerArea,
|
|
45
43
|
itemDataVersion: {
|
|
46
44
|
major: 0,
|
|
47
45
|
minor: 1,
|
|
@@ -178,3 +178,131 @@ export const numberline: PerseusRenderer = {
|
|
|
178
178
|
},
|
|
179
179
|
},
|
|
180
180
|
};
|
|
181
|
+
|
|
182
|
+
export const longTextFromArticle: PerseusRenderer = {
|
|
183
|
+
content: "[[☃ label-image 1]]",
|
|
184
|
+
images: {},
|
|
185
|
+
widgets: {
|
|
186
|
+
"label-image 1": {
|
|
187
|
+
type: "label-image",
|
|
188
|
+
alignment: "default",
|
|
189
|
+
static: false,
|
|
190
|
+
graded: true,
|
|
191
|
+
options: {
|
|
192
|
+
static: false,
|
|
193
|
+
choices: [
|
|
194
|
+
"long wavelength & low frequency",
|
|
195
|
+
"short wavelength & high frequency",
|
|
196
|
+
],
|
|
197
|
+
imageAlt:
|
|
198
|
+
"Section of a rainbow in the sky. From left to right, the colors appear as violet, indigo, blue, green, yellow, orange, and red.",
|
|
199
|
+
imageUrl:
|
|
200
|
+
"https://cdn.kastatic.org/ka-content-images/227d402cb09ebc1b67f197467212fa4ab3ced5b3.jpg",
|
|
201
|
+
imageWidth: 400,
|
|
202
|
+
imageHeight: 289,
|
|
203
|
+
markers: [
|
|
204
|
+
{
|
|
205
|
+
answers: ["short wavelength & high frequency"],
|
|
206
|
+
label: "Violet side of the rainbow",
|
|
207
|
+
x: 35.8,
|
|
208
|
+
y: 13,
|
|
209
|
+
},
|
|
210
|
+
{
|
|
211
|
+
answers: ["long wavelength & low frequency"],
|
|
212
|
+
label: "Red side of the rainbow",
|
|
213
|
+
x: 71.8,
|
|
214
|
+
y: 50.5,
|
|
215
|
+
},
|
|
216
|
+
],
|
|
217
|
+
multipleAnswers: false,
|
|
218
|
+
hideChoicesFromInstructions: true,
|
|
219
|
+
},
|
|
220
|
+
version: {
|
|
221
|
+
major: 0,
|
|
222
|
+
minor: 0,
|
|
223
|
+
},
|
|
224
|
+
},
|
|
225
|
+
},
|
|
226
|
+
};
|
|
227
|
+
|
|
228
|
+
export const mixedContentQuestion: PerseusRenderer = {
|
|
229
|
+
content:
|
|
230
|
+
"A beach ball floats on water. The ball is at rest.\n\n[[☃ image 1]]\n\n**Complete the free body diagram by labeling the forces acting on the ball.**\n\n[[☃ label-image 1]]",
|
|
231
|
+
images: {
|
|
232
|
+
"https://cdn.kastatic.org/ka-content-images/0fa7eefde0067d986d2e6dc377e8d2db3e1d466f.svg":
|
|
233
|
+
{
|
|
234
|
+
width: 150,
|
|
235
|
+
height: 300,
|
|
236
|
+
},
|
|
237
|
+
},
|
|
238
|
+
widgets: {
|
|
239
|
+
"image 1": {
|
|
240
|
+
type: "image",
|
|
241
|
+
alignment: "block",
|
|
242
|
+
static: false,
|
|
243
|
+
graded: true,
|
|
244
|
+
options: {
|
|
245
|
+
static: false,
|
|
246
|
+
title: "",
|
|
247
|
+
range: [
|
|
248
|
+
[0, 10],
|
|
249
|
+
[0, 10],
|
|
250
|
+
],
|
|
251
|
+
box: [350, 219],
|
|
252
|
+
backgroundImage: {
|
|
253
|
+
url: "https://cdn.kastatic.org/ka-content-images/581c7d3928ba5f81e9dc5720291ec895764cc7e8.png",
|
|
254
|
+
width: 350,
|
|
255
|
+
height: 219,
|
|
256
|
+
},
|
|
257
|
+
labels: [],
|
|
258
|
+
alt: "An inflated beach ball floats on the surface of water. Only a small portion of the ball is underwater.",
|
|
259
|
+
caption: "",
|
|
260
|
+
},
|
|
261
|
+
version: {
|
|
262
|
+
major: 0,
|
|
263
|
+
minor: 0,
|
|
264
|
+
},
|
|
265
|
+
},
|
|
266
|
+
"label-image 1": {
|
|
267
|
+
type: "label-image",
|
|
268
|
+
alignment: "default",
|
|
269
|
+
static: false,
|
|
270
|
+
graded: true,
|
|
271
|
+
options: {
|
|
272
|
+
static: false,
|
|
273
|
+
choices: [
|
|
274
|
+
"lift $(F_\\text{L})$",
|
|
275
|
+
"buoyant force $(F_\\text{B})$",
|
|
276
|
+
"gravity $(F_\\text{g})$",
|
|
277
|
+
"normal force $(F_\\text{N})$",
|
|
278
|
+
],
|
|
279
|
+
imageAlt:
|
|
280
|
+
"A model shows a square with two arrows pointing out of it. One arrow points up and another arrow points down.",
|
|
281
|
+
imageUrl:
|
|
282
|
+
"https://cdn.kastatic.org/ka-content-images/b24e40b5a36890130acfb7bd237c4bf0d85c7b44.svg",
|
|
283
|
+
imageWidth: 150,
|
|
284
|
+
imageHeight: 300,
|
|
285
|
+
markers: [
|
|
286
|
+
{
|
|
287
|
+
answers: ["buoyant force $(F_\\text{B})$"],
|
|
288
|
+
label: "An arrow that points upward from the square",
|
|
289
|
+
x: 64.2,
|
|
290
|
+
y: 17.6,
|
|
291
|
+
},
|
|
292
|
+
{
|
|
293
|
+
answers: ["gravity $(F_\\text{g})$"],
|
|
294
|
+
label: "An arrow that points downward from the square",
|
|
295
|
+
x: 66.2,
|
|
296
|
+
y: 81.8,
|
|
297
|
+
},
|
|
298
|
+
],
|
|
299
|
+
multipleAnswers: false,
|
|
300
|
+
hideChoicesFromInstructions: true,
|
|
301
|
+
},
|
|
302
|
+
version: {
|
|
303
|
+
major: 0,
|
|
304
|
+
minor: 0,
|
|
305
|
+
},
|
|
306
|
+
},
|
|
307
|
+
},
|
|
308
|
+
};
|
|
@@ -121,6 +121,35 @@ describe("expression mobile", () => {
|
|
|
121
121
|
);
|
|
122
122
|
});
|
|
123
123
|
|
|
124
|
+
it("shows keypad after focused input interaction", async () => {
|
|
125
|
+
render(<ConnectedRenderer />);
|
|
126
|
+
|
|
127
|
+
const input = screen.getByLabelText(
|
|
128
|
+
"Math input box Tap with one or two fingers to open keyboard",
|
|
129
|
+
);
|
|
130
|
+
|
|
131
|
+
fireEvent.touchStart(input);
|
|
132
|
+
|
|
133
|
+
// waiting because `visibility` is animated
|
|
134
|
+
await waitFor(() =>
|
|
135
|
+
expect(screen.getByRole("button", {name: "1"})).toBeVisible(),
|
|
136
|
+
);
|
|
137
|
+
|
|
138
|
+
userEvent.click(screen.getByRole("tab", {name: "Dismiss"}));
|
|
139
|
+
|
|
140
|
+
// wait for the keypad to close
|
|
141
|
+
await waitFor(() =>
|
|
142
|
+
expect(screen.queryByRole("button", {name: "1"})).toBeNull(),
|
|
143
|
+
);
|
|
144
|
+
|
|
145
|
+
fireEvent.touchStart(input);
|
|
146
|
+
|
|
147
|
+
// confirm that the keypad has reopened
|
|
148
|
+
await waitFor(() =>
|
|
149
|
+
expect(screen.getByRole("button", {name: "1"})).toBeVisible(),
|
|
150
|
+
);
|
|
151
|
+
});
|
|
152
|
+
|
|
124
153
|
it("is possible to use the keypad", async () => {
|
|
125
154
|
render(<ConnectedRenderer />);
|
|
126
155
|
|
|
@@ -22,7 +22,7 @@ export default story;
|
|
|
22
22
|
export const SingleAnswer = {
|
|
23
23
|
args: {
|
|
24
24
|
id: "1",
|
|
25
|
-
selectedAnswers: ["Answer Pill
|
|
25
|
+
selectedAnswers: ["Answer Pill"],
|
|
26
26
|
markerRef: null,
|
|
27
27
|
side: "top",
|
|
28
28
|
onClick: () => {},
|
|
@@ -42,7 +42,7 @@ export const MultipleAnswers = {
|
|
|
42
42
|
export const Correct = {
|
|
43
43
|
args: {
|
|
44
44
|
id: "1",
|
|
45
|
-
selectedAnswers: ["Right Answer
|
|
45
|
+
selectedAnswers: ["Right Answer"],
|
|
46
46
|
showCorrectness: "correct",
|
|
47
47
|
markerRef: null,
|
|
48
48
|
side: "top",
|
|
@@ -53,7 +53,7 @@ export const Correct = {
|
|
|
53
53
|
export const Incorrect = {
|
|
54
54
|
args: {
|
|
55
55
|
id: "1",
|
|
56
|
-
selectedAnswers: ["Wrong Answer
|
|
56
|
+
selectedAnswers: ["Wrong Answer"],
|
|
57
57
|
showCorrectness: "incorrect",
|
|
58
58
|
markerRef: null,
|
|
59
59
|
side: "top",
|
|
@@ -667,7 +667,7 @@ export class LabelImage extends React.Component<
|
|
|
667
667
|
[`margin${
|
|
668
668
|
markerPosition.charAt(0).toUpperCase() +
|
|
669
669
|
markerPosition.slice(1)
|
|
670
|
-
}`]:
|
|
670
|
+
}`]: 15, // move pill further from marker
|
|
671
671
|
};
|
|
672
672
|
|
|
673
673
|
const showAnswerChoice =
|
|
@@ -50,8 +50,11 @@ class PassageRefTarget extends React.Component<any> {
|
|
|
50
50
|
return (
|
|
51
51
|
<Renderer
|
|
52
52
|
content={this.props.content}
|
|
53
|
-
//
|
|
54
|
-
|
|
53
|
+
// This was already here before inline was recently added (#873)
|
|
54
|
+
// It was for a different use case a long time ago:
|
|
55
|
+
// https://phabricator.khanacademy.org/D12113
|
|
56
|
+
// Commenting out to prevent unanticipated side effects
|
|
57
|
+
// inline={true}
|
|
55
58
|
apiOptions={this.props.apiOptions}
|
|
56
59
|
linterContext={this.props.linterContext}
|
|
57
60
|
/>
|