5htp-core 0.4.7-1 → 0.4.7-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 (30) hide show
  1. package/package.json +6 -1
  2. package/src/client/components/Select/index.tsx +134 -129
  3. package/src/client/components/index.ts +2 -1
  4. package/src/client/components/inputv3/Rte/ExampleTheme.tsx +42 -0
  5. package/src/client/components/inputv3/Rte/ToolbarPlugin.tsx +167 -0
  6. package/src/client/components/inputv3/Rte/icons/LICENSE.md +5 -0
  7. package/src/client/components/inputv3/Rte/icons/arrow-clockwise.svg +4 -0
  8. package/src/client/components/inputv3/Rte/icons/arrow-counterclockwise.svg +4 -0
  9. package/src/client/components/inputv3/Rte/icons/journal-text.svg +5 -0
  10. package/src/client/components/inputv3/Rte/icons/justify.svg +3 -0
  11. package/src/client/components/inputv3/Rte/icons/text-center.svg +3 -0
  12. package/src/client/components/inputv3/Rte/icons/text-left.svg +3 -0
  13. package/src/client/components/inputv3/Rte/icons/text-paragraph.svg +3 -0
  14. package/src/client/components/inputv3/Rte/icons/text-right.svg +3 -0
  15. package/src/client/components/inputv3/Rte/icons/type-bold.svg +3 -0
  16. package/src/client/components/inputv3/Rte/icons/type-italic.svg +3 -0
  17. package/src/client/components/inputv3/Rte/icons/type-strikethrough.svg +3 -0
  18. package/src/client/components/inputv3/Rte/icons/type-underline.svg +3 -0
  19. package/src/client/components/inputv3/Rte/index.tsx +163 -0
  20. package/src/client/components/inputv3/Rte/style.less +428 -0
  21. package/src/client/components/inputv3/base.less +20 -33
  22. package/src/client/components/inputv3/base.tsx +33 -1
  23. package/src/client/components/inputv3/index.tsx +44 -43
  24. package/src/common/data/rte/index.ts +66 -0
  25. package/src/common/data/rte/nodes.ts +20 -0
  26. package/src/common/validation/validators.ts +45 -0
  27. package/src/client/components/input/Rte/index.less +0 -13
  28. package/src/client/components/input/Rte/index.tsx +0 -143
  29. package/src/client/components/input/Rte/selection.ts +0 -34
  30. package/src/common/data/rte.tsx +0 -11
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "5htp-core",
3
3
  "description": "Convenient TypeScript framework designed for Performance and Productivity.",
4
- "version": "0.4.7-1",
4
+ "version": "0.4.7-2",
5
5
  "author": "Gaetan Le Gac (https://github.com/gaetanlegac)",
6
6
  "repository": "git://github.com/gaetanlegac/5htp-core.git",
7
7
  "license": "MIT",
@@ -13,6 +13,9 @@
13
13
  "framework"
14
14
  ],
15
15
  "dependencies": {
16
+ "@lexical/headless": "^0.18.0",
17
+ "@lexical/html": "^0.18.0",
18
+ "@lexical/react": "^0.18.0",
16
19
  "accepts": "^1.3.7",
17
20
  "activity-detector": "^3.0.0",
18
21
  "ansi-to-html": "^0.7.1",
@@ -44,7 +47,9 @@
44
47
  "intl": "^1.2.5",
45
48
  "iso-639-1": "^2.1.9",
46
49
  "js-cookie": "^3.0.1",
50
+ "jsdom": "^25.0.1",
47
51
  "jsonwebtoken": "^8.5.1",
52
+ "lexical": "^0.18.0",
48
53
  "load-script": "^2.0.0",
49
54
  "locale": "^0.1.0",
50
55
  "markdown-it": "^13.0.1",
@@ -8,6 +8,7 @@ import React from 'react';
8
8
  // Core
9
9
  import { Props as DropdownProps } from '@client/components/dropdown';
10
10
  import { Popover, Button, Input } from '@client/components';
11
+ import { InputWrapper, InputBaseProps } from '@client/components/inputv3/base';
11
12
 
12
13
  // Specific
13
14
  import {
@@ -21,10 +22,8 @@ import ChoiceElement from './ChoiceElement';
21
22
  - TYPES
22
23
  ----------------------------------*/
23
24
 
24
- export type Props = SelectorProps & {
25
+ export type Props = SelectorProps & Omit<InputBaseProps<Choice>, 'value'> & {
25
26
  dropdown?: boolean | DropdownProps,
26
- title: string,
27
- errors?: string[],
28
27
  }
29
28
 
30
29
  export type { Choice } from './ChoiceSelector';
@@ -51,24 +50,27 @@ const ensureChoice = (choice: Choice | string, choices: Choice[]): Choice => {
51
50
  /*----------------------------------
52
51
  - COMONENT
53
52
  ----------------------------------*/
54
- export default ({
55
- // Input basics
56
- title,
57
- errors,
58
- icon,
59
- required,
60
- validator,
61
-
62
- // Choice selection
63
- choices: initChoices,
64
- noneSelection,
65
- enableSearch,
66
- value: current,
67
- onChange: onChangeCallback,
68
- multiple,
69
- dropdown,
70
- ...otherProps
71
- }: Props) => {
53
+ export default (props: Props) => {
54
+
55
+ let {
56
+ // Input basics
57
+ title,
58
+ errors,
59
+ icon,
60
+ required,
61
+ validator,
62
+ wrapper = true,
63
+
64
+ // Choice selection
65
+ choices: initChoices,
66
+ noneSelection,
67
+ enableSearch,
68
+ value: current,
69
+ onChange: onChangeCallback,
70
+ multiple,
71
+ dropdown,
72
+ ...otherProps
73
+ } = props;
72
74
 
73
75
  /*----------------------------------
74
76
  - INIT
@@ -161,119 +163,122 @@ export default ({
161
163
  />
162
164
  )
163
165
 
164
- return dropdown ? (
165
- <Popover {...(dropdown === true ? {
166
- width: '200px'
167
- } : dropdown)} content={(
168
- <div class="card bg white col al-top">
169
-
170
- {Search}
171
-
172
- {selectedItems.length !== 0 && (
173
- <ul class="row al-left wrap sp-05">
174
- {selectedItems.map( choice => (
175
- <ChoiceElement format='badge' choice={choice}
176
- currentList={currentList}
177
- onChange={onChange}
178
- multiple={multiple}
179
- includeCurrent
180
- />
181
- ))}
182
- </ul>
183
- )}
184
-
185
- {search.loading ? (
186
- <div class="row al-center h-2">
187
- <i src="spin" />
166
+ return (
167
+ <InputWrapper {...props}>
168
+ {dropdown ? (
169
+ <Popover {...(dropdown === true ? {
170
+ width: '200px'
171
+ } : dropdown)} content={(
172
+ <div class="card bg white col al-top">
173
+
174
+ {Search}
175
+
176
+ {selectedItems.length !== 0 && (
177
+ <ul class="row al-left wrap sp-05">
178
+ {selectedItems.map( choice => (
179
+ <ChoiceElement format='badge' choice={choice}
180
+ currentList={currentList}
181
+ onChange={onChange}
182
+ multiple={multiple}
183
+ includeCurrent
184
+ />
185
+ ))}
186
+ </ul>
187
+ )}
188
+
189
+ {search.loading ? (
190
+ <div class="row al-center h-2">
191
+ <i src="spin" />
192
+ </div>
193
+ ) : (
194
+ <ul class="menu col">
195
+ {choices.map( choice => (
196
+ <ChoiceElement format='list' choice={choice}
197
+ currentList={currentList}
198
+ onChange={onChange}
199
+ multiple={multiple}
200
+ includeCurrent
201
+ />
202
+ ))}
203
+ </ul>
204
+ )}
188
205
  </div>
189
- ) : (
190
- <ul class="menu col">
191
- {choices.map( choice => (
192
- <ChoiceElement format='list' choice={choice}
193
- currentList={currentList}
194
- onChange={onChange}
195
- multiple={multiple}
196
- includeCurrent
197
- />
198
- ))}
199
- </ul>
200
- )}
201
- </div>
202
- )} state={popoverState}>
203
- <Button type="secondary" icon={icon} iconR="chevron-down" {...otherProps}>
204
-
205
- {currentList.length === 0 ? <>
206
- {title}
207
- </> : multiple ? <>
208
- {title} <span class="badge s bg accent">{currentList.length}</span>
209
- </> : <>
210
- {currentList[0].label}
211
- </>}
212
-
213
- {errors?.length && (
214
- <div class="bubble bg error bottom">
215
- {errors.join('. ')}
216
- </div>
217
- )}
218
-
219
- </Button>
220
- </Popover>
221
- ) : (
222
-
223
- <div class="col sp-05">
224
- <div class={className} onMouseDown={() => refInputSearch.current?.focus()}>
225
-
226
- <div class="row al-left wrap pd-1">
227
-
228
- {icon !== undefined && (
229
- <i src={icon} />
230
- )}
206
+ )} state={popoverState}>
207
+ <Button type="secondary" icon={icon} iconR="chevron-down" {...otherProps}>
208
+
209
+ {currentList.length === 0 ? <>
210
+ {title}
211
+ </> : multiple ? <>
212
+ {title} <span class="badge s bg accent">{currentList.length}</span>
213
+ </> : <>
214
+ {currentList[0].label}
215
+ </>}
216
+
217
+ {errors?.length && (
218
+ <div class="bubble bg error bottom">
219
+ {errors.join('. ')}
220
+ </div>
221
+ )}
222
+
223
+ </Button>
224
+ </Popover>
225
+ ) : (
226
+ <div class="col sp-05">
227
+ <div class={className} onMouseDown={() => refInputSearch.current?.focus()}>
228
+
229
+ <div class="row al-left wrap pd-1">
230
+
231
+ {icon !== undefined && (
232
+ <i src={icon} />
233
+ )}
234
+
235
+ <div class="col al-left sp-05">
236
+
237
+ <label>{title}{isRequired && (
238
+ <span class="fg error">&nbsp;*</span>
239
+ )}</label>
240
+
241
+ <div class="row al-left wrap sp-05">
242
+
243
+ {selectedItems.map( choice => (
244
+ <ChoiceElement format='badge' choice={choice}
245
+ currentList={currentList}
246
+ onChange={onChange}
247
+ multiple={multiple}
248
+ includeCurrent
249
+ />
250
+ ))}
251
+
252
+ {Search}
253
+ </div>
254
+ </div>
231
255
 
232
- <div class="col al-left sp-05">
233
-
234
- <label>{title}{isRequired && (
235
- <span class="fg error">&nbsp;*</span>
236
- )}</label>
237
-
238
- <div class="row al-left wrap sp-05">
239
-
240
- {selectedItems.map( choice => (
241
- <ChoiceElement format='badge' choice={choice}
242
- currentList={currentList}
243
- onChange={onChange}
244
- multiple={multiple}
245
- includeCurrent
246
- />
247
- ))}
248
-
249
- {Search}
250
256
  </div>
251
- </div>
252
-
253
- </div>
254
257
 
255
- <div class="pd-1">
256
- <ul class="row al-left wrap sp-05" style={{
257
- maxHeight: '30vh',
258
- overflowY: 'auto'
259
- }}>
260
- {choices.map( choice => (
261
- <ChoiceElement format='badge' choice={choice}
262
- currentList={currentList}
263
- onChange={onChange}
264
- multiple={multiple}
265
- includeCurrent
266
- />
267
- ))}
268
- </ul>
269
- </div>
270
-
271
- </div>
272
- {errors?.length && (
273
- <div class="bubble bg error bottom">
274
- {errors.join('. ')}
258
+ <div class="pd-1">
259
+ <ul class="row al-left wrap sp-05" style={{
260
+ maxHeight: '30vh',
261
+ overflowY: 'auto'
262
+ }}>
263
+ {choices.map( choice => (
264
+ <ChoiceElement format='badge' choice={choice}
265
+ currentList={currentList}
266
+ onChange={onChange}
267
+ multiple={multiple}
268
+ includeCurrent
269
+ />
270
+ ))}
271
+ </ul>
272
+ </div>
273
+
274
+ </div>
275
+ {errors?.length && (
276
+ <div class="bubble bg error bottom">
277
+ {errors.join('. ')}
278
+ </div>
279
+ )}
275
280
  </div>
276
281
  )}
277
- </div>
282
+ </InputWrapper>
278
283
  )
279
284
  }
@@ -27,4 +27,5 @@ export { default as Select } from './Select';
27
27
  export { default as Input } from './inputv3';
28
28
  export { default as Checkbox } from './inputv3/Checkbox';
29
29
  export { default as File } from './inputv3/file';
30
- export { default as DateRangeInput } from './inputv3/Date';
30
+ export { default as DateRangeInput } from './inputv3/Date';
31
+ export { default as Rte } from './inputv3/Rte';
@@ -0,0 +1,42 @@
1
+ /**
2
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
3
+ *
4
+ * This source code is licensed under the MIT license found in the
5
+ * LICENSE file in the root directory of this source tree.
6
+ *
7
+ */
8
+ export default {
9
+ code: 'editor-code',
10
+ heading: {
11
+ h1: 'editor-heading-h1',
12
+ h2: 'editor-heading-h2',
13
+ h3: 'editor-heading-h3',
14
+ h4: 'editor-heading-h4',
15
+ h5: 'editor-heading-h5',
16
+ },
17
+ image: 'editor-image',
18
+ link: 'editor-link',
19
+ list: {
20
+ listitem: 'editor-listitem',
21
+ nested: {
22
+ listitem: 'editor-nested-listitem',
23
+ },
24
+ ol: 'editor-list-ol',
25
+ ul: 'editor-list-ul',
26
+ },
27
+ ltr: 'ltr',
28
+ paragraph: 'editor-paragraph',
29
+ placeholder: 'editor-placeholder',
30
+ quote: 'editor-quote',
31
+ rtl: 'rtl',
32
+ text: {
33
+ bold: 'editor-text-bold',
34
+ code: 'editor-text-code',
35
+ hashtag: 'editor-text-hashtag',
36
+ italic: 'editor-text-italic',
37
+ overflowed: 'editor-text-overflowed',
38
+ strikethrough: 'editor-text-strikethrough',
39
+ underline: 'editor-text-underline',
40
+ underlineStrikethrough: 'editor-text-underlineStrikethrough',
41
+ },
42
+ };
@@ -0,0 +1,167 @@
1
+ import { useLexicalComposerContext } from '@lexical/react/LexicalComposerContext';
2
+ import { mergeRegister } from '@lexical/utils';
3
+ import {
4
+ $getSelection,
5
+ $isRangeSelection,
6
+ CAN_REDO_COMMAND,
7
+ CAN_UNDO_COMMAND,
8
+ FORMAT_ELEMENT_COMMAND,
9
+ FORMAT_TEXT_COMMAND,
10
+ REDO_COMMAND,
11
+ SELECTION_CHANGE_COMMAND,
12
+ UNDO_COMMAND,
13
+ } from 'lexical';
14
+
15
+ import React from 'react';
16
+ import { useCallback, useEffect, useRef, useState } from 'react';
17
+
18
+ const LowPriority = 1;
19
+
20
+ function Divider() {
21
+ return <div className="divider" />;
22
+ }
23
+
24
+ export default function ToolbarPlugin() {
25
+ const [editor] = useLexicalComposerContext();
26
+ const toolbarRef = useRef(null);
27
+ const [canUndo, setCanUndo] = useState(false);
28
+ const [canRedo, setCanRedo] = useState(false);
29
+ const [isBold, setIsBold] = useState(false);
30
+ const [isItalic, setIsItalic] = useState(false);
31
+ const [isUnderline, setIsUnderline] = useState(false);
32
+ const [isStrikethrough, setIsStrikethrough] = useState(false);
33
+
34
+ const $updateToolbar = useCallback(() => {
35
+ const selection = $getSelection();
36
+ if ($isRangeSelection(selection)) {
37
+ // Update text format
38
+ setIsBold(selection.hasFormat('bold'));
39
+ setIsItalic(selection.hasFormat('italic'));
40
+ setIsUnderline(selection.hasFormat('underline'));
41
+ setIsStrikethrough(selection.hasFormat('strikethrough'));
42
+ }
43
+ }, []);
44
+
45
+ useEffect(() => {
46
+ return mergeRegister(
47
+ editor.registerUpdateListener(({ editorState }) => {
48
+ editorState.read(() => {
49
+ $updateToolbar();
50
+ });
51
+ }),
52
+ editor.registerCommand(
53
+ SELECTION_CHANGE_COMMAND,
54
+ (_payload, _newEditor) => {
55
+ $updateToolbar();
56
+ return false;
57
+ },
58
+ LowPriority,
59
+ ),
60
+ editor.registerCommand(
61
+ CAN_UNDO_COMMAND,
62
+ (payload) => {
63
+ setCanUndo(payload);
64
+ return false;
65
+ },
66
+ LowPriority,
67
+ ),
68
+ editor.registerCommand(
69
+ CAN_REDO_COMMAND,
70
+ (payload) => {
71
+ setCanRedo(payload);
72
+ return false;
73
+ },
74
+ LowPriority,
75
+ ),
76
+ );
77
+ }, [editor, $updateToolbar]);
78
+
79
+ return (
80
+ <div className="toolbar" ref={toolbarRef}>
81
+ <button
82
+ disabled={!canUndo}
83
+ onClick={() => {
84
+ editor.dispatchCommand(UNDO_COMMAND, undefined);
85
+ }}
86
+ className="toolbar-item spaced"
87
+ aria-label="Undo">
88
+ <i className="format undo" />
89
+ </button>
90
+ <button
91
+ disabled={!canRedo}
92
+ onClick={() => {
93
+ editor.dispatchCommand(REDO_COMMAND, undefined);
94
+ }}
95
+ className="toolbar-item"
96
+ aria-label="Redo">
97
+ <i className="format redo" />
98
+ </button>
99
+ <Divider />
100
+ <button
101
+ onClick={() => {
102
+ editor.dispatchCommand(FORMAT_TEXT_COMMAND, 'bold');
103
+ }}
104
+ className={'toolbar-item spaced ' + (isBold ? 'active' : '')}
105
+ aria-label="Format Bold">
106
+ <i className="format bold" />
107
+ </button>
108
+ <button
109
+ onClick={() => {
110
+ editor.dispatchCommand(FORMAT_TEXT_COMMAND, 'italic');
111
+ }}
112
+ className={'toolbar-item spaced ' + (isItalic ? 'active' : '')}
113
+ aria-label="Format Italics">
114
+ <i className="format italic" />
115
+ </button>
116
+ <button
117
+ onClick={() => {
118
+ editor.dispatchCommand(FORMAT_TEXT_COMMAND, 'underline');
119
+ }}
120
+ className={'toolbar-item spaced ' + (isUnderline ? 'active' : '')}
121
+ aria-label="Format Underline">
122
+ <i className="format underline" />
123
+ </button>
124
+ <button
125
+ onClick={() => {
126
+ editor.dispatchCommand(FORMAT_TEXT_COMMAND, 'strikethrough');
127
+ }}
128
+ className={'toolbar-item spaced ' + (isStrikethrough ? 'active' : '')}
129
+ aria-label="Format Strikethrough">
130
+ <i className="format strikethrough" />
131
+ </button>
132
+ <Divider />
133
+ <button
134
+ onClick={() => {
135
+ editor.dispatchCommand(FORMAT_ELEMENT_COMMAND, 'left');
136
+ }}
137
+ className="toolbar-item spaced"
138
+ aria-label="Left Align">
139
+ <i className="format left-align" />
140
+ </button>
141
+ <button
142
+ onClick={() => {
143
+ editor.dispatchCommand(FORMAT_ELEMENT_COMMAND, 'center');
144
+ }}
145
+ className="toolbar-item spaced"
146
+ aria-label="Center Align">
147
+ <i className="format center-align" />
148
+ </button>
149
+ <button
150
+ onClick={() => {
151
+ editor.dispatchCommand(FORMAT_ELEMENT_COMMAND, 'right');
152
+ }}
153
+ className="toolbar-item spaced"
154
+ aria-label="Right Align">
155
+ <i className="format right-align" />
156
+ </button>
157
+ <button
158
+ onClick={() => {
159
+ editor.dispatchCommand(FORMAT_ELEMENT_COMMAND, 'justify');
160
+ }}
161
+ className="toolbar-item"
162
+ aria-label="Justify Align">
163
+ <i className="format justify-align" />
164
+ </button>{' '}
165
+ </div>
166
+ );
167
+ }
@@ -0,0 +1,5 @@
1
+ Bootstrap Icons
2
+ https://icons.getbootstrap.com
3
+
4
+ Licensed under MIT license
5
+ https://github.com/twbs/icons/blob/main/LICENSE.md
@@ -0,0 +1,4 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-arrow-clockwise" viewBox="0 0 16 16">
2
+ <path fill-rule="evenodd" d="M8 3a5 5 0 1 0 4.546 2.914.5.5 0 0 1 .908-.417A6 6 0 1 1 8 2v1z"/>
3
+ <path d="M8 4.466V.534a.25.25 0 0 1 .41-.192l2.36 1.966c.12.1.12.284 0 .384L8.41 4.658A.25.25 0 0 1 8 4.466z"/>
4
+ </svg>
@@ -0,0 +1,4 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-arrow-counterclockwise" viewBox="0 0 16 16">
2
+ <path fill-rule="evenodd" d="M8 3a5 5 0 1 1-4.546 2.914.5.5 0 0 0-.908-.417A6 6 0 1 0 8 2v1z"/>
3
+ <path d="M8 4.466V.534a.25.25 0 0 0-.41-.192L5.23 2.308a.25.25 0 0 0 0 .384l2.36 1.966A.25.25 0 0 0 8 4.466z"/>
4
+ </svg>
@@ -0,0 +1,5 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-journal-text" viewBox="0 0 16 16">
2
+ <path d="M5 10.5a.5.5 0 0 1 .5-.5h2a.5.5 0 0 1 0 1h-2a.5.5 0 0 1-.5-.5zm0-2a.5.5 0 0 1 .5-.5h5a.5.5 0 0 1 0 1h-5a.5.5 0 0 1-.5-.5zm0-2a.5.5 0 0 1 .5-.5h5a.5.5 0 0 1 0 1h-5a.5.5 0 0 1-.5-.5zm0-2a.5.5 0 0 1 .5-.5h5a.5.5 0 0 1 0 1h-5a.5.5 0 0 1-.5-.5z"/>
3
+ <path d="M3 0h10a2 2 0 0 1 2 2v12a2 2 0 0 1-2 2H3a2 2 0 0 1-2-2v-1h1v1a1 1 0 0 0 1 1h10a1 1 0 0 0 1-1V2a1 1 0 0 0-1-1H3a1 1 0 0 0-1 1v1H1V2a2 2 0 0 1 2-2z"/>
4
+ <path d="M1 5v-.5a.5.5 0 0 1 1 0V5h.5a.5.5 0 0 1 0 1h-2a.5.5 0 0 1 0-1H1zm0 3v-.5a.5.5 0 0 1 1 0V8h.5a.5.5 0 0 1 0 1h-2a.5.5 0 0 1 0-1H1zm0 3v-.5a.5.5 0 0 1 1 0v.5h.5a.5.5 0 0 1 0 1h-2a.5.5 0 0 1 0-1H1z"/>
5
+ </svg>
@@ -0,0 +1,3 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-justify" viewBox="0 0 16 16">
2
+ <path fill-rule="evenodd" d="M2 12.5a.5.5 0 0 1 .5-.5h11a.5.5 0 0 1 0 1h-11a.5.5 0 0 1-.5-.5zm0-3a.5.5 0 0 1 .5-.5h11a.5.5 0 0 1 0 1h-11a.5.5 0 0 1-.5-.5zm0-3a.5.5 0 0 1 .5-.5h11a.5.5 0 0 1 0 1h-11a.5.5 0 0 1-.5-.5zm0-3a.5.5 0 0 1 .5-.5h11a.5.5 0 0 1 0 1h-11a.5.5 0 0 1-.5-.5z"/>
3
+ </svg>
@@ -0,0 +1,3 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-text-center" viewBox="0 0 16 16">
2
+ <path fill-rule="evenodd" d="M4 12.5a.5.5 0 0 1 .5-.5h7a.5.5 0 0 1 0 1h-7a.5.5 0 0 1-.5-.5zm-2-3a.5.5 0 0 1 .5-.5h11a.5.5 0 0 1 0 1h-11a.5.5 0 0 1-.5-.5zm2-3a.5.5 0 0 1 .5-.5h7a.5.5 0 0 1 0 1h-7a.5.5 0 0 1-.5-.5zm-2-3a.5.5 0 0 1 .5-.5h11a.5.5 0 0 1 0 1h-11a.5.5 0 0 1-.5-.5z"/>
3
+ </svg>
@@ -0,0 +1,3 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-text-left" viewBox="0 0 16 16">
2
+ <path fill-rule="evenodd" d="M2 12.5a.5.5 0 0 1 .5-.5h7a.5.5 0 0 1 0 1h-7a.5.5 0 0 1-.5-.5zm0-3a.5.5 0 0 1 .5-.5h11a.5.5 0 0 1 0 1h-11a.5.5 0 0 1-.5-.5zm0-3a.5.5 0 0 1 .5-.5h7a.5.5 0 0 1 0 1h-7a.5.5 0 0 1-.5-.5zm0-3a.5.5 0 0 1 .5-.5h11a.5.5 0 0 1 0 1h-11a.5.5 0 0 1-.5-.5z"/>
3
+ </svg>
@@ -0,0 +1,3 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-text-paragraph" viewBox="0 0 16 16">
2
+ <path fill-rule="evenodd" d="M2 12.5a.5.5 0 0 1 .5-.5h7a.5.5 0 0 1 0 1h-7a.5.5 0 0 1-.5-.5zm0-3a.5.5 0 0 1 .5-.5h11a.5.5 0 0 1 0 1h-11a.5.5 0 0 1-.5-.5zm0-3a.5.5 0 0 1 .5-.5h11a.5.5 0 0 1 0 1h-11a.5.5 0 0 1-.5-.5zm4-3a.5.5 0 0 1 .5-.5h7a.5.5 0 0 1 0 1h-7a.5.5 0 0 1-.5-.5z"/>
3
+ </svg>
@@ -0,0 +1,3 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-text-right" viewBox="0 0 16 16">
2
+ <path fill-rule="evenodd" d="M6 12.5a.5.5 0 0 1 .5-.5h7a.5.5 0 0 1 0 1h-7a.5.5 0 0 1-.5-.5zm-4-3a.5.5 0 0 1 .5-.5h11a.5.5 0 0 1 0 1h-11a.5.5 0 0 1-.5-.5zm4-3a.5.5 0 0 1 .5-.5h7a.5.5 0 0 1 0 1h-7a.5.5 0 0 1-.5-.5zm-4-3a.5.5 0 0 1 .5-.5h11a.5.5 0 0 1 0 1h-11a.5.5 0 0 1-.5-.5z"/>
3
+ </svg>
@@ -0,0 +1,3 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-type-bold" viewBox="0 0 16 16">
2
+ <path d="M8.21 13c2.106 0 3.412-1.087 3.412-2.823 0-1.306-.984-2.283-2.324-2.386v-.055a2.176 2.176 0 0 0 1.852-2.14c0-1.51-1.162-2.46-3.014-2.46H3.843V13H8.21zM5.908 4.674h1.696c.963 0 1.517.451 1.517 1.244 0 .834-.629 1.32-1.73 1.32H5.908V4.673zm0 6.788V8.598h1.73c1.217 0 1.88.492 1.88 1.415 0 .943-.643 1.449-1.832 1.449H5.907z"/>
3
+ </svg>
@@ -0,0 +1,3 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-type-italic" viewBox="0 0 16 16">
2
+ <path d="M7.991 11.674 9.53 4.455c.123-.595.246-.71 1.347-.807l.11-.52H7.211l-.11.52c1.06.096 1.128.212 1.005.807L6.57 11.674c-.123.595-.246.71-1.346.806l-.11.52h3.774l.11-.52c-1.06-.095-1.129-.211-1.006-.806z"/>
3
+ </svg>
@@ -0,0 +1,3 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-type-strikethrough" viewBox="0 0 16 16">
2
+ <path d="M6.333 5.686c0 .31.083.581.27.814H5.166a2.776 2.776 0 0 1-.099-.76c0-1.627 1.436-2.768 3.48-2.768 1.969 0 3.39 1.175 3.445 2.85h-1.23c-.11-1.08-.964-1.743-2.25-1.743-1.23 0-2.18.602-2.18 1.607zm2.194 7.478c-2.153 0-3.589-1.107-3.705-2.81h1.23c.144 1.06 1.129 1.703 2.544 1.703 1.34 0 2.31-.705 2.31-1.675 0-.827-.547-1.374-1.914-1.675L8.046 8.5H1v-1h14v1h-3.504c.468.437.675.994.675 1.697 0 1.826-1.436 2.967-3.644 2.967z"/>
3
+ </svg>
@@ -0,0 +1,3 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-type-underline" viewBox="0 0 16 16">
2
+ <path d="M5.313 3.136h-1.23V9.54c0 2.105 1.47 3.623 3.917 3.623s3.917-1.518 3.917-3.623V3.136h-1.23v6.323c0 1.49-.978 2.57-2.687 2.57-1.709 0-2.687-1.08-2.687-2.57V3.136zM12.5 15h-9v-1h9v1z"/>
3
+ </svg>