@@ -6,7 +6,7 @@ import position from 'selection-position'
6
6
import initialState from './state.json'
7
7
8
8
/**
9
- * Mark renderers.
9
+ * Define a set of mark renderers.
10
10
*
11
11
* @type {Object }
12
12
*/
@@ -30,17 +30,27 @@ const MARKS = {
30
30
}
31
31
32
32
/**
33
- * The rich text example.
33
+ * The hovering menu example.
34
34
*
35
35
* @type {Component }
36
36
*/
37
37
38
38
class HoveringMenu extends React . Component {
39
39
40
+ /**
41
+ * Deserialize the raw initial state.
42
+ *
43
+ * @type {Object }
44
+ */
45
+
40
46
state = {
41
47
state : Raw . deserialize ( initialState )
42
48
} ;
43
49
50
+ /**
51
+ * On update, update the menu.
52
+ */
53
+
44
54
componentDidMount = ( ) => {
45
55
this . updateMenu ( )
46
56
}
@@ -49,6 +59,64 @@ class HoveringMenu extends React.Component {
49
59
this . updateMenu ( )
50
60
}
51
61
62
+ /**
63
+ * Check if the current selection has a mark with `type` in it.
64
+ *
65
+ * @param {String } type
66
+ * @return {Boolean }
67
+ */
68
+
69
+ hasMark = ( type ) => {
70
+ const { state } = this . state
71
+ return state . marks . some ( mark => mark . type == type )
72
+ }
73
+
74
+ /**
75
+ * On change, save the new state.
76
+ *
77
+ * @param {State } state
78
+ */
79
+
80
+ onChange = ( state ) => {
81
+ this . setState ( { state } )
82
+ }
83
+
84
+ /**
85
+ * When a mark button is clicked, toggle the current mark.
86
+ *
87
+ * @param {Event } e
88
+ * @param {String } type
89
+ */
90
+
91
+ onClickMark = ( e , type ) => {
92
+ e . preventDefault ( )
93
+ const isActive = this . hasMark ( type )
94
+ let { state } = this . state
95
+
96
+ state = state
97
+ . transform ( )
98
+ [ isActive ? 'unmark' : 'mark' ] ( type )
99
+ . apply ( )
100
+
101
+ this . setState ( { state } )
102
+ }
103
+
104
+ /**
105
+ * When the portal opens, cache the menu element.
106
+ *
107
+ * @param {Element } portal
108
+ */
109
+
110
+ onOpen = ( portal ) => {
111
+ this . setState ( { menu : portal . firstChild } )
112
+ }
113
+
114
+ /**
115
+ * Render.
116
+ *
117
+ * @return {Element }
118
+ */
119
+
52
120
render = ( ) => {
53
121
return (
54
122
< div >
@@ -58,6 +126,12 @@ class HoveringMenu extends React.Component {
58
126
)
59
127
}
60
128
129
+ /**
130
+ * Render the hovering menu.
131
+ *
132
+ * @return {Element }
133
+ */
134
+
61
135
renderMenu = ( ) => {
62
136
const { state } = this . state
63
137
const isOpen = state . isExpanded && state . isFocused
@@ -73,6 +147,14 @@ class HoveringMenu extends React.Component {
73
147
)
74
148
}
75
149
150
+ /**
151
+ * Render a mark-toggling toolbar button.
152
+ *
153
+ * @param {String } type
154
+ * @param {String } icon
155
+ * @return {Element }
156
+ */
157
+
76
158
renderMarkButton = ( type , icon ) => {
77
159
const isActive = this . hasMark ( type )
78
160
const onMouseDown = e => this . onClickMark ( e , type )
@@ -84,6 +166,12 @@ class HoveringMenu extends React.Component {
84
166
)
85
167
}
86
168
169
+ /**
170
+ * Render the Slate editor.
171
+ *
172
+ * @return {Element }
173
+ */
174
+
87
175
renderEditor = ( ) => {
88
176
return (
89
177
< div className = "editor" >
@@ -96,10 +184,21 @@ class HoveringMenu extends React.Component {
96
184
)
97
185
}
98
186
187
+ /**
188
+ * Return a mark renderer for a Slate `mark`.
189
+ *
190
+ * @param {Mark } mark
191
+ * @return {Object or Void }
192
+ */
193
+
99
194
renderMark = ( mark ) => {
100
195
return MARKS [ mark . type ]
101
196
}
102
197
198
+ /**
199
+ * Update the menu's absolute position.
200
+ */
201
+
103
202
updateMenu = ( ) => {
104
203
const { menu, state } = this . state
105
204
if ( ! menu ) return
@@ -115,32 +214,6 @@ class HoveringMenu extends React.Component {
115
214
menu . style . left = `${ rect . left + window . scrollX - menu . offsetWidth / 2 + rect . width / 2 } px`
116
215
}
117
216
118
- hasMark = ( type ) => {
119
- const { state } = this . state
120
- return state . marks . some ( mark => mark . type == type )
121
- }
122
-
123
- onChange = ( state ) => {
124
- this . setState ( { state } )
125
- }
126
-
127
- onClickMark = ( e , type ) => {
128
- e . preventDefault ( )
129
- const isActive = this . hasMark ( type )
130
- let { state } = this . state
131
-
132
- state = state
133
- . transform ( )
134
- [ isActive ? 'unmark' : 'mark' ] ( type )
135
- . apply ( )
136
-
137
- this . setState ( { state } )
138
- }
139
-
140
- onOpen = ( el ) => {
141
- this . setState ( { menu : el . firstChild } )
142
- }
143
-
144
217
}
145
218
146
219
/**
0 commit comments