@khanacademy/perseus 1.4.1 → 2.0.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.
Files changed (51) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/dist/es/index.css +9 -245
  3. package/dist/es/index.js +138 -584
  4. package/dist/es/index.js.map +1 -1
  5. package/dist/index.css +9 -245
  6. package/dist/index.js +135 -581
  7. package/dist/index.js.map +1 -1
  8. package/package.json +1 -1
  9. package/src/__stories__/hints-renderer.stories.jsx +9 -1
  10. package/src/__testdata__/graphie_testdata.js +53 -0
  11. package/src/__tests__/__snapshots__/perseus-markdown_test.jsx.snap +0 -9
  12. package/src/__tests__/__snapshots__/renderer_test.jsx.snap +0 -9
  13. package/src/components/__stories__/graphie.stories.jsx +5 -1
  14. package/src/hint-renderer.jsx +11 -14
  15. package/src/perseus-api.jsx +0 -23
  16. package/src/perseus-markdown.jsx +0 -25
  17. package/src/styles/constants.js +0 -21
  18. package/src/styles/global-constants.js +0 -6
  19. package/src/styles/khan-exercise.css +9 -1
  20. package/src/styles/perseus-renderer.less +0 -259
  21. package/src/styles/variables.less +0 -11
  22. package/src/styles/variables.shared.less +0 -10
  23. package/src/types.js +0 -16
  24. package/src/widgets/__stories__/input-number.stories.jsx +0 -14
  25. package/src/widgets/__stories__/radio.stories.jsx +0 -3
  26. package/src/widgets/__tests__/__snapshots__/definition_test.js.snap +18 -28
  27. package/src/widgets/__tests__/__snapshots__/group_test.jsx.snap +0 -9
  28. package/src/widgets/__tests__/__snapshots__/image_test.jsx.snap +0 -18
  29. package/src/widgets/__tests__/__snapshots__/numeric-input_test.jsx.snap +2 -440
  30. package/src/widgets/__tests__/__snapshots__/radio_test.jsx.snap +66 -3726
  31. package/src/widgets/__tests__/numeric-input_test.jsx +54 -118
  32. package/src/widgets/__tests__/radio/choice-icon_test.jsx +25 -75
  33. package/src/widgets/__tests__/radio_test.jsx +362 -394
  34. package/src/widgets/definition.jsx +27 -14
  35. package/src/widgets/input-number.jsx +2 -60
  36. package/src/widgets/numeric-input.jsx +17 -89
  37. package/src/widgets/radio/__stories__/base-radio.stories.jsx +1 -3
  38. package/src/widgets/radio/__stories__/choice-icon.stories.jsx +23 -105
  39. package/src/widgets/radio/__stories__/option-status.stories.jsx +0 -8
  40. package/src/widgets/radio/base-radio.jsx +13 -96
  41. package/src/widgets/radio/choice-icon/choice-icon.jsx +177 -50
  42. package/src/widgets/radio/choice-icon/cross-out-line.jsx +9 -13
  43. package/src/widgets/radio/choice-icon/shared-styles.js +2 -3
  44. package/src/widgets/radio/choice.jsx +5 -59
  45. package/src/widgets/radio/option-status.jsx +2 -14
  46. package/src/components/__stories__/possible-answers.stories.jsx +0 -22
  47. package/src/components/possible-answers.jsx +0 -36
  48. package/src/styles/widgets/definition.less +0 -86
  49. package/src/widgets/radio/__stories__/sat-styles.stories.jsx +0 -191
  50. package/src/widgets/radio/choice-icon/library-choice-icon.jsx +0 -225
  51. package/src/widgets/radio/choice-icon/sat-choice-icon.jsx +0 -120
@@ -1,36 +0,0 @@
1
- // @flow
2
- /**
3
- * In review mode (currently only visible in the sat-mission), NumericInput and
4
- * InputNumber use this component to display the set of correct answers.
5
- */
6
-
7
- import * as i18n from "@khanacademy/wonder-blocks-i18n";
8
- import PropTypes from "prop-types";
9
- import * as React from "react";
10
- import _ from "underscore";
11
-
12
- class PossibleAnswers extends React.Component<$FlowFixMe> {
13
- static propTypes = {
14
- answers: PropTypes.arrayOf(PropTypes.string),
15
- };
16
-
17
- render(): React.Node {
18
- // It's redundant to show duplicate answers.
19
- // So, remove duplicates from the given list of answer strings.
20
- const answers = _.uniq(this.props.answers);
21
-
22
- const answerComponents = _.map(answers, (answer) => {
23
- // Plus, now that our answers are distinct, we can safely use the
24
- // answer string as a key.
25
- return <dd key={answer}>{answer}</dd>;
26
- });
27
- return (
28
- <dl className="perseus-possible-answers">
29
- <dt>{i18n.doNotTranslate("Correct Answer")}</dt>
30
- {answerComponents}
31
- </dl>
32
- );
33
- }
34
- }
35
-
36
- export default PossibleAnswers;
@@ -1,86 +0,0 @@
1
- @import "../variables.less";
2
- @import "../util.less";
3
-
4
- // HACK(michaelpolyak): As the Definition widget may be rendered within an
5
- // Article or an Exercise, we need to support the "legacy" way of styling for
6
- // the specific responsive rendering context. In order to match the surrounding
7
- // Perseus content styling, we copy and apply styles defined in
8
- // `perseus-renderer.less`, `articles.less` (both of which are now moved into
9
- // Perseus).
10
-
11
- // Desktop exercise styles
12
- .framework-perseus:not(.perseus-article):not(.perseus-mobile) {
13
- .perseus-widget-definition {
14
- .legacy-typography;
15
- }
16
- }
17
-
18
- // Mobile exercise styles
19
- .framework-perseus:not(.perseus-article).perseus-mobile {
20
- .perseus-widget-definition {
21
- @desktop-width-min: 1200px;
22
- @tablet-width-max: (@desktop-width-min - 1);
23
-
24
- // Phone styles
25
- @media (max-width: @pure-sm-max) {
26
- font-size: 18px;
27
- line-height: 1.4;
28
- }
29
-
30
- // Tablet styles
31
- @media (min-width: @pure-md-min) and (max-width: @tablet-width-max) {
32
- font-size: 20px;
33
- line-height: 1.5;
34
- }
35
-
36
- // "Desktop" (resolution) styles (while rendering on a mobile device,
37
- // ie. `this.props.apiOptions.isMobile` is `true`)
38
- @media (min-width: @desktop-width-min) {
39
- font-size: 22px;
40
- line-height: 1.4;
41
- }
42
- }
43
- }
44
-
45
- // Default article styles
46
- .bibliotron-article.framework-perseus.perseus-article {
47
- .perseus-widget-definition {
48
- font-size: 18px;
49
- line-height: 1.4;
50
- }
51
- }
52
-
53
- // Desktop article styles
54
- .bibliotron-article.framework-perseus.perseus-article:not(.perseus-mobile) {
55
- .perseus-widget-definition {
56
- font-size: 20px;
57
- line-height: 30px;
58
- }
59
- }
60
-
61
- // Mobile article styles
62
- .bibliotron-article.framework-perseus.perseus-article.perseus-mobile {
63
- .perseus-widget-definition {
64
- @desktop-width-min: 1200px;
65
- @tablet-width-max: (@desktop-width-min - 1);
66
-
67
- // Phone styles
68
- @media (max-width: @pure-sm-max) {
69
- font-size: 18px;
70
- line-height: 1.4;
71
- }
72
-
73
- // Tablet styles
74
- @media (min-width: @pure-md-min) and (max-width: @tablet-width-max) {
75
- font-size: 20px;
76
- line-height: 1.5;
77
- }
78
-
79
- // "Desktop" (resolution) styles (while rendering on a mobile device,
80
- // ie. `this.props.apiOptions.isMobile` is `true`)
81
- @media (min-width: @desktop-width-min) {
82
- font-size: 22px;
83
- line-height: 1.4;
84
- }
85
- }
86
- }
@@ -1,191 +0,0 @@
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
- };
@@ -1,225 +0,0 @@
1
- // @flow
2
- /* Component for rendering a letter icon in a library radio choice */
3
-
4
- import Color from "@khanacademy/wonder-blocks-color";
5
- import {StyleSheet, css} from "aphrodite";
6
- import * as React from "react";
7
-
8
- import InlineIcon from "../../../components/inline-icon.jsx";
9
- import {iconCheck, iconMinus} from "../../../icon-paths.js";
10
- import * as styleConstants from "../../../styles/constants.js";
11
- import FocusRing from "../focus-ring.jsx";
12
-
13
- import CrossOutLine from "./cross-out-line.jsx";
14
- import sharedStyles, {LIBRARY_ICON_SIZE} from "./shared-styles.js";
15
-
16
- type LibraryChoiceIconProps = {
17
- letter: string,
18
- checked: boolean,
19
- crossedOut: boolean,
20
- focused: boolean,
21
- hovered: boolean,
22
- pressed: boolean,
23
- multipleSelect: boolean,
24
- correct: ?boolean,
25
- reviewMode: boolean,
26
- showCorrectness: boolean,
27
- primaryProductColor: string,
28
- previouslyAnswered: boolean,
29
- transparentBackground?: boolean,
30
- };
31
-
32
- function ChoiceInner(props: {
33
- letter: string,
34
- showCorrectness: boolean,
35
- correct: ?boolean,
36
- }) {
37
- const {letter, showCorrectness, correct} = props;
38
-
39
- if (!showCorrectness) {
40
- return letter;
41
- }
42
- if (correct) {
43
- return (
44
- <InlineIcon
45
- {...iconCheck}
46
- style={{
47
- position: "relative",
48
- top: -1,
49
- }}
50
- />
51
- );
52
- }
53
- return <InlineIcon {...iconMinus} />;
54
- }
55
-
56
- // Handle dynamic styling of the multiple choice icon. Most
57
- // MC icon styles are constant, but we do allow the caller
58
- // to specify the selected color, and thus must control styles
59
- // related to the selected state dynamically.
60
- function getDynamicStyles(
61
- checked: boolean,
62
- showCorrectness: boolean,
63
- pressed: boolean,
64
- multipleSelect: boolean,
65
- primaryProductColor: string,
66
- correct: ?boolean,
67
- transparentBackground?: boolean,
68
- ): {
69
- backgroundColor: ?string,
70
- borderColor: string,
71
- color: string,
72
- borderRadius: number,
73
- } {
74
- let backgroundColor;
75
- let borderColor;
76
- let color;
77
- if (!showCorrectness && pressed) {
78
- borderColor = primaryProductColor;
79
- color = primaryProductColor;
80
- backgroundColor = transparentBackground
81
- ? "transparent"
82
- : styleConstants.white;
83
- } else if (checked) {
84
- // Note: kaGreen is not only the default product color,
85
- // but also the "correctness" color
86
- const bg =
87
- showCorrectness && correct ? Color.green : primaryProductColor;
88
- color = styleConstants.white;
89
- backgroundColor = bg;
90
- borderColor = bg;
91
- } else {
92
- borderColor = Color.offBlack64;
93
- color = Color.offBlack64;
94
- }
95
-
96
- // define shape
97
- let borderRadius;
98
- if (multipleSelect) {
99
- borderRadius = 3;
100
- } else {
101
- borderRadius = LIBRARY_ICON_SIZE;
102
- }
103
-
104
- return {backgroundColor, borderColor, color, borderRadius};
105
- }
106
-
107
- function LibraryChoiceIcon(props: LibraryChoiceIconProps): React.Node {
108
- const {
109
- checked,
110
- crossedOut,
111
- showCorrectness,
112
- correct,
113
- focused,
114
- hovered,
115
- multipleSelect,
116
- primaryProductColor,
117
- previouslyAnswered,
118
- letter,
119
- pressed,
120
- transparentBackground,
121
- } = props;
122
-
123
- const dynamicStyles = getDynamicStyles(
124
- checked,
125
- showCorrectness,
126
- pressed,
127
- multipleSelect,
128
- primaryProductColor,
129
- correct,
130
- transparentBackground,
131
- );
132
-
133
- return (
134
- <div className={css(sharedStyles.iconWrapper)}>
135
- <FocusRing
136
- color={primaryProductColor}
137
- visible={focused || hovered}
138
- multipleSelect={multipleSelect}
139
- >
140
- <div
141
- style={dynamicStyles}
142
- data-test-id="choice-icon__library-choice-icon"
143
- className={css(
144
- styles.circle,
145
- showCorrectness && correct && styles.circleCorrect,
146
- showCorrectness && !correct && styles.circleIncorrect,
147
- showCorrectness &&
148
- !correct &&
149
- (checked || previouslyAnswered) &&
150
- styles.circleIncorrectAnswered,
151
- )}
152
- // used in BaseRadio editMode to check
153
- // if we actually clicked on the radio icon
154
- data-is-radio-icon={true}
155
- >
156
- <div className={css(styles.innerWrapper)}>
157
- <ChoiceInner
158
- letter={letter}
159
- showCorrectness={showCorrectness}
160
- correct={correct}
161
- />
162
- </div>
163
- </div>
164
- </FocusRing>
165
- {crossedOut && <CrossOutLine color={dynamicStyles.borderColor} />}
166
- </div>
167
- );
168
- }
169
-
170
- const styles = StyleSheet.create({
171
- innerWrapper: {
172
- width: LIBRARY_ICON_SIZE,
173
- height: LIBRARY_ICON_SIZE,
174
-
175
- // Center the contents of the icon.
176
- display: "flex",
177
- alignItems: "center",
178
- justifyContent: "center",
179
- },
180
- circle: {
181
- // Make the circle
182
- width: LIBRARY_ICON_SIZE,
183
- height: LIBRARY_ICON_SIZE,
184
- boxSizing: "border-box",
185
- borderStyle: "solid",
186
- borderWidth: 2,
187
-
188
- // The default icons have letters in them. Style those letters.
189
- fontFamily: styleConstants.baseFontFamily,
190
- // NOTE(emily): We explicitly set the font weight instead of using the
191
- // "bold font family" so that characters which fall back to the default
192
- // font get bolded too.
193
- fontWeight: "bold",
194
- fontSize: 12,
195
-
196
- // Center the icon wrapper.
197
- display: "flex",
198
- alignItems: "center",
199
- justifyContent: "center",
200
- // HACK(emily): I don't know why adding this line height makes the text
201
- // appear centered better than any other value, but it does. In
202
- // particular, at large zoom levels this line height does almost
203
- // nothing, but at the default size this shifts the letter down one
204
- // pixel so it is much better centered.
205
- lineHeight: "1px",
206
- },
207
-
208
- circleCorrect: {
209
- fontSize: LIBRARY_ICON_SIZE,
210
- },
211
-
212
- circleIncorrect: {
213
- fontSize: LIBRARY_ICON_SIZE,
214
- borderColor: styleConstants.gray68,
215
- color: styleConstants.gray68,
216
- },
217
-
218
- circleIncorrectAnswered: {
219
- backgroundColor: Color.red,
220
- borderColor: Color.red,
221
- color: Color.white,
222
- },
223
- });
224
-
225
- export default LibraryChoiceIcon;
@@ -1,120 +0,0 @@
1
- // @flow
2
- /* Component for rendering a letter icon in a SAT radio choice */
3
-
4
- import {StyleSheet, css} from "aphrodite";
5
- import * as React from "react";
6
-
7
- import * as styleConstants from "../../../styles/constants.js";
8
-
9
- import CrossOutLine from "./cross-out-line.jsx";
10
- import sharedStyles, {SAT_ICON_SIZE} from "./shared-styles.js";
11
-
12
- type SATChoiceIconProps = {
13
- letter: string,
14
- checked: boolean,
15
- multipleSelect: boolean,
16
- correct: boolean,
17
- reviewMode: boolean,
18
- crossedOut: boolean,
19
- };
20
-
21
- // TODO(amy): figure out a better scheme for specifying these
22
- // styles that isn't such a pain to grok. See some neat ideas
23
- // from MDR in https://phabricator.khanacademy.org/D35249.
24
- function constructSATStyles(
25
- reviewMode: boolean,
26
- correct: boolean,
27
- checked: boolean,
28
- multipleSelect: boolean,
29
- ): {
30
- color: string,
31
- backgroundColor: ?string,
32
- borderColor: string,
33
- borderRadius: number,
34
- } {
35
- let backgroundColor;
36
- let borderColor = styleConstants.satBlue;
37
- let color = styleConstants.satBlue;
38
- if (reviewMode) {
39
- if (correct) {
40
- borderColor = styleConstants.satCorrectColor;
41
- color = checked
42
- ? styleConstants.white
43
- : styleConstants.satCorrectColor;
44
- backgroundColor = checked
45
- ? styleConstants.satCorrectColor
46
- : styleConstants.white;
47
- } else if (checked) {
48
- borderColor = styleConstants.satIncorrectColor;
49
- color = styleConstants.white;
50
- backgroundColor = styleConstants.satIncorrectColor;
51
- }
52
- } else if (checked) {
53
- color = styleConstants.white;
54
- backgroundColor = styleConstants.satBlue;
55
- }
56
-
57
- let borderRadius;
58
- if (multipleSelect) {
59
- borderRadius = 3;
60
- } else {
61
- borderRadius = SAT_ICON_SIZE;
62
- }
63
-
64
- return {color, backgroundColor, borderColor, borderRadius};
65
- }
66
-
67
- function SATChoiceIcon(props: SATChoiceIconProps): React.Node {
68
- const {letter, crossedOut, reviewMode, correct, checked, multipleSelect} =
69
- props;
70
-
71
- const {color, backgroundColor, borderColor, borderRadius} =
72
- constructSATStyles(reviewMode, correct, checked, multipleSelect);
73
-
74
- return (
75
- <div className={css(sharedStyles.iconWrapper)}>
76
- <div
77
- className={css(styles.satCircle)}
78
- data-test-id="choice-icon__sat-choice-icon"
79
- style={{backgroundColor, borderColor, borderRadius}}
80
- />
81
- <div style={{color}} className={css(styles.letter)}>
82
- <span>{letter}</span>
83
- </div>
84
- {crossedOut && <CrossOutLine color={borderColor} sat={true} />}
85
- </div>
86
- );
87
- }
88
-
89
- const styles = StyleSheet.create({
90
- satCircle: {
91
- display: "block",
92
- borderStyle: "solid",
93
- borderWidth: 2,
94
- content: `''`,
95
- height: SAT_ICON_SIZE,
96
- width: SAT_ICON_SIZE,
97
- top: 1,
98
- left: 1,
99
- },
100
- letter: {
101
- // These properties make sure that this element has the exact
102
- // same size as `circle` so that we can center things
103
- // inside of it.
104
- border: "2px solid transparent",
105
- width: SAT_ICON_SIZE,
106
- height: SAT_ICON_SIZE,
107
- position: "absolute",
108
- top: 1,
109
-
110
- // Center contained items.
111
- display: "flex",
112
- alignItems: "center",
113
- justifyContent: "center",
114
-
115
- fontFamily: styleConstants.boldFontFamily,
116
- fontSize: 13,
117
- },
118
- });
119
-
120
- export default SATChoiceIcon;