@pie-lib/editable-html-tip-tap 1.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 (167) hide show
  1. package/CHANGELOG.json +32 -0
  2. package/CHANGELOG.md +2280 -0
  3. package/lib/__tests__/editor.test.js +470 -0
  4. package/lib/__tests__/serialization.test.js +246 -0
  5. package/lib/__tests__/utils.js +106 -0
  6. package/lib/block-tags.js +25 -0
  7. package/lib/constants.js +16 -0
  8. package/lib/editor.js +1356 -0
  9. package/lib/extensions/MediaView.js +112 -0
  10. package/lib/extensions/characters.js +65 -0
  11. package/lib/extensions/component.js +325 -0
  12. package/lib/extensions/css.js +252 -0
  13. package/lib/extensions/custom-toolbar-wrapper.js +124 -0
  14. package/lib/extensions/image.js +106 -0
  15. package/lib/extensions/math.js +330 -0
  16. package/lib/extensions/media.js +276 -0
  17. package/lib/extensions/responseArea.js +278 -0
  18. package/lib/index.js +1213 -0
  19. package/lib/old-index.js +269 -0
  20. package/lib/parse-html.js +16 -0
  21. package/lib/plugins/characters/custom-popper.js +73 -0
  22. package/lib/plugins/characters/index.js +305 -0
  23. package/lib/plugins/characters/utils.js +381 -0
  24. package/lib/plugins/css/icons/index.js +37 -0
  25. package/lib/plugins/css/index.js +390 -0
  26. package/lib/plugins/customPlugin/index.js +114 -0
  27. package/lib/plugins/html/icons/index.js +38 -0
  28. package/lib/plugins/html/index.js +81 -0
  29. package/lib/plugins/image/__tests__/component.test.js +51 -0
  30. package/lib/plugins/image/__tests__/image-toolbar-logic.test.js +56 -0
  31. package/lib/plugins/image/__tests__/image-toolbar.test.js +26 -0
  32. package/lib/plugins/image/__tests__/index.test.js +98 -0
  33. package/lib/plugins/image/__tests__/insert-image-handler.test.js +125 -0
  34. package/lib/plugins/image/__tests__/mock-change.js +25 -0
  35. package/lib/plugins/image/alt-dialog.js +129 -0
  36. package/lib/plugins/image/component.js +419 -0
  37. package/lib/plugins/image/image-toolbar.js +177 -0
  38. package/lib/plugins/image/index.js +263 -0
  39. package/lib/plugins/image/insert-image-handler.js +117 -0
  40. package/lib/plugins/index.js +413 -0
  41. package/lib/plugins/list/__tests__/index.test.js +79 -0
  42. package/lib/plugins/list/index.js +334 -0
  43. package/lib/plugins/math/__tests__/index.test.js +300 -0
  44. package/lib/plugins/math/index.js +454 -0
  45. package/lib/plugins/media/__tests__/index.test.js +71 -0
  46. package/lib/plugins/media/index.js +387 -0
  47. package/lib/plugins/media/media-dialog.js +709 -0
  48. package/lib/plugins/media/media-toolbar.js +101 -0
  49. package/lib/plugins/media/media-wrapper.js +93 -0
  50. package/lib/plugins/rendering/index.js +46 -0
  51. package/lib/plugins/respArea/drag-in-the-blank/choice.js +289 -0
  52. package/lib/plugins/respArea/drag-in-the-blank/index.js +94 -0
  53. package/lib/plugins/respArea/explicit-constructed-response/index.js +120 -0
  54. package/lib/plugins/respArea/icons/index.js +95 -0
  55. package/lib/plugins/respArea/index.js +341 -0
  56. package/lib/plugins/respArea/inline-dropdown/index.js +126 -0
  57. package/lib/plugins/respArea/math-templated/index.js +130 -0
  58. package/lib/plugins/respArea/utils.js +125 -0
  59. package/lib/plugins/table/CustomTablePlugin.js +133 -0
  60. package/lib/plugins/table/__tests__/index.test.js +442 -0
  61. package/lib/plugins/table/__tests__/table-toolbar.test.js +54 -0
  62. package/lib/plugins/table/icons/index.js +69 -0
  63. package/lib/plugins/table/index.js +483 -0
  64. package/lib/plugins/table/table-toolbar.js +187 -0
  65. package/lib/plugins/textAlign/icons/index.js +194 -0
  66. package/lib/plugins/textAlign/index.js +34 -0
  67. package/lib/plugins/toolbar/__tests__/default-toolbar.test.js +128 -0
  68. package/lib/plugins/toolbar/__tests__/editor-and-toolbar.test.js +51 -0
  69. package/lib/plugins/toolbar/__tests__/toolbar-buttons.test.js +54 -0
  70. package/lib/plugins/toolbar/__tests__/toolbar.test.js +120 -0
  71. package/lib/plugins/toolbar/default-toolbar.js +229 -0
  72. package/lib/plugins/toolbar/done-button.js +53 -0
  73. package/lib/plugins/toolbar/editor-and-toolbar.js +286 -0
  74. package/lib/plugins/toolbar/index.js +34 -0
  75. package/lib/plugins/toolbar/toolbar-buttons.js +194 -0
  76. package/lib/plugins/toolbar/toolbar.js +376 -0
  77. package/lib/plugins/utils.js +62 -0
  78. package/lib/serialization.js +677 -0
  79. package/lib/shared/alert-dialog.js +75 -0
  80. package/lib/theme.js +9 -0
  81. package/package.json +69 -0
  82. package/src/__tests__/editor.test.jsx +363 -0
  83. package/src/__tests__/serialization.test.js +291 -0
  84. package/src/__tests__/utils.js +36 -0
  85. package/src/block-tags.js +17 -0
  86. package/src/constants.js +7 -0
  87. package/src/editor.jsx +1197 -0
  88. package/src/extensions/characters.js +46 -0
  89. package/src/extensions/component.jsx +294 -0
  90. package/src/extensions/css.js +217 -0
  91. package/src/extensions/custom-toolbar-wrapper.jsx +100 -0
  92. package/src/extensions/image.js +55 -0
  93. package/src/extensions/math.js +259 -0
  94. package/src/extensions/media.js +182 -0
  95. package/src/extensions/responseArea.js +205 -0
  96. package/src/index.jsx +1462 -0
  97. package/src/old-index.jsx +162 -0
  98. package/src/parse-html.js +8 -0
  99. package/src/plugins/README.md +27 -0
  100. package/src/plugins/characters/custom-popper.js +48 -0
  101. package/src/plugins/characters/index.jsx +284 -0
  102. package/src/plugins/characters/utils.js +447 -0
  103. package/src/plugins/css/icons/index.jsx +17 -0
  104. package/src/plugins/css/index.jsx +340 -0
  105. package/src/plugins/customPlugin/index.jsx +85 -0
  106. package/src/plugins/html/icons/index.jsx +19 -0
  107. package/src/plugins/html/index.jsx +72 -0
  108. package/src/plugins/image/__tests__/__snapshots__/component.test.jsx.snap +51 -0
  109. package/src/plugins/image/__tests__/__snapshots__/image-toolbar-logic.test.jsx.snap +27 -0
  110. package/src/plugins/image/__tests__/__snapshots__/image-toolbar.test.jsx.snap +44 -0
  111. package/src/plugins/image/__tests__/component.test.jsx +41 -0
  112. package/src/plugins/image/__tests__/image-toolbar-logic.test.jsx +42 -0
  113. package/src/plugins/image/__tests__/image-toolbar.test.jsx +11 -0
  114. package/src/plugins/image/__tests__/index.test.js +95 -0
  115. package/src/plugins/image/__tests__/insert-image-handler.test.js +113 -0
  116. package/src/plugins/image/__tests__/mock-change.js +15 -0
  117. package/src/plugins/image/alt-dialog.jsx +82 -0
  118. package/src/plugins/image/component.jsx +343 -0
  119. package/src/plugins/image/image-toolbar.jsx +100 -0
  120. package/src/plugins/image/index.jsx +227 -0
  121. package/src/plugins/image/insert-image-handler.js +79 -0
  122. package/src/plugins/index.jsx +377 -0
  123. package/src/plugins/list/__tests__/index.test.js +54 -0
  124. package/src/plugins/list/index.jsx +305 -0
  125. package/src/plugins/math/__tests__/__snapshots__/index.test.jsx.snap +48 -0
  126. package/src/plugins/math/__tests__/index.test.jsx +245 -0
  127. package/src/plugins/math/index.jsx +379 -0
  128. package/src/plugins/media/__tests__/index.test.js +75 -0
  129. package/src/plugins/media/index.jsx +325 -0
  130. package/src/plugins/media/media-dialog.js +624 -0
  131. package/src/plugins/media/media-toolbar.jsx +56 -0
  132. package/src/plugins/media/media-wrapper.jsx +43 -0
  133. package/src/plugins/rendering/index.js +31 -0
  134. package/src/plugins/respArea/drag-in-the-blank/choice.jsx +215 -0
  135. package/src/plugins/respArea/drag-in-the-blank/index.jsx +70 -0
  136. package/src/plugins/respArea/explicit-constructed-response/index.jsx +92 -0
  137. package/src/plugins/respArea/icons/index.jsx +71 -0
  138. package/src/plugins/respArea/index.jsx +299 -0
  139. package/src/plugins/respArea/inline-dropdown/index.jsx +108 -0
  140. package/src/plugins/respArea/math-templated/index.jsx +104 -0
  141. package/src/plugins/respArea/utils.jsx +90 -0
  142. package/src/plugins/table/CustomTablePlugin.js +113 -0
  143. package/src/plugins/table/__tests__/__snapshots__/table-toolbar.test.jsx.snap +44 -0
  144. package/src/plugins/table/__tests__/index.test.jsx +401 -0
  145. package/src/plugins/table/__tests__/table-toolbar.test.jsx +42 -0
  146. package/src/plugins/table/icons/index.jsx +53 -0
  147. package/src/plugins/table/index.jsx +427 -0
  148. package/src/plugins/table/table-toolbar.jsx +136 -0
  149. package/src/plugins/textAlign/icons/index.jsx +114 -0
  150. package/src/plugins/textAlign/index.jsx +23 -0
  151. package/src/plugins/toolbar/__tests__/__snapshots__/default-toolbar.test.jsx.snap +923 -0
  152. package/src/plugins/toolbar/__tests__/__snapshots__/editor-and-toolbar.test.jsx.snap +20 -0
  153. package/src/plugins/toolbar/__tests__/__snapshots__/toolbar-buttons.test.jsx.snap +36 -0
  154. package/src/plugins/toolbar/__tests__/__snapshots__/toolbar.test.jsx.snap +46 -0
  155. package/src/plugins/toolbar/__tests__/default-toolbar.test.jsx +94 -0
  156. package/src/plugins/toolbar/__tests__/editor-and-toolbar.test.jsx +37 -0
  157. package/src/plugins/toolbar/__tests__/toolbar-buttons.test.jsx +51 -0
  158. package/src/plugins/toolbar/__tests__/toolbar.test.jsx +106 -0
  159. package/src/plugins/toolbar/default-toolbar.jsx +206 -0
  160. package/src/plugins/toolbar/done-button.jsx +38 -0
  161. package/src/plugins/toolbar/editor-and-toolbar.jsx +257 -0
  162. package/src/plugins/toolbar/index.jsx +23 -0
  163. package/src/plugins/toolbar/toolbar-buttons.jsx +138 -0
  164. package/src/plugins/toolbar/toolbar.jsx +338 -0
  165. package/src/plugins/utils.js +31 -0
  166. package/src/serialization.jsx +621 -0
  167. package/src/theme.js +1 -0
@@ -0,0 +1,257 @@
1
+ import React from 'react';
2
+ import Toolbar from './toolbar';
3
+ import classNames from 'classnames';
4
+ import debug from 'debug';
5
+ import { primary } from '../../theme';
6
+ import { withStyles } from '@material-ui/core/styles';
7
+ import PropTypes from 'prop-types';
8
+ import SlatePropTypes from 'slate-prop-types';
9
+ import { color } from '@pie-lib/render-ui';
10
+
11
+ const log = debug('@pie-lib:editable-html:plugins:toolbar:editor-and-toolbar');
12
+
13
+ export class EditorAndToolbar extends React.Component {
14
+ static propTypes = {
15
+ children: PropTypes.oneOfType([PropTypes.arrayOf(PropTypes.node), PropTypes.node]).isRequired,
16
+ value: SlatePropTypes.value.isRequired,
17
+ plugins: PropTypes.array.isRequired,
18
+ onChange: PropTypes.func.isRequired,
19
+ getFocusedValue: PropTypes.func.isRequired,
20
+ onDone: PropTypes.func.isRequired,
21
+ onDataChange: PropTypes.func,
22
+ toolbarRef: PropTypes.func,
23
+ focusedNode: SlatePropTypes.node,
24
+ readOnly: PropTypes.bool,
25
+ disableScrollbar: PropTypes.bool,
26
+ disableUnderline: PropTypes.bool,
27
+ autoWidth: PropTypes.bool,
28
+ classes: PropTypes.object.isRequired,
29
+ pluginProps: PropTypes.object,
30
+ toolbarOpts: PropTypes.shape({
31
+ position: PropTypes.oneOf(['bottom', 'top']),
32
+ alwaysVisible: PropTypes.bool,
33
+ error: PropTypes.string,
34
+ noBorder: PropTypes.any,
35
+ noPadding: PropTypes.any,
36
+ }),
37
+ focusToolbar: PropTypes.bool.isRequired,
38
+ onToolbarFocus: PropTypes.func.isRequired,
39
+ onToolbarBlur: PropTypes.func.isRequired,
40
+ doneButtonRef: PropTypes.func,
41
+ };
42
+
43
+ render() {
44
+ const {
45
+ classes,
46
+ children,
47
+ value,
48
+ plugins,
49
+ onChange,
50
+ getFocusedValue,
51
+ onDone,
52
+ focusedNode,
53
+ autoWidth,
54
+ readOnly,
55
+ disableScrollbar,
56
+ disableUnderline,
57
+ pluginProps,
58
+ toolbarOpts,
59
+ onDataChange,
60
+ toolbarRef,
61
+ doneButtonRef,
62
+ focusToolbar,
63
+ onToolbarFocus,
64
+ onToolbarBlur,
65
+ } = this.props;
66
+
67
+ let inFocus = value.isFocused || (focusedNode !== null && focusedNode !== undefined) || focusToolbar;
68
+
69
+ const holderNames = classNames(classes.editorHolder, {
70
+ [classes.editorInFocus]: inFocus,
71
+ [classes.readOnly]: readOnly,
72
+ [classes.disabledUnderline]: disableUnderline,
73
+ [classes.disabledScrollbar]: disableScrollbar,
74
+ });
75
+
76
+ let clonedChildren = children;
77
+
78
+ if (typeof children !== 'string') {
79
+ clonedChildren = React.cloneElement(children, {
80
+ ref: (el) => (this.editorRef = el),
81
+ });
82
+ }
83
+
84
+ log('[render] inFocus: ', inFocus, 'value.isFocused:', value.isFocused, 'focused node: ', focusedNode);
85
+
86
+ return (
87
+ <div
88
+ className={classNames(
89
+ {
90
+ [classes.noBorder]: toolbarOpts && toolbarOpts.noBorder,
91
+ [classes.error]: toolbarOpts && toolbarOpts.error,
92
+ },
93
+ classes.root,
94
+ )}
95
+ >
96
+ <div className={holderNames}>
97
+ <div
98
+ className={classNames(
99
+ {
100
+ [classes.noPadding]: toolbarOpts && toolbarOpts.noPadding,
101
+ },
102
+ classes.children,
103
+ )}
104
+ >
105
+ {clonedChildren}
106
+ </div>
107
+ </div>
108
+
109
+ <Toolbar
110
+ autoWidth={autoWidth}
111
+ plugins={plugins}
112
+ focusedNode={focusedNode}
113
+ value={value}
114
+ isFocused={inFocus}
115
+ onBlur={onToolbarBlur}
116
+ onFocus={onToolbarFocus}
117
+ onChange={onChange}
118
+ getFocusedValue={getFocusedValue}
119
+ onDone={onDone}
120
+ onDataChange={onDataChange}
121
+ toolbarRef={toolbarRef}
122
+ doneButtonRef={doneButtonRef}
123
+ pluginProps={pluginProps}
124
+ toolbarOpts={toolbarOpts}
125
+ />
126
+ </div>
127
+ );
128
+ }
129
+ }
130
+
131
+ const style = (theme) => ({
132
+ root: {
133
+ position: 'relative',
134
+ padding: '0px',
135
+ border: '1px solid #ccc',
136
+ borderRadius: '4px',
137
+ cursor: 'text',
138
+ '& [data-slate-editor="true"]': {
139
+ wordBreak: 'break-word',
140
+ overflow: 'visible',
141
+ maxHeight: '500px',
142
+ // needed in order to be able to put the focus before a void element when it is the first one in the editor
143
+ padding: '5px',
144
+ },
145
+ },
146
+ children: {
147
+ padding: '10px 16px',
148
+ },
149
+ editorHolder: {
150
+ position: 'relative',
151
+ padding: '0px',
152
+ overflowY: 'auto',
153
+ color: color.text(),
154
+ backgroundColor: color.background(),
155
+ '&::before': {
156
+ left: '0',
157
+ right: '0',
158
+ bottom: '0',
159
+ height: '1px',
160
+ content: '""',
161
+ position: 'absolute',
162
+ transition: 'background-color 200ms cubic-bezier(0.4, 0, 0.2, 1) 0ms',
163
+ pointerEvents: 'none',
164
+ backgroundColor: 'rgba(0, 0, 0, 0.42)',
165
+ },
166
+ '&::after': {
167
+ left: '0',
168
+ right: '0',
169
+ bottom: '0',
170
+ height: '1px',
171
+ content: '""',
172
+ position: 'absolute',
173
+ transform: 'scaleX(0)',
174
+ transition: 'transform 200ms cubic-bezier(0.0, 0.0, 0.2, 1) 0ms, background-color 200ms linear',
175
+ backgroundColor: 'rgba(0, 0, 0, 0.42)',
176
+ },
177
+ '&:focus': {
178
+ '&::after': {
179
+ transform: 'scaleX(1)',
180
+ backgroundColor: primary,
181
+ height: '2px',
182
+ },
183
+ },
184
+ '&:hover': {
185
+ '&::after': {
186
+ transform: 'scaleX(1)',
187
+ backgroundColor: theme.palette.common.black,
188
+ height: '2px',
189
+ },
190
+ },
191
+ },
192
+ disabledUnderline: {
193
+ '&::before': {
194
+ display: 'none',
195
+ },
196
+ '&::after': {
197
+ display: 'none',
198
+ },
199
+ },
200
+ disabledScrollbar: {
201
+ '&::-webkit-scrollbar': {
202
+ display: 'none',
203
+ },
204
+ scrollbarWidth: 'none',
205
+ '-ms-overflow-style': 'none',
206
+ },
207
+ readOnly: {
208
+ '&::before': {
209
+ background: 'transparent',
210
+ backgroundSize: '5px 1px',
211
+ backgroundImage: 'linear-gradient(to right, rgba(0, 0, 0, 0.42) 33%, transparent 0%)',
212
+ backgroundRepeat: 'repeat-x',
213
+ backgroundPosition: 'left top',
214
+ },
215
+ '&::after': {
216
+ left: '0',
217
+ right: '0',
218
+ bottom: '0',
219
+ height: '1px',
220
+ content: '""',
221
+ position: 'absolute',
222
+ transform: 'scaleX(0)',
223
+ transition: 'transform 200ms cubic-bezier(0.0, 0.0, 0.2, 1) 0ms, background-color 0ms linear',
224
+ backgroundColor: 'rgba(0, 0, 0, 0)',
225
+ },
226
+ '&:hover': {
227
+ '&::after': {
228
+ transform: 'scaleX(0)',
229
+ backgroundColor: theme.palette.common.black,
230
+ height: '2px',
231
+ },
232
+ },
233
+ },
234
+ editorInFocus: {
235
+ '&::after': {
236
+ transform: 'scaleX(1)',
237
+ backgroundColor: primary,
238
+ height: '2px',
239
+ },
240
+ '&:hover': {
241
+ '&::after': {
242
+ backgroundColor: primary,
243
+ },
244
+ },
245
+ },
246
+ error: {
247
+ border: `2px solid ${theme.palette.error.main} !important`,
248
+ },
249
+ noBorder: {
250
+ border: 'none',
251
+ },
252
+ noPadding: {
253
+ padding: 0,
254
+ },
255
+ });
256
+
257
+ export default withStyles(style)(EditorAndToolbar);
@@ -0,0 +1,23 @@
1
+ import React from 'react';
2
+
3
+ import EditorAndToolbar from './editor-and-toolbar';
4
+
5
+ /**
6
+ * Adds a toolbar which is shown when the editor is focused.
7
+ * @param {*} opts
8
+ */
9
+ export default function ToolbarPlugin(opts) {
10
+ return {
11
+ /* eslint-disable-next-line */
12
+ renderEditor: (props) => (
13
+ <EditorAndToolbar
14
+ {...props}
15
+ mainEditorRef={opts.mainEditorRef}
16
+ disableScrollbar={opts.disableScrollbar}
17
+ disableUnderline={opts.disableUnderline}
18
+ autoWidth={opts.autoWidth}
19
+ onDone={opts.onDone}
20
+ />
21
+ ),
22
+ };
23
+ }
@@ -0,0 +1,138 @@
1
+ import React from 'react';
2
+ import debug from 'debug';
3
+ import { withStyles } from '@material-ui/core/styles';
4
+ import classNames from 'classnames';
5
+ import PropTypes from 'prop-types';
6
+
7
+ const styles = (theme) => ({
8
+ button: {
9
+ color: 'grey',
10
+ display: 'inline-flex',
11
+ padding: '2px',
12
+ background: 'none',
13
+ border: 'none',
14
+ cursor: 'pointer',
15
+ '&:hover': {
16
+ color: 'black',
17
+ },
18
+ '&:focus': {
19
+ outline: `2px solid ${theme.palette.grey[700]}`,
20
+ },
21
+ },
22
+ active: {
23
+ color: 'black',
24
+ },
25
+ disabled: {
26
+ opacity: 0.7,
27
+ cursor: 'not-allowed',
28
+ '& :hover': {
29
+ color: 'grey',
30
+ },
31
+ },
32
+ });
33
+
34
+ const log = debug('pie-elements:editable-html:raw-button');
35
+
36
+ export class RawButton extends React.Component {
37
+ static propTypes = {
38
+ onClick: PropTypes.func.isRequired,
39
+ classes: PropTypes.object.isRequired,
40
+ children: PropTypes.oneOfType([PropTypes.arrayOf(PropTypes.node), PropTypes.node]).isRequired,
41
+ active: PropTypes.bool,
42
+ disabled: PropTypes.bool,
43
+ extraStyles: PropTypes.object,
44
+ };
45
+
46
+ constructor(props) {
47
+ super(props);
48
+ }
49
+
50
+ onClick = (e) => {
51
+ log('[onClick]');
52
+ e.preventDefault();
53
+ const { onClick } = this.props;
54
+ onClick(e);
55
+ };
56
+
57
+ onKeyDown = (e) => {
58
+ if (e.key === 'Enter' || e.key === ' ') {
59
+ log('[onKeyDown]');
60
+ e.preventDefault();
61
+ const { onClick } = this.props;
62
+ onClick(e);
63
+ }
64
+ };
65
+
66
+ render() {
67
+ const { active, classes, children, disabled, extraStyles, ariaLabel } = this.props;
68
+
69
+ const names = classNames(classes.button, {
70
+ [classes.active]: active,
71
+ [classes.disabled]: disabled,
72
+ });
73
+
74
+ return (
75
+ <button
76
+ style={extraStyles}
77
+ className={names}
78
+ onMouseDown={this.onClick}
79
+ onKeyDown={this.onKeyDown}
80
+ disabled={disabled}
81
+ aria-label={ariaLabel}
82
+ aria-pressed={active}
83
+ tabIndex={0}
84
+ >
85
+ {children}
86
+ </button>
87
+ );
88
+ }
89
+ }
90
+
91
+ export const Button = withStyles(styles)(RawButton);
92
+
93
+ export class RawMarkButton extends React.Component {
94
+ static propTypes = {
95
+ onToggle: PropTypes.func.isRequired,
96
+ mark: PropTypes.string,
97
+ label: PropTypes.string.isRequired,
98
+ children: PropTypes.oneOfType([PropTypes.arrayOf(PropTypes.node), PropTypes.node]).isRequired,
99
+ classes: PropTypes.object.isRequired,
100
+ active: PropTypes.bool,
101
+ };
102
+
103
+ constructor(props) {
104
+ super(props);
105
+ }
106
+
107
+ onToggle = (e) => {
108
+ e.preventDefault();
109
+ this.props.onToggle(this.props.mark);
110
+ };
111
+
112
+ onKeyDown = (e) => {
113
+ if (e.key === 'Enter' || e.key === ' ') {
114
+ e.preventDefault();
115
+ this.props.onToggle(this.props.mark);
116
+ }
117
+ };
118
+
119
+ render() {
120
+ const { classes, children, active, label } = this.props;
121
+
122
+ const names = classNames(classes.button, active && classes.active);
123
+ return (
124
+ <button
125
+ className={names}
126
+ onMouseDown={this.onToggle}
127
+ aria-pressed={active}
128
+ onKeyDown={this.onKeyDown}
129
+ aria-label={label}
130
+ tabIndex={0}
131
+ >
132
+ {children}
133
+ </button>
134
+ );
135
+ }
136
+ }
137
+
138
+ export const MarkButton = withStyles(styles)(RawMarkButton);