@khanacademy/perseus 1.4.0 → 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 +22 -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 +36 -36
  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
@@ -443,7 +443,6 @@
443
443
  }
444
444
 
445
445
  @import "./widgets/categorizer.less";
446
- @import "./widgets/definition.less";
447
446
  @import "./widgets/dropdown.less";
448
447
  @import "./widgets/expression.less";
449
448
  @import "./widgets/grapher.less";
@@ -722,264 +721,6 @@
722
721
  @satTopSpacingForTwoColumnLayout: 48px;
723
722
  @satTwoColumnLayoutSideMargin: 32px;
724
723
 
725
- // #sat-mission (below) matches when we're inside the SAT MVP product,
726
- // basically internal-only and in flux.
727
- #sat-mission {
728
- @satContentWidth: 592px;
729
-
730
- .content-area > div {
731
- margin-left: auto;
732
- margin-right: auto;
733
- width: @satContentWidth;
734
- .perseus-input-with-label {
735
- display: flex;
736
- align-items: center;
737
- .perseus-input-label {
738
- font-weight: 600;
739
- padding-right: 10px;
740
- }
741
- }
742
- .perseus-input-with-answer-blurb {
743
- // numeric-inputs widgets use labels whereas input-number widgets
744
- // use spans.
745
- > span, > label {
746
- display: inline-block;
747
- }
748
-
749
- .perseus-possible-answers {
750
- color: rgb(0, 153, 0);
751
- display: inline-block;
752
- padding-right: 4px;
753
-
754
- dt, dd {
755
- // If you just use inline, then screen readers (or at least
756
- // ChromeVox) won't read the answers as distinct items;
757
- // if 2 and 4 were both correct, then it would read them
758
- // concatenated as "twenty-four".
759
- display: inline-block;
760
- }
761
-
762
- dt {
763
- padding: 0 5px 0 13px;
764
- color: rgb(18, 18, 18);
765
- text-transform: uppercase;
766
- }
767
-
768
- dt::after {
769
- content: ":";
770
- }
771
-
772
- dd:not(:last-child)::after {
773
- // TODO(johnsullivan): Figure out a better way to do this list
774
- // joining.
775
- // TODO(mattdr): Joining in CSS makes semantic sense here
776
- // (they're definition list entries that we happen to be
777
- // rendering as a line of text joined by "or"), but CSS is
778
- // more difficult to internationalize. SAT is English-only
779
- // for now, though.
780
- content: "or";
781
- padding: 0 5px;
782
- color: rgb(18, 18, 18);
783
- }
784
- }
785
- }
786
-
787
- input.perseus-incorrect {
788
- color: @satIncorrectColor;
789
- background-color: @satIncorrectBackgroundColor;
790
- border: solid 1px @satIncorrectBorderColor;
791
- }
792
-
793
- input.perseus-correct {
794
- color: @satCorrectColor;
795
- background-color: @satCorrectBackgroundColor;
796
- border: solid 1px @satCorrectBorderColor;
797
- }
798
-
799
- input.perseus-unanswered {
800
- background-color: #eee;
801
- border: solid 1px #999;
802
- }
803
-
804
- &.perseus-renderer-two-columns {
805
- width: 1024px;
806
-
807
- // This prevents a strange blank space from appearing above
808
- // passages.
809
- // TODO(johnsullivan): Try and get rid of the wrapping div that's
810
- // causing this instead of modifying its margin like this.
811
- & > .paragraph {
812
- margin: 0;
813
- }
814
-
815
- .perseus-two-columns {
816
- display: flex;
817
- justify-content: center;
818
- }
819
-
820
- .perseus-column {
821
- // NOTE(emily): For some reason, these prefixes aren't being
822
- // added by our auto-prefixer, and we need these prefixes to
823
- // work in Safari <= 8.
824
- display: -webkit-flex;
825
- -webkit-flex-direction: column;
826
-
827
- display: flex;
828
- flex-direction: column;
829
- // Should this be @articleMaxWidthTablet? or is this
830
- // conceptually a different value?
831
- width: 512px;
832
-
833
- &:nth-child(1) {
834
- background: #eee;
835
- border-right: 1px solid #ddd;
836
- box-sizing: border-box;
837
-
838
- .perseus-column-content {
839
- padding-top: @satTopSpacingForTwoColumnLayout;
840
- padding-bottom: 22px;
841
- padding-left: 46px;
842
- padding-right: @satTwoColumnLayoutSideMargin;
843
- }
844
-
845
- .perseus-widget-passage-container {
846
- position: relative;
847
- .perseus-widget-passage-instructions div.paragraph {
848
- margin-top: 0;
849
- }
850
- }
851
- .perseus-widget-passage {
852
- // We've replaced the margin here with padding in the
853
- // parent element to stay consistent with non-passage
854
- // two-column mode.
855
- margin: 0;
856
- }
857
-
858
- & > .paragraph {
859
- margin-right: 40px;
860
- }
861
-
862
- blockquote {
863
- padding: 0;
864
- margin-right: 22px;
865
-
866
- & > .paragraph:nth-child(1) {
867
- margin-top: 0;
868
- }
869
- }
870
- }
871
-
872
- &:nth-child(2) {
873
- .perseus-column-content {
874
- padding-left: @satTwoColumnLayoutSideMargin;
875
- padding-right: @satTwoColumnLayoutSideMargin;
876
- }
877
-
878
- .perseus-group {
879
- margin-bottom: 20px;
880
- }
881
- }
882
- }
883
-
884
- .perseus-column-content {
885
- flex: 1 1 auto;
886
- overflow-y: auto;
887
-
888
- & > .paragraph {
889
- margin-top: 0;
890
- }
891
- }
892
-
893
- }
894
- }
895
-
896
- input[type=text],
897
- input[type=number] {
898
- border: 1px solid #aaa;
899
- font-family: @boldFontFamily;
900
- font-size: 14px;
901
- margin: 10px 0;
902
- padding: 5px;
903
-
904
- &:focus {
905
- border-color: @satBlue;
906
- box-shadow: 0 0 10px fade(@satBlue, 80%);
907
- outline: none;
908
- }
909
- }
910
-
911
- .valid-answer-mixin() {
912
- input[type=text]:valid, input[type=number]:valid {
913
- border: 1px solid @satBlue;
914
- background: @satSelectedBackgroundColor;
915
- color: initial;
916
-
917
- &:focus {
918
- box-shadow: 0 0 10px fade(@satBlue, 80%);
919
- }
920
- }
921
- }
922
-
923
- .invalid-answer-mixin() {
924
- input[type=text]:valid, input[type=number]:valid {
925
- color: @satIncorrectColor;
926
- background-color: @satIncorrectBackgroundColor;
927
- border: solid 1px @satIncorrectBorderColor;
928
-
929
- &:focus {
930
- box-shadow: 0 0 10px fade(@satIncorrectBorderColor, 80%);
931
- }
932
- }
933
- }
934
-
935
- // If a textbox appears inside a Perseus group widget, then the group
936
- // widget's validity should override the item's validity when styling that
937
- // item.
938
- //
939
- // That is, if a group widget is valid, but the item as a whole is
940
- // invalid, inputs inside the valid group widget should still render as
941
- // valid.
942
- //
943
- // This is implemented as a mixin and mixed into .valid-answer and
944
- // .invalid-answer, in order to ensure that there's no ambiguity as to
945
- // which selector takes precedence. Additionally, this ensures that these
946
- // styles will only be applied when validity is relevant to the user (i.e.
947
- // not in review mode).
948
- .perseus-group-validity-override() {
949
- .perseus-group-valid-answer {
950
- .valid-answer-mixin();
951
- }
952
- .perseus-group-invalid-answer {
953
- .invalid-answer-mixin();
954
- }
955
- }
956
-
957
- .valid-answer {
958
- .valid-answer-mixin();
959
- .perseus-group-validity-override();
960
- }
961
- .invalid-answer {
962
- .invalid-answer-mixin();
963
- .perseus-group-validity-override();
964
- }
965
-
966
- #sat-route-task, #sat-route-section {
967
- .content-area > .perseus-renderer-two-columns {
968
- // Override column top margin to 0 (the first column will get
969
- // the desired spacing by adding padding - to preserve the
970
- // gray background)
971
- margin-top: 0;
972
-
973
- // Add spacing to the second column, by way of its first child.
974
- // We want the margins to auto collapse, and so we can't add
975
- // it to perseus-column because it's floated.
976
- .perseus-column:nth-child(2) > .perseus-column-content > :first-child {
977
- margin-top: @satTopSpacingForTwoColumnLayout;
978
- }
979
- }
980
- }
981
- }
982
-
983
724
  .perseus-error {
984
725
  background: @red;
985
726
  border: 2px solid red;
@@ -41,17 +41,6 @@
41
41
  @pure-md-max: (@pure-lg-min - 1);
42
42
  @pure-lg-max: (@pure-xl-min - 1);
43
43
 
44
- // SAT variables
45
- @satBlue: #0084ce;
46
- @satSelectedBackgroundColor: #e4f3f9;
47
- @satActiveBackgroundColor: #d0edf4;
48
- @satCorrectColor: #009900;
49
- @satCorrectBorderColor: #00cc00;
50
- @satCorrectBackgroundColor: #e4f7e4;
51
- @satIncorrectColor: #990000;
52
- @satIncorrectBorderColor: #cc5252;
53
- @satIncorrectBackgroundColor: #f2ebeb;
54
-
55
44
  // Layer variables
56
45
  @zIndexScratchPad: 1;
57
46
  @zIndexAboveScratchpad: @zIndexScratchPad + 1;
@@ -311,16 +311,6 @@
311
311
  @collegeCareersMoreLinkColor: @collegeCareersMoreDomainColor;
312
312
  @collegeCareersMoreLinkHoverColor: @collegeCareersMoreTopicColor;
313
313
 
314
- // NOTE(johnsullivan): SAT isn't really a part of the domain system so doesn't
315
- // get included in the .applyToDomains mixin. Currently these variables are
316
- // only used for KUI buttons.
317
- @satDomainColor: #0084ce;
318
- @satSubjectColor: #0084ce;
319
- @satTopicColor: #0084ce;
320
- @satHoverColor: @satDomainColor;
321
- @satLinkColor: @satDomainColor;
322
- @satLinkHoverColor: @satTopicColor;
323
-
324
314
  // Exercise Colors
325
315
  // If you update these colours, please update thumbnail_handler.py's
326
316
  // get_domain_color method.
package/src/types.js CHANGED
@@ -142,7 +142,6 @@ type StubTagEditorType = $FlowFixMe; // from "./components/stub-tag-editor.jsx";
142
142
  export type APIOptions = $ReadOnly<{|
143
143
  isArticle?: boolean,
144
144
 
145
- satStyling?: boolean,
146
145
  // This should actually be required since renderer.jsx sets defaults for
147
146
  // any missing properties in this object using this.getApiOptions() before
148
147
  // passing the prop on to other components.
@@ -232,19 +231,6 @@ export type APIOptions = $ReadOnly<{|
232
231
  // Whether to use the Draft.js editor or the legacy textarea
233
232
  useDraftEditor?: boolean,
234
233
 
235
- // Styling options that control the visual behavior of Perseus
236
- // items.
237
- // TODO(mdr): If we adopt this pattern, we'll need to think about
238
- // how to make individual `styling` options be optional, and
239
- // how to set their default values without overwriting provided
240
- // values. For now, though, you must either specify all fields
241
- // of `styling`, or omit the `styling` option entirely.
242
- styling?: {|
243
- // TODO(Nicole): Remove this after landing wonderblock-ifying
244
- // the radio widget
245
- primaryProductColor?: string,
246
- |},
247
-
248
234
  // The color used for the hint progress indicator (eg. 1 / 3)
249
235
  hintProgressColor?: string,
250
236
 
@@ -399,13 +385,11 @@ export type APIOptionsWithDefaults = $ReadOnly<{|
399
385
  onFocusChange: $NonMaybeType<APIOptions["onFocusChange"]>,
400
386
  onInputError: $NonMaybeType<APIOptions["onInputError"]>,
401
387
  readOnly: $NonMaybeType<APIOptions["readOnly"]>,
402
- satStyling: $NonMaybeType<APIOptions["satStyling"]>,
403
388
  setDrawingAreaAvailable: $NonMaybeType<
404
389
  APIOptions["setDrawingAreaAvailable"],
405
390
  >,
406
391
  showAlignmentOptions: $NonMaybeType<APIOptions["showAlignmentOptions"]>,
407
392
  staticRender: $NonMaybeType<APIOptions["staticRender"]>,
408
- styling: $NonMaybeType<APIOptions["styling"]>,
409
393
  useDraftEditor: $NonMaybeType<APIOptions["useDraftEditor"]>,
410
394
  |}>;
411
395
 
@@ -100,17 +100,3 @@ export const Percent = (args: InputNumberOptions): React.Node => {
100
100
  return <RendererWithDebugUI question={question} />;
101
101
  };
102
102
  Percent.args = question3.widgets["input-number 1"].options;
103
-
104
- export const RationalWithSatStyling = (
105
- args: InputNumberOptions,
106
- ): React.Node => {
107
- const question = updateWidgetOptions(question1, "input-number 1", args);
108
- return (
109
- <RendererWithDebugUI
110
- question={question}
111
- apiOptions={{satStyling: true}}
112
- reviewMode={true}
113
- />
114
- );
115
- };
116
- Rational.args = question1.widgets["input-number 1"].options;
@@ -17,7 +17,6 @@ type StoryArgs = {|
17
17
  static: boolean,
18
18
 
19
19
  // API Options
20
- satStyling: boolean,
21
20
  crossOutEnabled: boolean,
22
21
 
23
22
  // Renderer Options
@@ -33,7 +32,6 @@ export default ({
33
32
  title: "Perseus/Widgets/Radio",
34
33
  args: {
35
34
  static: false,
36
- satStyling: false,
37
35
  crossOutEnabled: false,
38
36
  reviewMode: false,
39
37
  },
@@ -57,7 +55,6 @@ const applyStoryArgs = (
57
55
 
58
56
  const buildApiOptions = (args: StoryArgs): APIOptions => {
59
57
  return {
60
- satStyling: args.satStyling,
61
58
  crossOutEnabled: args.crossOutEnabled,
62
59
  };
63
60
  };
@@ -29,25 +29,20 @@ exports[`Definition widget should have a default snapshot: first render 1`] = `
29
29
  <div
30
30
  class="perseus-widget-container widget-nohighlight widget-inline"
31
31
  >
32
- <span
32
+ <button
33
33
  aria-controls="uid-popover-0-wb-id"
34
+ aria-disabled="false"
34
35
  aria-expanded="false"
35
- class="perseus-widget-definition"
36
+ class="button_vr44p2-o_O-reset_152ygtm-o_O-link_13xlah4"
36
37
  id="uid-popover-0-wb-id-anchor"
38
+ type="button"
37
39
  >
38
- <button
39
- aria-disabled="false"
40
- class="button_vr44p2-o_O-shared_lwskrm-o_O-default_1hl5pu8"
41
- role="button"
42
- type="button"
40
+ <span
41
+ style="color: rgb(24, 101, 242);"
43
42
  >
44
- <span
45
- class="text_f1191h-o_O-LabelLarge_5s82ln-o_O-text_m8a8ki-o_O-textWithFocus_e296pg"
46
- >
47
- the Pequots
48
- </span>
49
- </button>
50
- </span>
43
+ the Pequots
44
+ </span>
45
+ </button>
51
46
  </div>
52
47
  , upon these conditions.
53
48
  </div>
@@ -86,25 +81,20 @@ exports[`Definition widget should have an open state snapshot: open state 1`] =
86
81
  <div
87
82
  class="perseus-widget-container widget-nohighlight widget-inline"
88
83
  >
89
- <span
84
+ <button
90
85
  aria-controls="uid-popover-1-wb-id"
86
+ aria-disabled="false"
91
87
  aria-expanded="true"
92
- class="perseus-widget-definition"
88
+ class="button_vr44p2-o_O-reset_152ygtm-o_O-link_13xlah4"
93
89
  id="uid-popover-1-wb-id-anchor"
90
+ type="button"
94
91
  >
95
- <button
96
- aria-disabled="false"
97
- class="button_vr44p2-o_O-shared_lwskrm-o_O-default_1hl5pu8"
98
- role="button"
99
- type="button"
92
+ <span
93
+ style="color: rgb(24, 101, 242); border-bottom: 2px solid #1865f2;"
100
94
  >
101
- <span
102
- class="text_f1191h-o_O-LabelLarge_5s82ln-o_O-text_m8a8ki-o_O-textWithFocus_e296pg-o_O-focus_15mc0l2"
103
- >
104
- the Pequots
105
- </span>
106
- </button>
107
- </span>
95
+ the Pequots
96
+ </span>
97
+ </button>
108
98
  </div>
109
99
  , upon these conditions.
110
100
  </div>
@@ -58,15 +58,9 @@ exports[`group widget should snapshot: initial render 1`] = `
58
58
  <div
59
59
  class="perseus-column"
60
60
  >
61
- <div
62
- class="sat-header-grafting-area"
63
- />
64
61
  <div
65
62
  class="perseus-column-content"
66
63
  >
67
- <div
68
- class="sat-skill-subscore-grafting-area"
69
- />
70
64
  <div
71
65
  class="paragraph"
72
66
  >
@@ -1270,9 +1264,6 @@ exports[`group widget should snapshot: initial render 1`] = `
1270
1264
  </div>
1271
1265
  </div>
1272
1266
  </div>
1273
- <div
1274
- class="sat-grafting-area"
1275
- />
1276
1267
  </div>
1277
1268
  </div>
1278
1269
  </div>
@@ -117,15 +117,9 @@ exports[`image widget - isMobile %b should snapshot: first render 1`] = `
117
117
  <div
118
118
  class="perseus-column"
119
119
  >
120
- <div
121
- class="sat-header-grafting-area"
122
- />
123
120
  <div
124
121
  class="perseus-column-content"
125
122
  >
126
- <div
127
- class="sat-skill-subscore-grafting-area"
128
- />
129
123
  <div
130
124
  class="paragraph"
131
125
  >
@@ -191,9 +185,6 @@ exports[`image widget - isMobile %b should snapshot: first render 1`] = `
191
185
  </span>
192
186
  ?
193
187
  </div>
194
- <div
195
- class="sat-grafting-area"
196
- />
197
188
  </div>
198
189
  </div>
199
190
  </div>
@@ -335,15 +326,9 @@ exports[`image widget - isMobile %b should snapshot: first render 2`] = `
335
326
  <div
336
327
  class="perseus-column"
337
328
  >
338
- <div
339
- class="sat-header-grafting-area"
340
- />
341
329
  <div
342
330
  class="perseus-column-content"
343
331
  >
344
- <div
345
- class="sat-skill-subscore-grafting-area"
346
- />
347
332
  <div
348
333
  class="paragraph"
349
334
  >
@@ -409,9 +394,6 @@ exports[`image widget - isMobile %b should snapshot: first render 2`] = `
409
394
  </span>
410
395
  ?
411
396
  </div>
412
- <div
413
- class="sat-grafting-area"
414
- />
415
397
  </div>
416
398
  </div>
417
399
  </div>