@pareto-engineering/design-system 4.0.0-alpha.39 → 4.0.0-alpha.41

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 (40) hide show
  1. package/dist/cjs/a/People/common/Person/Person.js +4 -4
  2. package/dist/cjs/a/People/styles.scss +10 -4
  3. package/dist/cjs/b/Card/common/Group/Group.js +1 -1
  4. package/dist/cjs/f/fields/EditorInput/EditorInput.js +191 -0
  5. package/dist/cjs/f/fields/EditorInput/common/Toolbar.js +193 -0
  6. package/dist/cjs/f/fields/EditorInput/common/TreeViewPlugin.js +19 -0
  7. package/dist/cjs/f/fields/EditorInput/common/index.js +20 -0
  8. package/dist/cjs/f/fields/EditorInput/index.js +13 -0
  9. package/dist/cjs/f/fields/EditorInput/styles.scss +119 -0
  10. package/dist/cjs/f/fields/QueryCombobox/common/Combobox/Combobox.js +1 -1
  11. package/dist/cjs/f/fields/QueryCombobox/styles.scss +4 -1
  12. package/dist/cjs/f/fields/index.js +8 -1
  13. package/dist/es/a/People/common/Person/Person.js +4 -4
  14. package/dist/es/a/People/styles.scss +10 -4
  15. package/dist/es/b/Card/common/Group/Group.js +1 -1
  16. package/dist/es/f/fields/EditorInput/EditorInput.js +186 -0
  17. package/dist/es/f/fields/EditorInput/common/Toolbar.js +182 -0
  18. package/dist/es/f/fields/EditorInput/common/TreeViewPlugin.js +11 -0
  19. package/dist/es/f/fields/EditorInput/common/index.js +2 -0
  20. package/dist/es/f/fields/EditorInput/index.js +2 -0
  21. package/dist/es/f/fields/EditorInput/styles.scss +119 -0
  22. package/dist/es/f/fields/QueryCombobox/common/Combobox/Combobox.js +1 -1
  23. package/dist/es/f/fields/QueryCombobox/styles.scss +4 -1
  24. package/dist/es/f/fields/index.js +2 -1
  25. package/package.json +5 -3
  26. package/src/stories/a/People.stories.jsx +20 -0
  27. package/src/stories/f/EditorInput.stories.jsx +88 -0
  28. package/src/ui/a/People/common/Person/Person.jsx +4 -4
  29. package/src/ui/a/People/styles.scss +10 -4
  30. package/src/ui/b/Card/common/Group/Group.jsx +1 -1
  31. package/src/ui/f/fields/EditorInput/EditorInput.jsx +237 -0
  32. package/src/ui/f/fields/EditorInput/common/Toolbar.jsx +254 -0
  33. package/src/ui/f/fields/EditorInput/common/TreeViewPlugin.jsx +16 -0
  34. package/src/ui/f/fields/EditorInput/common/index.jsx +2 -0
  35. package/src/ui/f/fields/EditorInput/index.js +2 -0
  36. package/src/ui/f/fields/EditorInput/styles.scss +119 -0
  37. package/src/ui/f/fields/QueryCombobox/common/Combobox/Combobox.jsx +1 -0
  38. package/src/ui/f/fields/QueryCombobox/styles.scss +4 -1
  39. package/src/ui/f/fields/index.js +1 -0
  40. package/tests/__snapshots__/Storyshots.test.js.snap +703 -4
@@ -70,3 +70,23 @@ export const OnePerson = () => {
70
70
  </div>
71
71
  )
72
72
  }
73
+
74
+ export const WithoutRole = () => {
75
+ const peopleMap = [
76
+ {
77
+ image:'https://pareto-v1.s3.us-west-2.amazonaws.com/profile-pictures/Camille-Arigo.jpg',
78
+ name :'Camillie Arigo',
79
+ color:'background4',
80
+ },
81
+ ]
82
+
83
+ return (
84
+ <div className="x-background-far b-x v1 p-v">
85
+ <People>
86
+ {peopleMap.map((person) => (
87
+ <People.Person key={person.name} {...person} />
88
+ ))}
89
+ </People>
90
+ </div>
91
+ )
92
+ }
@@ -0,0 +1,88 @@
1
+ /* @pareto-engineering/generator-front 1.0.12 */
2
+ import * as React from 'react'
3
+
4
+ import { Formik, Form } from 'formik'
5
+
6
+ import { EditorInput, FormDebugger } from 'ui'
7
+
8
+ export default {
9
+ title :'f/fields/EditorInput',
10
+ component :EditorInput,
11
+ subcomponents:{
12
+ // Item:TextareaInput.Item
13
+ },
14
+ decorators:[
15
+ (storyfn) => (
16
+ <Formik
17
+ initialValues={{ feedback: '' }}
18
+ >
19
+ <Form>
20
+ { storyfn() }
21
+ </Form>
22
+ </Formik>
23
+ ),
24
+ ],
25
+ argTypes:{
26
+ name :{ control: 'text' },
27
+ label :{ control: 'text' },
28
+ labelColor :{ control: 'text' },
29
+ disabled :{ control: 'boolean' },
30
+ labelAsDescription:{ control: 'boolean' },
31
+ optional :{ control: 'boolean' },
32
+ labelSpan :{ control: 'number' },
33
+ inputSpan :{ control: 'number' },
34
+ desktopLabelSpan :{ control: 'number' },
35
+ desktopInputSpan :{ control: 'number' },
36
+ showDebugger :{ control: 'boolean' },
37
+ },
38
+ }
39
+
40
+ const Template = (args) => (
41
+ <div className="grid">
42
+ <EditorInput {...args} />
43
+ <FormDebugger />
44
+ </div>
45
+ )
46
+
47
+ export const Base = Template.bind({})
48
+ Base.args = {
49
+ name :'instructions',
50
+ label:'Project Instructions',
51
+ }
52
+
53
+ export const Optional = Template.bind({})
54
+ Optional.args = {
55
+ ...Base.args,
56
+ optional:true,
57
+ }
58
+
59
+ // const validate = (value) => {
60
+ // let errorMessage = ''
61
+ // const isValid = value.length > 3
62
+
63
+ // if (!isValid) {
64
+ // errorMessage = 'Value should be greater than 3 characters'
65
+ // }
66
+ // return errorMessage
67
+ // }
68
+
69
+ // export const Validation = Template.bind({})
70
+ // Validation.args = {
71
+ // ...Base.args,
72
+ // validate,
73
+ // }
74
+
75
+ export const Disabled = Template.bind({})
76
+ Disabled.args = {
77
+ ...Base.args,
78
+ disabled:true,
79
+ }
80
+
81
+ export const OnSingleRow = Template.bind({})
82
+ OnSingleRow.args = {
83
+ ...Base.args,
84
+ labelSpan :4,
85
+ inputSpan :4,
86
+ desktopLabelSpan:4,
87
+ desktopInputSpan:10,
88
+ }
@@ -40,8 +40,8 @@ const Person = ({
40
40
  >
41
41
  <img className="image v50 mr-v" src={image} alt={`${name}, ${role}`} />
42
42
  <div className="details">
43
- <p className="name">{name}</p>
44
- <p className="role">{role}</p>
43
+ {name && <p className="name">{name}</p>}
44
+ { role && <p className="role">{role}</p>}
45
45
  </div>
46
46
  </div>
47
47
  )
@@ -69,11 +69,11 @@ Person.propTypes = {
69
69
  /**
70
70
  * The person's name
71
71
  */
72
- name :PropTypes.string.isRequired,
72
+ name :PropTypes.string,
73
73
  /**
74
74
  * The person's role
75
75
  */
76
- role :PropTypes.string.isRequired,
76
+ role :PropTypes.string,
77
77
  /**
78
78
  * The base color of the person's component
79
79
  */
@@ -11,7 +11,9 @@ $default-padding:var(--u);
11
11
  $default-horizontal-margin: .5em;
12
12
 
13
13
  $default-grid-gap: 1em;
14
- $default-image-padding: 1.5rem;
14
+ $default-margin: 1.5rem;
15
+ $default-image-margin: var(--default-image-margin, #{$default-margin});
16
+ $default-color: var(--default-color, var(--grey));
15
17
 
16
18
  .#{bem.$base}.people {
17
19
  display: grid;
@@ -29,18 +31,22 @@ $default-image-padding: 1.5rem;
29
31
  .image {
30
32
  border-radius: $default-border-radius;
31
33
  height: var(--image-size);
32
- margin-right: $default-image-padding;
34
+ margin-right: $default-image-margin;
33
35
  width: var(--image-size);
34
36
  }
35
37
 
36
38
  .details {
37
39
  align-items: flex-start;
38
- color: var(--grey);
40
+ color: $default-color;
39
41
  display: flex;
40
42
  flex-direction: column;
41
43
 
44
+ p:only-child {
45
+ margin: 0;
46
+ }
47
+
42
48
  .name {
43
- color: var(--grey);
49
+ color: $default-color;
44
50
  margin-bottom: .1em;
45
51
  }
46
52
 
@@ -28,7 +28,7 @@ const Group = ({
28
28
  import('./styles.scss')
29
29
  }, [])
30
30
  const Wrapper = type === 'snap-scroller' ? SnapScroller : 'div'
31
- const wrapperProps = type === 'snap-scroller' ? { noScrollOnDesktop: true } : {}
31
+ const wrapperProps = (type === 'snap-scroller' && desktopType !== 'snap-scroller') ? { noScrollOnDesktop: true } : {}
32
32
 
33
33
  return (
34
34
  <Wrapper
@@ -0,0 +1,237 @@
1
+ /* @pareto-engineering/generator-front 1.0.12 */
2
+ /* eslint-disable import/no-extraneous-dependencies -- required here */
3
+ import * as React from 'react'
4
+ import { useInsertionEffect, memo } from 'react'
5
+ import { useFormikContext } from 'formik'
6
+ import { LexicalComposer } from '@lexical/react/LexicalComposer'
7
+ import { RichTextPlugin } from '@lexical/react/LexicalRichTextPlugin'
8
+ import { ContentEditable } from '@lexical/react/LexicalContentEditable'
9
+ import { OnChangePlugin } from '@lexical/react/LexicalOnChangePlugin'
10
+ import { HistoryPlugin } from '@lexical/react/LexicalHistoryPlugin'
11
+ import { LinkPlugin } from '@lexical/react/LexicalLinkPlugin'
12
+ import { ListPlugin } from '@lexical/react/LexicalListPlugin'
13
+ import { TabIndentationPlugin } from '@lexical/react/LexicalTabIndentationPlugin'
14
+ import { AutoLinkNode, LinkNode } from '@lexical/link'
15
+ import { ListItemNode, ListNode } from '@lexical/list'
16
+
17
+ import PropTypes from 'prop-types'
18
+ import styleNames from '@pareto-engineering/bem/exports'
19
+
20
+ // Local Definitions
21
+
22
+ import { FormLabel, FormDescription, InputWrapper } from '../../common'
23
+ import { Toolbar, TreeViewPlugin } from './common'
24
+
25
+ const baseClassName = styleNames.base
26
+ const componentClassName = 'editor-input'
27
+
28
+ /**
29
+ * This is the component description.
30
+ */
31
+ const EditorInput = ({
32
+ id,
33
+ className:userClassName,
34
+ style,
35
+ name,
36
+ label,
37
+ // validate,
38
+ resize,
39
+ color,
40
+ rows,
41
+ optional,
42
+ labelColor,
43
+ description,
44
+ disabled,
45
+ labelSpan,
46
+ desktopLabelSpan,
47
+ inputSpan,
48
+ desktopInputSpan,
49
+ showDebugger,
50
+ // ...otherProps
51
+ }) => {
52
+ useInsertionEffect(() => {
53
+ import('./styles.scss')
54
+ }, [])
55
+
56
+ const formik = useFormikContext()
57
+
58
+ const setInitialValue = () => {
59
+ const value = formik.values[name]
60
+ return value || undefined
61
+ }
62
+
63
+ const onChange = (state) => {
64
+ formik.setValues({
65
+ ...formik.values,
66
+ [name]:JSON.stringify(state),
67
+ })
68
+ }
69
+
70
+ const initialConfig = {
71
+ nameSpace :name,
72
+ editable :!disabled,
73
+ editorState:setInitialValue(),
74
+ theme :{
75
+ text:{
76
+ italic :'italic',
77
+ strikethrough:'strikethrough',
78
+ underline :'underlined',
79
+ },
80
+ },
81
+ nodes:[
82
+ AutoLinkNode,
83
+ LinkNode,
84
+ ListNode,
85
+ ListItemNode,
86
+ ],
87
+ }
88
+
89
+ return (
90
+ <LexicalComposer
91
+ initialConfig={initialConfig}
92
+ >
93
+ <FormLabel
94
+ name={name}
95
+ color={labelColor}
96
+ optional={optional}
97
+ columnSpan={labelSpan}
98
+ desktopColumnSpan={desktopLabelSpan}
99
+ // {...otherProps}
100
+ >
101
+ {label}
102
+ </FormLabel>
103
+ <InputWrapper
104
+ id={id}
105
+ className={[
106
+ baseClassName,
107
+ componentClassName,
108
+ userClassName,
109
+ `y-${color}`,
110
+ disabled && 'disabled',
111
+ ]
112
+ .filter((e) => e)
113
+ .join(' ')}
114
+ style={{
115
+ ...style,
116
+ '--resize':resize,
117
+ '--rows' :`${rows}em`,
118
+ }}
119
+ columnSpan={inputSpan}
120
+ desktopColumnSpan={desktopInputSpan}
121
+ >
122
+ { !disabled && <Toolbar /> }
123
+ <RichTextPlugin
124
+ contentEditable={(
125
+ <ContentEditable
126
+ id={name}
127
+ className="content-editable"
128
+ />
129
+ )}
130
+ />
131
+ <OnChangePlugin onChange={onChange} />
132
+ <LinkPlugin />
133
+ <ListPlugin />
134
+ <TabIndentationPlugin />
135
+ <HistoryPlugin />
136
+ <FormDescription className="s-1" description={description} name={name} />
137
+ { showDebugger && <TreeViewPlugin />}
138
+ </InputWrapper>
139
+ </LexicalComposer>
140
+ )
141
+ }
142
+
143
+ EditorInput.propTypes = {
144
+ /**
145
+ * The HTML id for this element
146
+ */
147
+ id:PropTypes.string,
148
+
149
+ /**
150
+ * The HTML class names for this element
151
+ */
152
+ className:PropTypes.string,
153
+
154
+ /**
155
+ * The React-written, css properties for this element.
156
+ */
157
+ style:PropTypes.objectOf(PropTypes.string),
158
+
159
+ /**
160
+ * The input name (html - and Formik state)
161
+ */
162
+ name:PropTypes.string.isRequired,
163
+
164
+ /**
165
+ * The input label
166
+ */
167
+ label:PropTypes.string.isRequired,
168
+
169
+ /**
170
+ * The input value validator function
171
+ */
172
+ // validate:PropTypes.func,
173
+
174
+ /**
175
+ * The number of rows int the text area
176
+ */
177
+ rows:PropTypes.number,
178
+
179
+ /**
180
+ * Color of the text
181
+ */
182
+ color:PropTypes.string,
183
+
184
+ /**
185
+ * Label base color
186
+ */
187
+ labelColor:PropTypes.string,
188
+
189
+ /**
190
+ * Text area description
191
+ */
192
+ description:PropTypes.string,
193
+
194
+ /**
195
+ * Whether the text area should be disabled
196
+ */
197
+ disabled:PropTypes.bool,
198
+
199
+ /**
200
+ * Whether the input is optional or not
201
+ */
202
+ optional:PropTypes.bool,
203
+
204
+ /**
205
+ * The number of columns the label should span
206
+ */
207
+ labelSpan:PropTypes.number,
208
+
209
+ /**
210
+ * The number of columns the input should span
211
+ */
212
+ inputSpan:PropTypes.number,
213
+
214
+ /**
215
+ * The number of columns the label should span on desktop
216
+ */
217
+ desktopLabelSpan:PropTypes.number,
218
+
219
+ /**
220
+ * The number of columns the input should span on desktop
221
+ */
222
+ desktopInputSpan:PropTypes.number,
223
+
224
+ /**
225
+ * The resize property of the text area
226
+ */
227
+ resize:PropTypes.oneOf(['none', 'both', 'horizontal', 'vertical']),
228
+ }
229
+
230
+ EditorInput.defaultProps = {
231
+ rows :10,
232
+ disabled:false,
233
+ color :'paragraph',
234
+ resize :'vertical',
235
+ }
236
+
237
+ export default memo(EditorInput)
@@ -0,0 +1,254 @@
1
+ /* eslint-disable import/no-extraneous-dependencies -- required here */
2
+ import * as React from 'react'
3
+
4
+ import { useEffect, useState, useCallback } from 'react'
5
+
6
+ import {
7
+ $getSelection,
8
+ $isRangeSelection,
9
+ FORMAT_TEXT_COMMAND,
10
+ FORMAT_ELEMENT_COMMAND,
11
+ UNDO_COMMAND,
12
+ REDO_COMMAND,
13
+ } from 'lexical'
14
+ import {
15
+ INSERT_ORDERED_LIST_COMMAND,
16
+ INSERT_UNORDERED_LIST_COMMAND,
17
+ REMOVE_LIST_COMMAND,
18
+ $isListNode,
19
+ ListNode,
20
+ } from '@lexical/list'
21
+ import {
22
+ $isAtNodeEnd,
23
+ } from '@lexical/selection'
24
+ import {
25
+ $isLinkNode,
26
+ TOGGLE_LINK_COMMAND,
27
+ } from '@lexical/link'
28
+ import { useLexicalComposerContext } from '@lexical/react/LexicalComposerContext'
29
+ import { mergeRegister, $getNearestNodeOfType } from '@lexical/utils'
30
+ import styleNames from '@pareto-engineering/bem/exports'
31
+
32
+ const baseClassName = styleNames.base
33
+
34
+ const componentClassName = 'toolbar'
35
+
36
+ const getSelectedNode = (selection) => {
37
+ const { anchor, focus } = selection
38
+ const anchorNode = selection.anchor.getNode()
39
+ const focusNode = selection.focus.getNode()
40
+ if (anchorNode === focusNode) {
41
+ return anchorNode
42
+ }
43
+ const isBackward = selection.isBackward()
44
+ if (isBackward) {
45
+ return $isAtNodeEnd(focus) ? anchorNode : focusNode
46
+ }
47
+ return $isAtNodeEnd(anchor) ? focusNode : anchorNode
48
+ }
49
+
50
+ const Toolbar = () => {
51
+ const [editor] = useLexicalComposerContext()
52
+ const [isBold, setIsBold] = useState(false)
53
+ const [isItalic, setIsItalic] = useState(false)
54
+ const [isStrikethrough, setIsStrikethrough] = useState(false)
55
+ const [blockType, setBlockType] = useState('paragraph')
56
+ const [isLink, setIsLink] = useState(false)
57
+ const [isUnderline, setIsUnderline] = useState(false)
58
+
59
+ const formatBulletList = () => {
60
+ if (blockType !== 'ul') {
61
+ editor.dispatchCommand(INSERT_UNORDERED_LIST_COMMAND)
62
+ } else {
63
+ editor.dispatchCommand(REMOVE_LIST_COMMAND)
64
+ }
65
+ }
66
+
67
+ const formatNumberedList = () => {
68
+ if (blockType !== 'ol') {
69
+ editor.dispatchCommand(INSERT_ORDERED_LIST_COMMAND)
70
+ } else {
71
+ editor.dispatchCommand(REMOVE_LIST_COMMAND)
72
+ }
73
+ }
74
+
75
+ const formatLink = useCallback(() => {
76
+ if (!isLink) {
77
+ // eslint-disable-next-line no-alert
78
+ const path = prompt('Enter the full URL. Ex: https://www.example.com')
79
+ editor.dispatchCommand(TOGGLE_LINK_COMMAND, path)
80
+ } else {
81
+ editor.dispatchCommand(TOGGLE_LINK_COMMAND, null)
82
+ }
83
+ }, [editor, isLink])
84
+
85
+ const updateToolbar = useCallback(() => {
86
+ const selection = $getSelection()
87
+
88
+ // Check list selection
89
+ if ($isRangeSelection(selection)) {
90
+ const anchorNode = selection.anchor.getNode()
91
+ const element = anchorNode.getKey() === 'root'
92
+ ? anchorNode
93
+ : anchorNode.getTopLevelElementOrThrow()
94
+ if ($isListNode(element)) {
95
+ const parentList = $getNearestNodeOfType(anchorNode, ListNode)
96
+ const type = parentList ? parentList.getTag() : element.getTag()
97
+ setBlockType(type)
98
+ } else {
99
+ setBlockType(element)
100
+ }
101
+
102
+ // Check selection text styles
103
+ setIsBold(selection.hasFormat('bold'))
104
+ setIsItalic(selection.hasFormat('italic'))
105
+ setIsStrikethrough(selection.hasFormat('strikethrough'))
106
+ setIsUnderline(selection.hasFormat('underline'))
107
+ setIsLink(selection.hasFormat('link'))
108
+
109
+ // Check links
110
+ const node = getSelectedNode(selection)
111
+ const parent = node.getParent()
112
+ if ($isLinkNode(parent) || $isLinkNode(node)) {
113
+ setIsLink(true)
114
+ } else {
115
+ setIsLink(false)
116
+ }
117
+ }
118
+ }, [editor])
119
+
120
+ useEffect(() => mergeRegister(
121
+ editor.registerUpdateListener(({ editorState }) => {
122
+ editorState.read(() => {
123
+ updateToolbar()
124
+ })
125
+ }),
126
+ ), [updateToolbar, editor])
127
+
128
+ return (
129
+ <div className={`${baseClassName} ${componentClassName}`}>
130
+ <div className="group">
131
+ <button
132
+ type="button"
133
+ className={isBold ? 'active' : undefined}
134
+ onClick={() => editor.dispatchCommand(FORMAT_TEXT_COMMAND, 'bold')}
135
+ >
136
+ <span className="icon">
137
+ |
138
+ </span>
139
+ </button>
140
+ <button
141
+ type="button"
142
+ className={isItalic ? 'active' : undefined}
143
+ onClick={() => editor.dispatchCommand(FORMAT_TEXT_COMMAND, 'italic')}
144
+ >
145
+ <span className="icon">
146
+ &#125;
147
+ </span>
148
+ </button>
149
+ <button
150
+ type="button"
151
+ className={isUnderline ? 'active' : undefined}
152
+ onClick={() => editor.dispatchCommand(FORMAT_TEXT_COMMAND, 'underline')}
153
+ >
154
+ <span className="icon">
155
+ ~
156
+ </span>
157
+ </button>
158
+ <button
159
+ type="button"
160
+ className={isStrikethrough ? 'active' : undefined}
161
+ onClick={() => editor.dispatchCommand(FORMAT_TEXT_COMMAND, 'strikethrough')}
162
+ >
163
+ <span className="icon">
164
+ ?
165
+ </span>
166
+ </button>
167
+ <button
168
+ type="button"
169
+ className={isLink ? 'active' : undefined}
170
+ onClick={() => formatLink()}
171
+ >
172
+ <span className="icon">
173
+ &#93;
174
+ </span>
175
+ </button>
176
+ <button
177
+ type="button"
178
+ className={blockType === 'ul' ? 'active' : undefined}
179
+ onClick={() => formatBulletList()}
180
+ >
181
+ <span className="icon">
182
+ .
183
+ </span>
184
+ </button>
185
+ <button
186
+ type="button"
187
+ className={blockType === 'ol' ? 'active' : undefined}
188
+ onClick={() => formatNumberedList()}
189
+ >
190
+ <span className="icon">
191
+ -
192
+ </span>
193
+ </button>
194
+ </div>
195
+
196
+ <div className="group">
197
+ <button
198
+ type="button"
199
+ onClick={() => editor.dispatchCommand(FORMAT_ELEMENT_COMMAND, 'left')}
200
+ >
201
+ <span className="icon">
202
+ ^
203
+ </span>
204
+ </button>
205
+ <button
206
+ type="button"
207
+ onClick={() => editor.dispatchCommand(FORMAT_ELEMENT_COMMAND, 'center')}
208
+ >
209
+ <span className="icon">
210
+ _
211
+ </span>
212
+ </button>
213
+ <button
214
+ type="button"
215
+ onClick={() => editor.dispatchCommand(FORMAT_ELEMENT_COMMAND, 'right')}
216
+ >
217
+ <span className="icon">
218
+ `
219
+ </span>
220
+ </button>
221
+ <button
222
+ type="button"
223
+ onClick={() => editor.dispatchCommand(FORMAT_ELEMENT_COMMAND, 'justify')}
224
+ >
225
+ <span className="icon">
226
+ &#123;
227
+ </span>
228
+ </button>
229
+ </div>
230
+
231
+ <div className="group">
232
+ <button
233
+ type="button"
234
+ onClick={() => editor.dispatchCommand(UNDO_COMMAND)}
235
+ >
236
+ <span className="icon">
237
+ \
238
+ </span>
239
+ </button>
240
+ <button
241
+ type="button"
242
+ className="flip"
243
+ onClick={() => editor.dispatchCommand(REDO_COMMAND)}
244
+ >
245
+ <span className="icon">
246
+ \
247
+ </span>
248
+ </button>
249
+ </div>
250
+ </div>
251
+ )
252
+ }
253
+
254
+ export default Toolbar
@@ -0,0 +1,16 @@
1
+ import React from 'react'
2
+ import { useLexicalComposerContext } from '@lexical/react/LexicalComposerContext'
3
+ import { TreeView } from '@lexical/react/LexicalTreeView'
4
+
5
+ const TreeViewPlugin = () => {
6
+ const [editor] = useLexicalComposerContext()
7
+
8
+ return (
9
+ <TreeView
10
+ viewClassName="tree-view-output"
11
+ editor={editor}
12
+ />
13
+ )
14
+ }
15
+
16
+ export default TreeViewPlugin
@@ -0,0 +1,2 @@
1
+ export { default as Toolbar } from './Toolbar'
2
+ export { default as TreeViewPlugin } from './TreeViewPlugin'
@@ -0,0 +1,2 @@
1
+ /* @pareto-engineering/generator-front 1.0.12 */
2
+ export { default as EditorInput } from './EditorInput'