@khanacademy/perseus 1.3.0 → 1.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.
@@ -0,0 +1,191 @@
1
+ // @flow
2
+ import {action} from "@storybook/addon-actions";
3
+ import * as React from "react";
4
+
5
+ import {generateChoice} from "../../__testdata__/base-radio_testdata.js";
6
+ import BaseRadio from "../base-radio.jsx";
7
+
8
+ type StoryArgs = {|
9
+ multipleSelect: boolean,
10
+ editMode: boolean,
11
+ countChoices: boolean,
12
+ |};
13
+
14
+ type Story = {|
15
+ title: string,
16
+ args: StoryArgs,
17
+ |};
18
+
19
+ export default ({
20
+ title: "Perseus/Widgets/Radio/SAT Base Radio",
21
+ args: {
22
+ multipleSelect: false,
23
+ editMode: false,
24
+ countChoices: false,
25
+ },
26
+ }: Story);
27
+
28
+ const defaultProps = {
29
+ apiOptions: {
30
+ satStyling: true,
31
+ },
32
+ choices: [
33
+ generateChoice({
34
+ content: "Content 1",
35
+ }),
36
+ generateChoice({
37
+ content: "Content 2",
38
+ }),
39
+ generateChoice({
40
+ content: "Content 3",
41
+ correct: true,
42
+ }),
43
+ generateChoice({
44
+ isNoneOfTheAbove: true,
45
+ }),
46
+ ],
47
+ deselectEnabled: false,
48
+ editMode: false,
49
+ labelWrap: false,
50
+ countChoices: false,
51
+ numCorrect: 1,
52
+ multipleSelect: false,
53
+
54
+ // A callback indicating that this choice has changed. Its argument is
55
+ // an object with two keys: `checked` and `crossedOut`. Each contains
56
+ // an array of boolean values, specifying the new checked and
57
+ // crossed-out value of each choice.
58
+ onChange: action("changed"),
59
+
60
+ // Whether this widget was the most recently used widget in this
61
+ // Renderer. Determines whether we'll auto-scroll the page upon
62
+ // entering review mode.
63
+ isLastUsedWidget: false,
64
+ };
65
+
66
+ export const Interactive = (args: StoryArgs): React.Node => {
67
+ const overwrittenProps = {...defaultProps, ...args};
68
+ return <BaseRadio {...overwrittenProps} />;
69
+ };
70
+
71
+ export const SingleSelectWithNothingSelected = (
72
+ args: StoryArgs,
73
+ ): React.Node => {
74
+ const overwrittenProps = {...defaultProps, multipleSelect: false};
75
+ return <BaseRadio {...overwrittenProps} />;
76
+ };
77
+
78
+ export const MultipleSelectWithNothingSelected = (
79
+ args: StoryArgs,
80
+ ): React.Node => {
81
+ const overwrittenProps = {...defaultProps, multipleSelect: true};
82
+ return <BaseRadio {...overwrittenProps} />;
83
+ };
84
+
85
+ export const MultipleSelectWithCountChoicesLabel = (
86
+ args: StoryArgs,
87
+ ): React.Node => {
88
+ const overwrittenProps = {
89
+ ...defaultProps,
90
+ multipleSelect: true,
91
+ numCorrect: 2,
92
+ countChoices: true,
93
+ };
94
+ return <BaseRadio {...overwrittenProps} />;
95
+ };
96
+
97
+ export const SingleSelected = (args: StoryArgs): React.Node => {
98
+ const choices = Array(4)
99
+ .fill(null)
100
+ .map((_, i) => generateChoice({content: `Choice ${i + 1}`}));
101
+ choices[1].checked = true;
102
+
103
+ const overwrittenProps = {...defaultProps, multipleSelect: false, choices};
104
+ return <BaseRadio {...overwrittenProps} />;
105
+ };
106
+
107
+ export const MultipleSelected = (args: StoryArgs): React.Node => {
108
+ const choices = Array(4)
109
+ .fill(null)
110
+ .map((_, i) => generateChoice({content: `Choice ${i + 1}`}));
111
+ choices[1].checked = true;
112
+ choices[2].checked = true;
113
+
114
+ const overwrittenProps = {...defaultProps, multipleSelect: true, choices};
115
+ return <BaseRadio {...overwrittenProps} />;
116
+ };
117
+
118
+ export const SingleKitchenSink = (args: StoryArgs): React.Node => {
119
+ const choices = Array(4)
120
+ .fill(null)
121
+ .map((_, i) => {
122
+ const choice = generateChoice({
123
+ content: `Choice ${i + 1}`,
124
+ rationale: "This is a neat rationale",
125
+ hasRationale: true,
126
+ showRationale: true,
127
+ correct: false,
128
+ showCorrectness: true,
129
+ });
130
+
131
+ return choice;
132
+ });
133
+ choices[1].checked = true;
134
+ choices[2].correct = true;
135
+
136
+ const rubricChoices = choices.map(({correct}) => ({
137
+ // note(matthew): reviewModeRubric.choices requires content,
138
+ // but I don't see how it's getting used and Flow gets mad
139
+ // when I use choice.content because it's not a string.
140
+ // reviewModeRubric could probably use a look over.
141
+ content: "",
142
+ correct,
143
+ }));
144
+
145
+ const overwrittenProps = {
146
+ ...defaultProps,
147
+ multipleSelect: false,
148
+ reviewModeRubric: {choices: rubricChoices},
149
+ choices,
150
+ };
151
+ return <BaseRadio {...overwrittenProps} />;
152
+ };
153
+
154
+ export const MultipleKitchenSink = (args: StoryArgs): React.Node => {
155
+ const choices = Array(4)
156
+ .fill(null)
157
+ .map((_, i) => {
158
+ const choice = generateChoice({
159
+ content: `Choice ${i + 1}`,
160
+ rationale: "This is a neat rationale",
161
+ hasRationale: true,
162
+ showRationale: true,
163
+ correct: false,
164
+ showCorrectness: true,
165
+ });
166
+
167
+ return choice;
168
+ });
169
+ choices[1].checked = true;
170
+ choices[2].checked = true;
171
+ choices[2].correct = true;
172
+ choices[3].correct = true;
173
+
174
+ const rubricChoices = choices.map((c) => ({
175
+ // note(matthew): reviewModeRubric.choices requires content,
176
+ // but I don't see how it's getting used and Flow gets mad
177
+ // when I use choice.content because it's not a string.
178
+ // reviewModeRubric could probably use a look over.
179
+ content: "",
180
+ correct: c.correct,
181
+ }));
182
+
183
+ const overwrittenProps = {
184
+ ...defaultProps,
185
+ multipleSelect: true,
186
+ numCorrect: 2,
187
+ reviewModeRubric: {choices: rubricChoices},
188
+ choices,
189
+ };
190
+ return <BaseRadio {...overwrittenProps} />;
191
+ };
@@ -454,8 +454,7 @@ const styles: StyleDeclaration = StyleSheet.create({
454
454
  },
455
455
 
456
456
  radio: {
457
- // Avoid centering
458
- width: "100%",
457
+ padding: 0,
459
458
  },
460
459
 
461
460
  responsiveRadioContainer: {
@@ -14,7 +14,7 @@ import {useState, useEffect} from "react";
14
14
  import _ from "underscore";
15
15
 
16
16
  import Icon from "../../components/icon.jsx";
17
- import {ApiOptions} from "../../perseus-api.jsx";
17
+ import {ApiOptions, ClassNames} from "../../perseus-api.jsx";
18
18
  import * as styleConstants from "../../styles/constants.js";
19
19
  import mediaQueries from "../../styles/media-queries.js";
20
20
 
@@ -140,7 +140,6 @@ function Choice(props: ChoicePropsWithForwardRef): React.Node {
140
140
  css(
141
141
  !apiOptions.satStyling && styles.description,
142
142
  apiOptions.satStyling && styles.satDescription,
143
- satCorrectChoice && styles.satDescriptionCorrect,
144
143
  satCorrectChoice && checked && styles.satDescriptionCorrectChecked,
145
144
  satIncorrectChecked && styles.satDescriptionIncorrectChecked,
146
145
  ),
@@ -179,12 +178,12 @@ function Choice(props: ChoicePropsWithForwardRef): React.Node {
179
178
  dispay: "flex",
180
179
  flexDirection: "column",
181
180
  }}
181
+ className={descriptionClassName}
182
182
  >
183
183
  <div
184
184
  style={{
185
185
  display: "flex",
186
186
  flexDirection: "row",
187
- width: "100%",
188
187
  opacity: showDimmed ? 0.5 : 1.0,
189
188
  }}
190
189
  >
@@ -208,6 +207,7 @@ function Choice(props: ChoicePropsWithForwardRef): React.Node {
208
207
  apiOptions.readOnly
209
208
  }
210
209
  tabIndex={-1}
210
+ className={ClassNames.RADIO.OPTION_CONTENT}
211
211
  />
212
212
  <label htmlFor={choiceId}>
213
213
  {a11yText} &nbsp; {content}
@@ -222,7 +222,6 @@ function Choice(props: ChoicePropsWithForwardRef): React.Node {
222
222
  crossedOut: false,
223
223
  });
224
224
  }}
225
- className={descriptionClassName}
226
225
  disabled={
227
226
  disabled ||
228
227
  apiOptions.staticRender ||
@@ -390,11 +389,7 @@ const styles = StyleSheet.create({
390
389
  boxSizing: "border-box",
391
390
  cursor: "pointer",
392
391
  marginLeft: 0,
393
- padding: "17px 14px",
394
- },
395
-
396
- satDescriptionCorrect: {
397
- color: styleConstants.satCorrectColor,
392
+ padding: "17px 14px 17px 0",
398
393
  },
399
394
 
400
395
  satDescriptionCorrectChecked: {
@@ -402,7 +397,6 @@ const styles = StyleSheet.create({
402
397
  },
403
398
 
404
399
  satDescriptionIncorrectChecked: {
405
- color: styleConstants.satIncorrectColor,
406
400
  backgroundColor: styleConstants.satIncorrectBackgroundColor,
407
401
  },
408
402