@khanacademy/perseus-editor 0.0.1 → 0.1.2

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 (127) hide show
  1. package/.babelrc.js +1 -1
  2. package/CHANGELOG.md +26 -0
  3. package/dist/es/index.css +1020 -0
  4. package/dist/es/index.js +9 -1
  5. package/dist/es/index.js.map +1 -1
  6. package/dist/index.css +1020 -0
  7. package/dist/index.js +9 -1
  8. package/dist/index.js.map +1 -1
  9. package/dist/strings.js +6 -1
  10. package/package.json +16 -4
  11. package/src/README.md +7 -0
  12. package/src/__stories__/editor.stories.js +33 -0
  13. package/src/__stories__/section-control-button.stories.jsx +27 -0
  14. package/src/__testdata__/input-number_testdata.js +28 -0
  15. package/src/__tests__/editor_test.jsx +123 -0
  16. package/src/__tests__/i18n_test.jsx +585 -0
  17. package/src/__tests__/traversal_test.jsx +378 -0
  18. package/src/all-editors.js +85 -0
  19. package/src/all-editors_test.js +17 -0
  20. package/src/all-widgets.js +10 -0
  21. package/src/article-editor.jsx +437 -0
  22. package/src/components/__stories__/blur-input.stories.jsx +24 -0
  23. package/src/components/blur-input.jsx +62 -0
  24. package/src/components/checkbox.jsx +194 -0
  25. package/src/components/device-framer.jsx +91 -0
  26. package/src/components/drag-target.jsx +88 -0
  27. package/src/components/dropdown-option.jsx +318 -0
  28. package/src/components/form-wrapped-text-field.jsx +248 -0
  29. package/src/components/graph-settings.jsx +631 -0
  30. package/src/components/hover-behavior.jsx +178 -0
  31. package/src/components/json-editor.jsx +121 -0
  32. package/src/components/link.jsx +173 -0
  33. package/src/components/simple-button.jsx +86 -0
  34. package/src/components/sortable.jsx +186 -0
  35. package/src/components/util.js +39 -0
  36. package/src/components/viewport-resizer.jsx +73 -0
  37. package/src/diffs/__stories__/perseus-diff-wrapper.jsx +8 -0
  38. package/src/diffs/__stories__/structured-item-diff.stories.jsx +855 -0
  39. package/src/diffs/__stories__/tags-diff.stories.jsx +38 -0
  40. package/src/diffs/__stories__/text-diff.stories.jsx +37 -0
  41. package/src/diffs/__tests__/split-diff_test.js +34 -0
  42. package/src/diffs/__tests__/string-array-diff_test.js +74 -0
  43. package/src/diffs/__tests__/structured-item-diff_test.js +432 -0
  44. package/src/diffs/__tests__/widget-diff-performer_test.js +44 -0
  45. package/src/diffs/article-diff.jsx +70 -0
  46. package/src/diffs/item-diff.jsx +77 -0
  47. package/src/diffs/renderer-diff.jsx +143 -0
  48. package/src/diffs/split-diff.jsx +30 -0
  49. package/src/diffs/string-array-diff.jsx +75 -0
  50. package/src/diffs/structured-item-diff.jsx +269 -0
  51. package/src/diffs/tags-diff.jsx +50 -0
  52. package/src/diffs/text-diff.jsx +194 -0
  53. package/src/diffs/widget-diff-performer.jsx +74 -0
  54. package/src/diffs/widget-diff.jsx +291 -0
  55. package/src/editor-page.jsx +351 -0
  56. package/src/editor.jsx +1364 -0
  57. package/src/hint-editor.jsx +447 -0
  58. package/src/i18n.jsx +139 -0
  59. package/src/iframe-content-renderer.jsx +201 -0
  60. package/src/index.js +27 -8
  61. package/src/item-editor.jsx +159 -0
  62. package/src/item-extras-editor.jsx +150 -0
  63. package/src/katex-error-view.jsx +87 -0
  64. package/src/multirenderer-editor.jsx +1074 -0
  65. package/src/section-control-button.jsx +53 -0
  66. package/src/stateful-article-editor.jsx +176 -0
  67. package/src/stateful-editor-page.jsx +90 -0
  68. package/src/styles/perseus-editor.less +1339 -0
  69. package/src/testing-widgets.js +12 -0
  70. package/src/util/register-all-widgets-and-editors-for-testing.js +15 -0
  71. package/src/util/register-all-widgets-and-editors-for-testing_test.js +18 -0
  72. package/src/widgets/__stories__/label-image-editor.stories.jsx +97 -0
  73. package/src/widgets/categorizer-editor.jsx +103 -0
  74. package/src/widgets/cs-program-editor.jsx +258 -0
  75. package/src/widgets/definition-editor.jsx +75 -0
  76. package/src/widgets/dropdown-editor.jsx +201 -0
  77. package/src/widgets/example-graphie-widget-editor.jsx +70 -0
  78. package/src/widgets/example-graphie-widget.jsx +175 -0
  79. package/src/widgets/example-widget-editor.jsx +60 -0
  80. package/src/widgets/example-widget.jsx +153 -0
  81. package/src/widgets/explanation-editor.jsx +89 -0
  82. package/src/widgets/expression-editor.jsx +560 -0
  83. package/src/widgets/graded-group-editor.jsx +162 -0
  84. package/src/widgets/graded-group-set-editor.jsx +101 -0
  85. package/src/widgets/grapher-editor.jsx +154 -0
  86. package/src/widgets/group-editor.jsx +83 -0
  87. package/src/widgets/iframe-editor.jsx +200 -0
  88. package/src/widgets/image-editor.jsx +326 -0
  89. package/src/widgets/input-number-editor.jsx +269 -0
  90. package/src/widgets/interaction/constraint-editor.jsx +147 -0
  91. package/src/widgets/interaction-editor.jsx +1389 -0
  92. package/src/widgets/interactive-graph-editor.jsx +322 -0
  93. package/src/widgets/label-image/__stories__/answer-choices.stories.jsx +81 -0
  94. package/src/widgets/label-image/__stories__/behavior.stories.jsx +32 -0
  95. package/src/widgets/label-image/__stories__/marker.stories.jsx +76 -0
  96. package/src/widgets/label-image/__stories__/question-markers.stories.jsx +106 -0
  97. package/src/widgets/label-image/__stories__/select-image.stories.jsx +60 -0
  98. package/src/widgets/label-image/answer-choices.jsx +231 -0
  99. package/src/widgets/label-image/behavior.jsx +92 -0
  100. package/src/widgets/label-image/marker.jsx +292 -0
  101. package/src/widgets/label-image/question-markers.jsx +181 -0
  102. package/src/widgets/label-image/select-image.jsx +86 -0
  103. package/src/widgets/label-image-editor.jsx +257 -0
  104. package/src/widgets/lights-puzzle-editor.jsx +267 -0
  105. package/src/widgets/matcher-editor.jsx +147 -0
  106. package/src/widgets/matrix-editor.jsx +155 -0
  107. package/src/widgets/measurer-editor.jsx +245 -0
  108. package/src/widgets/molecule-editor.jsx +63 -0
  109. package/src/widgets/number-line-editor.jsx +498 -0
  110. package/src/widgets/numeric-input-editor.jsx +554 -0
  111. package/src/widgets/orderer-editor.jsx +166 -0
  112. package/src/widgets/passage-editor.jsx +115 -0
  113. package/src/widgets/passage-ref-editor.jsx +77 -0
  114. package/src/widgets/passage-ref-target-editor.jsx +47 -0
  115. package/src/widgets/plotter-editor.jsx +537 -0
  116. package/src/widgets/radio/editor.jsx +398 -0
  117. package/src/widgets/reaction-diagram-editor.jsx +127 -0
  118. package/src/widgets/sequence-editor.jsx +205 -0
  119. package/src/widgets/simple-markdown-tester-editor.jsx +84 -0
  120. package/src/widgets/simple-markdown-tester.jsx +91 -0
  121. package/src/widgets/simulator-editor.jsx +144 -0
  122. package/src/widgets/sorter-editor.jsx +100 -0
  123. package/src/widgets/table-editor.jsx +164 -0
  124. package/src/widgets/transformer-editor.jsx +1006 -0
  125. package/src/widgets/unit-editor.jsx +293 -0
  126. package/src/widgets/video-editor.jsx +74 -0
  127. package/src/__tests__/index.test.js +0 -15
@@ -0,0 +1,248 @@
1
+ // @flow
2
+ /**
3
+ * DEPRECATED: Use <TextField> from ./text-field.jsx instead.
4
+ *
5
+ * This component wraps an <input> in a <form> to make it easier to add an
6
+ * `onSubmit` handler. In practice though this can complicate things because
7
+ * each field is in it's own form which is not how forms should be structured.
8
+ * If you need to handle `onSubmit`, please use <TextField> directly with your
9
+ * own <form> that wraps all text fields in the form.
10
+ **/
11
+ import {globalStyles, components} from "@khanacademy/perseus";
12
+ import Color from "@khanacademy/wonder-blocks-color";
13
+ import {StyleSheet, css} from "aphrodite";
14
+ import * as React from "react";
15
+
16
+ import type {StyleType} from "@khanacademy/wonder-blocks-core";
17
+
18
+ type Props = {|
19
+ // This id is used to tie the input field to the label that describes it.
20
+ // TODO(diedra): Instead of passing in this id to connect the label and input
21
+ // field, we should pass in the label for the input field and place it
22
+ // inside the <form>.
23
+ id?: string,
24
+ testId?: string,
25
+ type?: string,
26
+ name?: string,
27
+ readOnly?: boolean,
28
+ value?: ?string,
29
+ placeholder?: string,
30
+ // https://reactjs.org/docs/uncontrolled-components.html#default-values
31
+ defaultValue?: ?string,
32
+ disabled?: boolean,
33
+ autoFocus?: boolean,
34
+ maxLength?: number,
35
+ invalid?: "true" | "false",
36
+
37
+ // styling
38
+ // This prop is passed directly to <input>. This is incorrect since HTML
39
+ // tags don't know what to do with an aphrodite which is typed as:
40
+ // {
41
+ // _len: number,
42
+ // _name: string,
43
+ // _definition: CSSProperties,
44
+ // }
45
+ // TODO(WB-1026): Update StyleType to reflect the aphrodite type
46
+ // TODO(FEI-3282): Update uses of StyleType in webapp to be correct
47
+ style?: StyleType,
48
+ className?: string,
49
+ width?: number | string,
50
+ grow?: boolean | number,
51
+ shrink?: boolean | number,
52
+ // HACK(mattmorgan) to enforce WB LabelMedium-like styles on this older
53
+ // component.
54
+ labelMediumInputText?: boolean,
55
+ icon?: React.Element<typeof components.Icon>,
56
+ leftSideIcon?: boolean,
57
+ backgroundColor?: string,
58
+ focusBorderColor?: string,
59
+ borderColor?: string,
60
+ color?: string,
61
+
62
+ // events
63
+ onSubmit?: (SyntheticInputEvent<HTMLInputElement>) => mixed,
64
+ onBlur?: (SyntheticInputEvent<HTMLInputElement>) => mixed,
65
+ onFocus?: (SyntheticInputEvent<HTMLInputElement>) => mixed,
66
+ onChange?: (SyntheticInputEvent<HTMLInputElement>) => mixed,
67
+ onClick?: (SyntheticMouseEvent<HTMLInputElement>) => mixed,
68
+ onKeyPress?: (SyntheticKeyboardEvent<HTMLInputElement>) => mixed,
69
+ onKeyDown?: (SyntheticKeyboardEvent<HTMLInputElement>) => mixed,
70
+
71
+ // aria
72
+ "aria-label"?: string,
73
+ "aria-describedby"?: ?string,
74
+ |};
75
+
76
+ type State = {|
77
+ focused: boolean,
78
+ |};
79
+
80
+ type PropsWithForwardRef = {|
81
+ ...Props,
82
+ forwardedRef: React.Ref<"input">,
83
+ |};
84
+
85
+ class FormWrappedTextField extends React.Component<PropsWithForwardRef, State> {
86
+ state = {
87
+ focused: false,
88
+ };
89
+
90
+ handleBlur = (e: SyntheticInputEvent<HTMLInputElement>) => {
91
+ const {onBlur} = this.props;
92
+ onBlur && onBlur(e);
93
+
94
+ this.setState({focused: false});
95
+ };
96
+
97
+ handleFocus = (e: SyntheticInputEvent<HTMLInputElement>) => {
98
+ const {onFocus} = this.props;
99
+ onFocus && onFocus(e);
100
+
101
+ this.setState({focused: true});
102
+ };
103
+
104
+ disableDefault = (e: Event) => {
105
+ e.preventDefault();
106
+ };
107
+
108
+ render() {
109
+ const {
110
+ forwardedRef,
111
+ width,
112
+ grow,
113
+ shrink,
114
+ icon,
115
+ backgroundColor,
116
+ focusBorderColor,
117
+ borderColor,
118
+ color,
119
+ onSubmit,
120
+ leftSideIcon,
121
+ id,
122
+ testId,
123
+ type,
124
+ labelMediumInputText,
125
+ ...allProps
126
+ } = this.props;
127
+ const {focused} = this.state;
128
+
129
+ const extraStyles: any = {};
130
+ const spanStyle = [styles.input, styles.container];
131
+
132
+ if (width) {
133
+ extraStyles.width = width;
134
+ }
135
+
136
+ if (grow) {
137
+ extraStyles.flexGrow = grow === true ? 1 : grow;
138
+ }
139
+
140
+ if (shrink || shrink === 0) {
141
+ extraStyles.flexShrink = shrink === true ? 0 : shrink;
142
+ }
143
+
144
+ if (backgroundColor) {
145
+ extraStyles.backgroundColor = backgroundColor;
146
+ } else {
147
+ spanStyle.push(styles.defaultBackground);
148
+ }
149
+
150
+ // Add text color if specified.
151
+ if (color) {
152
+ extraStyles.color = color;
153
+ }
154
+
155
+ const borderColorStyle = focused
156
+ ? focusBorderColor || Color.blue
157
+ : borderColor || Color.offBlack16;
158
+ extraStyles.border = `1px solid ${borderColorStyle}`;
159
+
160
+ const wrappedIcon = icon && (
161
+ <span className={css(styles.icon)}>{icon}</span>
162
+ );
163
+
164
+ const inputBase = labelMediumInputText
165
+ ? styles.labelMediumInputBase
166
+ : styles.inputBase;
167
+
168
+ // TODO(diedra): The label for the input field should be here inside of
169
+ // the form.
170
+ return (
171
+ <form
172
+ className={css(spanStyle)}
173
+ style={extraStyles}
174
+ onSubmit={onSubmit || this.disableDefault}
175
+ >
176
+ {leftSideIcon && wrappedIcon}
177
+ <input
178
+ {...allProps}
179
+ onFocus={this.handleFocus}
180
+ onBlur={this.handleBlur}
181
+ type={type}
182
+ className={css(inputBase)}
183
+ ref={forwardedRef}
184
+ id={id}
185
+ data-test-id={testId}
186
+ />
187
+ {!leftSideIcon && wrappedIcon}
188
+ </form>
189
+ );
190
+ }
191
+ }
192
+
193
+ const styles = StyleSheet.create({
194
+ inputBase: {
195
+ background: "inherit",
196
+ border: "none",
197
+ ...globalStyles.typography.bodyXsmall,
198
+ outline: "none",
199
+ "::placeholder": {
200
+ color: globalStyles.colors.gray41,
201
+ },
202
+ width: "100%",
203
+ color: "inherit",
204
+ marginBottom: 0,
205
+ paddingLeft: 0,
206
+ boxShadow: "none",
207
+ padding: 0, // override Chrome's stylesheet
208
+ margin: 0, // override Safari's stylesheet
209
+ },
210
+ // HACK(mattmorgan) to enforce WB LabelMedium-like styles on this older
211
+ // component.
212
+ labelMediumInputBase: {
213
+ background: "inherit",
214
+ border: "none",
215
+ outline: "none",
216
+ "::placeholder": {
217
+ color: globalStyles.colors.gray41,
218
+ },
219
+ width: "100%",
220
+ fontWeight: "normal",
221
+ fontFamily: "Lato, san-serif",
222
+ fontSize: "16px",
223
+ lineHeight: "20px",
224
+ },
225
+ input: {
226
+ height: 40,
227
+ borderRadius: globalStyles.borderRadius,
228
+ boxSizing: "border-box",
229
+ padding: "8px 10px",
230
+ },
231
+ container: {
232
+ display: "inline-flex",
233
+ alignItems: "center",
234
+ marginBottom: 0,
235
+ },
236
+ defaultBackground: {
237
+ backgroundColor: globalStyles.colors.white,
238
+ },
239
+ icon: {
240
+ display: "flex",
241
+ alignItems: "center",
242
+ justifyContent: "center",
243
+ },
244
+ });
245
+
246
+ export default (React.forwardRef<Props, HTMLInputElement>((props, ref) => (
247
+ <FormWrappedTextField {...props} forwardedRef={ref} />
248
+ )): React$AbstractComponent<Props, HTMLInputElement>);