@khanacademy/perseus 12.4.0 → 13.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 +30 -0
- package/dist/es/index.js +554 -210
- package/dist/es/index.js.map +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.js +9661 -9438
- package/dist/index.js.map +1 -1
- package/dist/item-renderer.d.ts +3 -1
- package/dist/perseus-types.d.ts +4 -2
- package/dist/widgets/label-image/strings.d.ts +3 -0
- package/dist/widgets/plotter.d.ts +8 -22
- package/package.json +4 -2
- package/src/__tests__/item-renderer.test.tsx +41 -0
- package/src/index.ts +5 -1
- package/src/item-renderer.tsx +4 -2
- package/src/perseus-types.ts +11 -2
- package/src/widgets/__stories__/video.stories.tsx +9 -1
- package/src/widgets/__testdata__/video.testdata.ts +40 -0
- package/src/widgets/__tests__/plotter.test.tsx +11 -8
- package/src/widgets/__tests__/video.test.ts +17 -1
- package/src/widgets/label-image/strings.ts +3 -0
- package/src/widgets/plotter.tsx +29 -50
- package/src/widgets/video.tsx +11 -0
- package/tsconfig-build.tsbuildinfo +1 -1
package/dist/item-renderer.d.ts
CHANGED
|
@@ -16,7 +16,9 @@ KeypadProps & {
|
|
|
16
16
|
item: PerseusItem | any;
|
|
17
17
|
onShowCalculator?: () => unknown;
|
|
18
18
|
onShowChi2Table?: () => unknown;
|
|
19
|
-
onShowPeriodicTable?: (
|
|
19
|
+
onShowPeriodicTable?: (options?: {
|
|
20
|
+
showKey: boolean;
|
|
21
|
+
}) => unknown;
|
|
20
22
|
onShowTTable?: () => unknown;
|
|
21
23
|
onShowZTable?: () => unknown;
|
|
22
24
|
problemNum: number;
|
package/dist/perseus-types.d.ts
CHANGED
|
@@ -413,17 +413,19 @@ export type PerseusPassageRefWidgetOptions = {
|
|
|
413
413
|
referenceNumber: number;
|
|
414
414
|
summaryText: string;
|
|
415
415
|
};
|
|
416
|
+
export declare const plotterPlotTypes: readonly ["bar", "line", "pic", "histogram", "dotplot"];
|
|
417
|
+
export type PlotType = typeof plotterPlotTypes[number];
|
|
416
418
|
export type PerseusPlotterWidgetOptions = {
|
|
417
419
|
labels: ReadonlyArray<string>;
|
|
418
420
|
categories: ReadonlyArray<string>;
|
|
419
|
-
type:
|
|
421
|
+
type: PlotType;
|
|
420
422
|
maxY: number;
|
|
421
423
|
scaleY: number;
|
|
422
424
|
labelInterval: number | null | undefined;
|
|
423
425
|
snapsPerLine: number;
|
|
424
426
|
starting: ReadonlyArray<number>;
|
|
425
427
|
correct: ReadonlyArray<number>;
|
|
426
|
-
picUrl:
|
|
428
|
+
picUrl: string | null | undefined;
|
|
427
429
|
picSize: number | null | undefined;
|
|
428
430
|
picBoxHeight: number | null | undefined;
|
|
429
431
|
plotDimensions: ReadonlyArray<number>;
|
|
@@ -1,25 +1,11 @@
|
|
|
1
1
|
import * as React from "react";
|
|
2
|
-
import type {
|
|
3
|
-
|
|
4
|
-
type
|
|
5
|
-
type
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
scaleY: number;
|
|
10
|
-
maxY: number;
|
|
11
|
-
snapsPerLine: number;
|
|
12
|
-
picSize: number;
|
|
13
|
-
picBoxHeight: number;
|
|
14
|
-
picUrl: string;
|
|
15
|
-
plotDimensions: ReadonlyArray<number>;
|
|
16
|
-
labelInterval: number;
|
|
17
|
-
starting: Array<number>;
|
|
18
|
-
static: boolean;
|
|
19
|
-
markings: any;
|
|
20
|
-
onChange: any;
|
|
21
|
-
trackInteraction: () => void;
|
|
22
|
-
apiOptions: APIOptions;
|
|
2
|
+
import type { PerseusPlotterWidgetOptions } from "../perseus-types";
|
|
3
|
+
import type { WidgetProps } from "../types";
|
|
4
|
+
type Rubric = PerseusPlotterWidgetOptions;
|
|
5
|
+
type RenderProps = PerseusPlotterWidgetOptions;
|
|
6
|
+
type Props = WidgetProps<RenderProps, Rubric> & {
|
|
7
|
+
labelInterval: NonNullable<PerseusPlotterWidgetOptions["labelInterval"]>;
|
|
8
|
+
picSize: NonNullable<PerseusPlotterWidgetOptions["picSize"]>;
|
|
23
9
|
};
|
|
24
10
|
type DefaultProps = {
|
|
25
11
|
type: Props["type"];
|
|
@@ -35,7 +21,7 @@ type DefaultProps = {
|
|
|
35
21
|
labelInterval: Props["labelInterval"];
|
|
36
22
|
};
|
|
37
23
|
type State = {
|
|
38
|
-
values:
|
|
24
|
+
values: ReadonlyArray<number>;
|
|
39
25
|
categoryHeights: Record<string, number>;
|
|
40
26
|
};
|
|
41
27
|
export declare class Plotter extends React.Component<Props, State> {
|
package/package.json
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
"description": "Core Perseus API (includes renderers and widgets)",
|
|
4
4
|
"author": "Khan Academy",
|
|
5
5
|
"license": "MIT",
|
|
6
|
-
"version": "
|
|
6
|
+
"version": "13.1.0",
|
|
7
7
|
"publishConfig": {
|
|
8
8
|
"access": "public"
|
|
9
9
|
},
|
|
@@ -24,7 +24,7 @@
|
|
|
24
24
|
"dependencies": {
|
|
25
25
|
"@khanacademy/kas": "^0.3.5",
|
|
26
26
|
"@khanacademy/kmath": "^0.1.6",
|
|
27
|
-
"@khanacademy/math-input": "^
|
|
27
|
+
"@khanacademy/math-input": "^15.0.1",
|
|
28
28
|
"@khanacademy/perseus-core": "1.3.0",
|
|
29
29
|
"@khanacademy/perseus-linter": "^0.3.8",
|
|
30
30
|
"@khanacademy/pure-markdown": "^0.2.10",
|
|
@@ -48,6 +48,7 @@
|
|
|
48
48
|
"@khanacademy/wonder-blocks-tooltip": "^2.1.2",
|
|
49
49
|
"@khanacademy/wonder-blocks-typography": "^2.1.3",
|
|
50
50
|
"@khanacademy/wonder-stuff-core": "^1.5.1",
|
|
51
|
+
"@phosphor-icons/core": "^2.0.2",
|
|
51
52
|
"aphrodite": "^1.2.5",
|
|
52
53
|
"classnames": "^1.1.4",
|
|
53
54
|
"create-react-class": "^15.6.3",
|
|
@@ -82,6 +83,7 @@
|
|
|
82
83
|
"@khanacademy/wonder-blocks-tooltip": "^2.1.2",
|
|
83
84
|
"@khanacademy/wonder-blocks-typography": "^2.1.3",
|
|
84
85
|
"@khanacademy/wonder-stuff-core": "^1.5.1",
|
|
86
|
+
"@phosphor-icons/core": "^2.0.2",
|
|
85
87
|
"aphrodite": "^1.2.5",
|
|
86
88
|
"classnames": "^1.1.4",
|
|
87
89
|
"create-react-class": "^15.6.3",
|
|
@@ -805,6 +805,47 @@ describe("item renderer", () => {
|
|
|
805
805
|
expect(onShowTTable).toHaveBeenCalled();
|
|
806
806
|
expect(onShowChi2Table).toHaveBeenCalled();
|
|
807
807
|
});
|
|
808
|
+
|
|
809
|
+
it("should call onShowPeriodicTable with showKey option if selected", () => {
|
|
810
|
+
// Arrange
|
|
811
|
+
const item = {
|
|
812
|
+
...itemWithInput,
|
|
813
|
+
answerArea: {
|
|
814
|
+
zTable: false,
|
|
815
|
+
chi2Table: false,
|
|
816
|
+
tTable: false,
|
|
817
|
+
calculator: false,
|
|
818
|
+
periodicTable: true,
|
|
819
|
+
periodicTableWithKey: true,
|
|
820
|
+
},
|
|
821
|
+
} as const;
|
|
822
|
+
|
|
823
|
+
const onShowCalculator = jest.fn();
|
|
824
|
+
const onShowPeriodicTable = jest.fn();
|
|
825
|
+
const onShowZTable = jest.fn();
|
|
826
|
+
const onShowTTable = jest.fn();
|
|
827
|
+
const onShowChi2Table = jest.fn();
|
|
828
|
+
const localExtraProps = {
|
|
829
|
+
...extraProps,
|
|
830
|
+
onShowCalculator,
|
|
831
|
+
onShowPeriodicTable,
|
|
832
|
+
onShowZTable,
|
|
833
|
+
onShowTTable,
|
|
834
|
+
onShowChi2Table,
|
|
835
|
+
} as const;
|
|
836
|
+
|
|
837
|
+
// Act
|
|
838
|
+
renderQuestion(item, undefined, localExtraProps);
|
|
839
|
+
|
|
840
|
+
// Assert
|
|
841
|
+
expect(onShowCalculator).not.toHaveBeenCalled();
|
|
842
|
+
expect(onShowZTable).not.toHaveBeenCalled();
|
|
843
|
+
expect(onShowTTable).not.toHaveBeenCalled();
|
|
844
|
+
expect(onShowChi2Table).not.toHaveBeenCalled();
|
|
845
|
+
expect(onShowPeriodicTable).toHaveBeenCalledWith(
|
|
846
|
+
expect.objectContaining({showKey: true}),
|
|
847
|
+
);
|
|
848
|
+
});
|
|
808
849
|
});
|
|
809
850
|
|
|
810
851
|
describe("controlPeripherals is enabled", () => {
|
package/src/index.ts
CHANGED
|
@@ -62,7 +62,10 @@ export {default as KhanMath} from "./util/math";
|
|
|
62
62
|
export {default as LoadingContext} from "./loading-context";
|
|
63
63
|
export {default as mediaQueries} from "./styles/media-queries";
|
|
64
64
|
export {default as PerseusMarkdown} from "./perseus-markdown";
|
|
65
|
-
export {
|
|
65
|
+
export {
|
|
66
|
+
PerseusExpressionAnswerFormConsidered,
|
|
67
|
+
plotterPlotTypes,
|
|
68
|
+
} from "./perseus-types";
|
|
66
69
|
export {traverse} from "./traversal";
|
|
67
70
|
export {isItemRenderableByVersion} from "./renderability";
|
|
68
71
|
export {violatingWidgets} from "./a11y";
|
|
@@ -123,6 +126,7 @@ export type {
|
|
|
123
126
|
PerseusInteractiveGraphWidgetOptions,
|
|
124
127
|
PerseusRadioWidgetOptions,
|
|
125
128
|
PerseusExpressionWidgetOptions,
|
|
129
|
+
PerseusPlotterWidgetOptions,
|
|
126
130
|
PerseusRenderer,
|
|
127
131
|
} from "./perseus-types";
|
|
128
132
|
export type {Coord} from "./interactive2/types";
|
package/src/item-renderer.tsx
CHANGED
|
@@ -39,7 +39,7 @@ type Props = // These props are used by the ProvideKeypad mixin.
|
|
|
39
39
|
item: PerseusItem | any /* any for _multi items */;
|
|
40
40
|
onShowCalculator?: () => unknown;
|
|
41
41
|
onShowChi2Table?: () => unknown;
|
|
42
|
-
onShowPeriodicTable?: () => unknown;
|
|
42
|
+
onShowPeriodicTable?: (options?: {showKey: boolean}) => unknown;
|
|
43
43
|
onShowTTable?: () => unknown;
|
|
44
44
|
onShowZTable?: () => unknown;
|
|
45
45
|
problemNum: number;
|
|
@@ -254,7 +254,9 @@ class ItemRenderer extends React.Component<Props, State> {
|
|
|
254
254
|
}
|
|
255
255
|
if (answerArea.periodicTable) {
|
|
256
256
|
this.props.onShowPeriodicTable &&
|
|
257
|
-
this.props.onShowPeriodicTable(
|
|
257
|
+
this.props.onShowPeriodicTable({
|
|
258
|
+
showKey: answerArea.periodicTableWithKey,
|
|
259
|
+
});
|
|
258
260
|
}
|
|
259
261
|
if (answerArea.zTable) {
|
|
260
262
|
this.props.onShowZTable && this.props.onShowZTable();
|
package/src/perseus-types.ts
CHANGED
|
@@ -848,13 +848,22 @@ export type PerseusPassageRefWidgetOptions = {
|
|
|
848
848
|
summaryText: string;
|
|
849
849
|
};
|
|
850
850
|
|
|
851
|
+
export const plotterPlotTypes = [
|
|
852
|
+
"bar",
|
|
853
|
+
"line",
|
|
854
|
+
"pic",
|
|
855
|
+
"histogram",
|
|
856
|
+
"dotplot",
|
|
857
|
+
] as const;
|
|
858
|
+
export type PlotType = typeof plotterPlotTypes[number];
|
|
859
|
+
|
|
851
860
|
export type PerseusPlotterWidgetOptions = {
|
|
852
861
|
// Translatable Text; The Axis labels. e.g. ["X Label", "Y Label"]
|
|
853
862
|
labels: ReadonlyArray<string>;
|
|
854
863
|
// Translatable Text; Categories to display along the X access. e.g. [">0", ">6", ">12", ">18"]
|
|
855
864
|
categories: ReadonlyArray<string>;
|
|
856
865
|
// The type of the graph. options "bar", "line", "pic", "histogram", "dotplot"
|
|
857
|
-
type:
|
|
866
|
+
type: PlotType;
|
|
858
867
|
// The maximimum Y tick to display in the graph
|
|
859
868
|
maxY: number;
|
|
860
869
|
// The scale of the Y Axis
|
|
@@ -868,7 +877,7 @@ export type PerseusPlotterWidgetOptions = {
|
|
|
868
877
|
// The Y values that represent the correct answer expected
|
|
869
878
|
correct: ReadonlyArray<number>;
|
|
870
879
|
// A picture to represent items in a graph.
|
|
871
|
-
picUrl:
|
|
880
|
+
picUrl: string | null | undefined;
|
|
872
881
|
// deprecated
|
|
873
882
|
picSize: number | null | undefined;
|
|
874
883
|
// deprecated
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import * as React from "react";
|
|
2
2
|
|
|
3
3
|
import {RendererWithDebugUI} from "../../../../../testing/renderer-with-debug-ui";
|
|
4
|
-
import {question1} from "../__testdata__/video.testdata";
|
|
4
|
+
import {question1, question2, question3} from "../__testdata__/video.testdata";
|
|
5
5
|
|
|
6
6
|
export default {
|
|
7
7
|
title: "Perseus/Widgets/Video",
|
|
@@ -12,3 +12,11 @@ type StoryArgs = Record<any, any>;
|
|
|
12
12
|
export const Question1 = (args: StoryArgs): React.ReactElement => {
|
|
13
13
|
return <RendererWithDebugUI question={question1} />;
|
|
14
14
|
};
|
|
15
|
+
|
|
16
|
+
export const Question2 = (args: StoryArgs): React.ReactElement => {
|
|
17
|
+
return <RendererWithDebugUI question={question2} />;
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
export const Question3 = (args: StoryArgs): React.ReactElement => {
|
|
21
|
+
return <RendererWithDebugUI question={question3} />;
|
|
22
|
+
};
|
|
@@ -19,3 +19,43 @@ export const question1: PerseusRenderer = {
|
|
|
19
19
|
},
|
|
20
20
|
replace: false,
|
|
21
21
|
};
|
|
22
|
+
|
|
23
|
+
export const question2: PerseusRenderer = {
|
|
24
|
+
content:
|
|
25
|
+
"Watch the WMF at Angkor Wat video to find the answer.\n\n[[\u2603 video 1]]\n\n",
|
|
26
|
+
images: {},
|
|
27
|
+
widgets: {
|
|
28
|
+
"video 1": {
|
|
29
|
+
graded: true,
|
|
30
|
+
version: {major: 0, minor: 0},
|
|
31
|
+
static: false,
|
|
32
|
+
type: "video",
|
|
33
|
+
options: {
|
|
34
|
+
static: false,
|
|
35
|
+
location: "https://player.vimeo.com/video/4754041",
|
|
36
|
+
},
|
|
37
|
+
alignment: "block",
|
|
38
|
+
},
|
|
39
|
+
},
|
|
40
|
+
replace: false,
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
export const question3: PerseusRenderer = {
|
|
44
|
+
content:
|
|
45
|
+
"Watch the WMF at Angkor Wat video to find the answer.\n\n[[\u2603 video 1]]\n\n",
|
|
46
|
+
images: {},
|
|
47
|
+
widgets: {
|
|
48
|
+
"video 1": {
|
|
49
|
+
graded: true,
|
|
50
|
+
version: {major: 0, minor: 0},
|
|
51
|
+
static: false,
|
|
52
|
+
type: "video",
|
|
53
|
+
options: {
|
|
54
|
+
static: false,
|
|
55
|
+
location: "https://player.vimeo.com/video/4754041?h=64fbc32a6e",
|
|
56
|
+
},
|
|
57
|
+
alignment: "block",
|
|
58
|
+
},
|
|
59
|
+
},
|
|
60
|
+
replace: false,
|
|
61
|
+
};
|
|
@@ -4,13 +4,12 @@ import React from "react";
|
|
|
4
4
|
|
|
5
5
|
import {testDependencies} from "../../../../../testing/test-dependencies";
|
|
6
6
|
import {setDependencies} from "../../dependencies";
|
|
7
|
+
import {ApiOptions} from "../../perseus-api";
|
|
7
8
|
import {question1} from "../__testdata__/plotter.testdata";
|
|
8
9
|
import {Plotter} from "../plotter";
|
|
9
10
|
|
|
10
11
|
import {renderQuestion} from "./renderQuestion";
|
|
11
12
|
|
|
12
|
-
import type {APIOptions} from "../../types";
|
|
13
|
-
|
|
14
13
|
describe("plotter widget", () => {
|
|
15
14
|
beforeEach(() => {
|
|
16
15
|
setDependencies(testDependencies);
|
|
@@ -26,15 +25,17 @@ describe("plotter widget", () => {
|
|
|
26
25
|
|
|
27
26
|
it("should show drag text when not static", () => {
|
|
28
27
|
// Arrange and Act
|
|
29
|
-
const apiOptions: APIOptions = {isMobile: true};
|
|
30
28
|
render(
|
|
29
|
+
// @ts-expect-error - TS2769 - test works, but I can't figure out how to make the types happy
|
|
31
30
|
<Plotter
|
|
32
31
|
static={false}
|
|
33
32
|
trackInteraction={() => {}}
|
|
34
33
|
onChange={() => {}}
|
|
35
|
-
apiOptions={
|
|
34
|
+
apiOptions={{
|
|
35
|
+
...ApiOptions.defaults,
|
|
36
|
+
isMobile: true,
|
|
37
|
+
}}
|
|
36
38
|
starting={[0]}
|
|
37
|
-
markings={""}
|
|
38
39
|
/>,
|
|
39
40
|
);
|
|
40
41
|
|
|
@@ -46,15 +47,17 @@ describe("plotter widget", () => {
|
|
|
46
47
|
|
|
47
48
|
it("should not show drag text when static", () => {
|
|
48
49
|
// Arrange and Act
|
|
49
|
-
const apiOptions: APIOptions = {isMobile: true};
|
|
50
50
|
render(
|
|
51
|
+
// @ts-expect-error - TS2769 - test works, but I can't figure out how to make the types happy
|
|
51
52
|
<Plotter
|
|
52
53
|
static={true}
|
|
53
54
|
trackInteraction={() => {}}
|
|
54
55
|
onChange={() => {}}
|
|
55
|
-
apiOptions={
|
|
56
|
+
apiOptions={{
|
|
57
|
+
...ApiOptions.defaults,
|
|
58
|
+
isMobile: true,
|
|
59
|
+
}}
|
|
56
60
|
starting={[0]}
|
|
57
|
-
markings={""}
|
|
58
61
|
/>,
|
|
59
62
|
);
|
|
60
63
|
|
|
@@ -2,7 +2,7 @@ import "@testing-library/jest-dom";
|
|
|
2
2
|
|
|
3
3
|
import {testDependencies} from "../../../../../testing/test-dependencies";
|
|
4
4
|
import * as Dependencies from "../../dependencies";
|
|
5
|
-
import {question1} from "../__testdata__/video.testdata";
|
|
5
|
+
import {question1, question2} from "../__testdata__/video.testdata";
|
|
6
6
|
|
|
7
7
|
import {renderQuestion} from "./renderQuestion";
|
|
8
8
|
|
|
@@ -50,4 +50,20 @@ describe("video widget", () => {
|
|
|
50
50
|
// Assert
|
|
51
51
|
expect(container).toMatchSnapshot("first mobile render");
|
|
52
52
|
});
|
|
53
|
+
|
|
54
|
+
it("vimeo widget should contain dnt param", () => {
|
|
55
|
+
// Arrange
|
|
56
|
+
const apiOptions: APIOptions = {
|
|
57
|
+
isMobile: false,
|
|
58
|
+
};
|
|
59
|
+
|
|
60
|
+
// Act
|
|
61
|
+
renderQuestion(question2, apiOptions);
|
|
62
|
+
|
|
63
|
+
// Assert
|
|
64
|
+
// eslint-disable-next-line testing-library/no-node-access
|
|
65
|
+
expect(document.getElementsByTagName("iframe")[0].src).toContain(
|
|
66
|
+
"dnt=1",
|
|
67
|
+
);
|
|
68
|
+
});
|
|
53
69
|
});
|
package/src/widgets/plotter.tsx
CHANGED
|
@@ -13,38 +13,17 @@ import KhanColors from "../util/colors";
|
|
|
13
13
|
import GraphUtils from "../util/graph-utils";
|
|
14
14
|
import KhanMath from "../util/math";
|
|
15
15
|
|
|
16
|
-
import type {
|
|
16
|
+
import type {PerseusPlotterWidgetOptions} from "../perseus-types";
|
|
17
|
+
import type {WidgetExports, WidgetProps} from "../types";
|
|
17
18
|
|
|
18
19
|
const {deepEq} = Util;
|
|
19
20
|
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
const plotTypes = [BAR, LINE, PIC, HISTOGRAM, DOTPLOT];
|
|
27
|
-
type PlotType = typeof plotTypes[number];
|
|
28
|
-
|
|
29
|
-
type Props = {
|
|
30
|
-
type: PlotType;
|
|
31
|
-
labels: ReadonlyArray<string>;
|
|
32
|
-
categories: ReadonlyArray<string | number>;
|
|
33
|
-
scaleY: number;
|
|
34
|
-
maxY: number;
|
|
35
|
-
snapsPerLine: number;
|
|
36
|
-
picSize: number;
|
|
37
|
-
picBoxHeight: number;
|
|
38
|
-
picUrl: string;
|
|
39
|
-
plotDimensions: ReadonlyArray<number>;
|
|
40
|
-
labelInterval: number;
|
|
41
|
-
|
|
42
|
-
starting: Array<number>;
|
|
43
|
-
static: boolean;
|
|
44
|
-
markings: any;
|
|
45
|
-
onChange: any;
|
|
46
|
-
trackInteraction: () => void;
|
|
47
|
-
apiOptions: APIOptions;
|
|
21
|
+
type Rubric = PerseusPlotterWidgetOptions;
|
|
22
|
+
type RenderProps = PerseusPlotterWidgetOptions;
|
|
23
|
+
|
|
24
|
+
type Props = WidgetProps<RenderProps, Rubric> & {
|
|
25
|
+
labelInterval: NonNullable<PerseusPlotterWidgetOptions["labelInterval"]>;
|
|
26
|
+
picSize: NonNullable<PerseusPlotterWidgetOptions["picSize"]>;
|
|
48
27
|
};
|
|
49
28
|
|
|
50
29
|
type DefaultProps = {
|
|
@@ -62,7 +41,7 @@ type DefaultProps = {
|
|
|
62
41
|
};
|
|
63
42
|
|
|
64
43
|
type State = {
|
|
65
|
-
values:
|
|
44
|
+
values: ReadonlyArray<number>;
|
|
66
45
|
categoryHeights: Record<string, number>;
|
|
67
46
|
};
|
|
68
47
|
|
|
@@ -75,7 +54,7 @@ export class Plotter extends React.Component<Props, State> {
|
|
|
75
54
|
graphie: any;
|
|
76
55
|
|
|
77
56
|
static defaultProps: DefaultProps = {
|
|
78
|
-
type:
|
|
57
|
+
type: "bar",
|
|
79
58
|
labels: ["", ""],
|
|
80
59
|
categories: [""],
|
|
81
60
|
|
|
@@ -175,11 +154,11 @@ export class Plotter extends React.Component<Props, State> {
|
|
|
175
154
|
self.graphie.pics = [];
|
|
176
155
|
self.graphie.dotTicks = [];
|
|
177
156
|
|
|
178
|
-
const isBar = self.props.type ===
|
|
179
|
-
const isLine = self.props.type ===
|
|
180
|
-
const isPic = self.props.type ===
|
|
181
|
-
const isHistogram = self.props.type ===
|
|
182
|
-
const isDotplot = self.props.type ===
|
|
157
|
+
const isBar = self.props.type === "bar";
|
|
158
|
+
const isLine = self.props.type === "line";
|
|
159
|
+
const isPic = self.props.type === "pic";
|
|
160
|
+
const isHistogram = self.props.type === "histogram";
|
|
161
|
+
const isDotplot = self.props.type === "dotplot";
|
|
183
162
|
|
|
184
163
|
const isTiledPlot = isPic || isDotplot;
|
|
185
164
|
|
|
@@ -462,7 +441,7 @@ export class Plotter extends React.Component<Props, State> {
|
|
|
462
441
|
};
|
|
463
442
|
|
|
464
443
|
showHairlines: (arg1: any) => void = (point) => {
|
|
465
|
-
if (this.props.apiOptions.isMobile
|
|
444
|
+
if (this.props.apiOptions.isMobile) {
|
|
466
445
|
// Hairlines are already initialized when the graph is loaded, so
|
|
467
446
|
// here we just move them to the updated location and make them
|
|
468
447
|
// visible.
|
|
@@ -546,7 +525,7 @@ export class Plotter extends React.Component<Props, State> {
|
|
|
546
525
|
// The deferred measurements returned from `labelCategory`.
|
|
547
526
|
const categoryHeightPromises = [];
|
|
548
527
|
|
|
549
|
-
if (self.props.type ===
|
|
528
|
+
if (self.props.type === "histogram") {
|
|
550
529
|
// Histograms with n labels/categories have n - 1 buckets
|
|
551
530
|
_.times(self.props.categories.length - 1, function (i) {
|
|
552
531
|
self.setupBar({
|
|
@@ -580,29 +559,29 @@ export class Plotter extends React.Component<Props, State> {
|
|
|
580
559
|
const startHeight = self.state.values[i];
|
|
581
560
|
let x;
|
|
582
561
|
|
|
583
|
-
if (self.props.type ===
|
|
562
|
+
if (self.props.type === "bar") {
|
|
584
563
|
x = self.setupBar({
|
|
585
564
|
index: i,
|
|
586
565
|
startHeight: startHeight,
|
|
587
566
|
config: config,
|
|
588
567
|
isHistogram: false,
|
|
589
568
|
});
|
|
590
|
-
} else if (self.props.type ===
|
|
569
|
+
} else if (self.props.type === "line") {
|
|
591
570
|
x = self.setupLine(i, startHeight, config);
|
|
592
|
-
} else if (self.props.type ===
|
|
571
|
+
} else if (self.props.type === "pic") {
|
|
593
572
|
x = self.setupPic(i, config);
|
|
594
|
-
} else if (self.props.type ===
|
|
573
|
+
} else if (self.props.type === "dotplot") {
|
|
595
574
|
x = self.setupDotplot(i, config);
|
|
596
575
|
}
|
|
597
576
|
|
|
598
577
|
let tickStart = 0;
|
|
599
578
|
let tickEnd = -6 / c.scale[1];
|
|
600
579
|
|
|
601
|
-
if (self.props.type ===
|
|
580
|
+
if (self.props.type === "dotplot" && !isMobile) {
|
|
602
581
|
tickStart = -tickEnd;
|
|
603
582
|
}
|
|
604
583
|
|
|
605
|
-
if (self.props.type ===
|
|
584
|
+
if (self.props.type === "dotplot") {
|
|
606
585
|
// Dotplot lets you specify to only show labels every 'n'
|
|
607
586
|
// ticks. It also looks nicer if it makes the labelled
|
|
608
587
|
// ticks a bit bigger.
|
|
@@ -804,7 +783,7 @@ export class Plotter extends React.Component<Props, State> {
|
|
|
804
783
|
onMove: function () {
|
|
805
784
|
const y = config.graph.lines[i].coord()[1];
|
|
806
785
|
|
|
807
|
-
const values =
|
|
786
|
+
const values = [...self.state.values];
|
|
808
787
|
values[i] = y;
|
|
809
788
|
self.setState({values: values});
|
|
810
789
|
self.changeAndTrack({values: values});
|
|
@@ -851,7 +830,7 @@ export class Plotter extends React.Component<Props, State> {
|
|
|
851
830
|
this.transform();
|
|
852
831
|
}
|
|
853
832
|
|
|
854
|
-
const values =
|
|
833
|
+
const values = [...self.state.values];
|
|
855
834
|
values[i] = y;
|
|
856
835
|
self.setState({values: values});
|
|
857
836
|
self.changeAndTrack({values: values});
|
|
@@ -901,7 +880,7 @@ export class Plotter extends React.Component<Props, State> {
|
|
|
901
880
|
onMove: function () {
|
|
902
881
|
const y = c.graph.points[i].coord()[1];
|
|
903
882
|
|
|
904
|
-
const values =
|
|
883
|
+
const values = [...self.state.values];
|
|
905
884
|
values[i] = y;
|
|
906
885
|
self.setState({values: values});
|
|
907
886
|
self.changeAndTrack({values: values});
|
|
@@ -941,7 +920,7 @@ export class Plotter extends React.Component<Props, State> {
|
|
|
941
920
|
});
|
|
942
921
|
c.graph.points[i].onMove = function (x, y) {
|
|
943
922
|
y = Math.min(Math.max(y, 0), c.dimY);
|
|
944
|
-
const values =
|
|
923
|
+
const values = [...self.state.values];
|
|
945
924
|
values[i] = y;
|
|
946
925
|
self.setState({values: values});
|
|
947
926
|
self.changeAndTrack({values: values});
|
|
@@ -1095,7 +1074,7 @@ export class Plotter extends React.Component<Props, State> {
|
|
|
1095
1074
|
};
|
|
1096
1075
|
|
|
1097
1076
|
setPicHeight: (arg1: number, arg2: number) => void = (i, y) => {
|
|
1098
|
-
const values =
|
|
1077
|
+
const values = [...this.state.values];
|
|
1099
1078
|
values[i] = y;
|
|
1100
1079
|
this.drawPicHeights(values, this.state.values);
|
|
1101
1080
|
this.setState({values: values});
|
|
@@ -1126,7 +1105,7 @@ export class Plotter extends React.Component<Props, State> {
|
|
|
1126
1105
|
const y = (j + 1) * self.props.scaleY;
|
|
1127
1106
|
const show = y <= values[i];
|
|
1128
1107
|
|
|
1129
|
-
if (self.props.type ===
|
|
1108
|
+
if (self.props.type === "dotplot") {
|
|
1130
1109
|
const wasShown = y <= prevValues[i];
|
|
1131
1110
|
const wasJustShown = show && !wasShown;
|
|
1132
1111
|
if (wasJustShown) {
|
package/src/widgets/video.tsx
CHANGED
|
@@ -24,6 +24,7 @@ const DEFAULT_HEIGHT = 720;
|
|
|
24
24
|
const KA_EMBED = "{host}/embed_video?slug={slug}" + "&internal_video_only=1";
|
|
25
25
|
const IS_URL = /^https?:\/\//;
|
|
26
26
|
const IS_KA_SITE = /(khanacademy\.org|localhost)/;
|
|
27
|
+
const IS_VIMEO = /(vimeo\.com)/;
|
|
27
28
|
|
|
28
29
|
type UserInput = null;
|
|
29
30
|
type Rubric = PerseusVideoWidgetOptions;
|
|
@@ -75,6 +76,16 @@ class Video extends React.Component<Props> {
|
|
|
75
76
|
|
|
76
77
|
if (IS_URL.test(location)) {
|
|
77
78
|
url = location;
|
|
79
|
+
if (IS_VIMEO.test(url)) {
|
|
80
|
+
// If this is a vimeo video, we need to add the query string
|
|
81
|
+
// parameter "dnt" so that analytics/tracking cookies aren't set.
|
|
82
|
+
// https://help.vimeo.com/hc/en-us/articles/12426260232977-Player-parameters-overview
|
|
83
|
+
if (url.indexOf("?") === -1) {
|
|
84
|
+
url += "?dnt=1";
|
|
85
|
+
} else {
|
|
86
|
+
url += "&dnt=1";
|
|
87
|
+
}
|
|
88
|
+
}
|
|
78
89
|
} else {
|
|
79
90
|
url = KA_EMBED.replace("{slug}", location);
|
|
80
91
|
let embedHostname = "https://www.khanacademy.org";
|