5htp-core 0.4.8 → 0.4.9

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 (187) hide show
  1. package/package.json +5 -1
  2. package/src/client/assets/css/components/table.less +2 -0
  3. package/src/client/components/Form.ts +1 -1
  4. package/src/client/components/button.tsx +2 -1
  5. package/src/client/components/containers/Popover/index.tsx +2 -2
  6. package/src/client/components/dropdown/index.tsx +16 -6
  7. package/src/client/components/input/Slider/index.tsx +0 -2
  8. package/src/client/components/inputv3/Rte/Editor.tsx +271 -0
  9. package/src/client/components/inputv3/Rte/ToolbarPlugin/BlockFormat.tsx +220 -0
  10. package/src/client/components/inputv3/Rte/ToolbarPlugin/ElementFormat.tsx +107 -0
  11. package/src/client/components/inputv3/Rte/ToolbarPlugin/index.tsx +768 -0
  12. package/src/client/components/inputv3/Rte/appSettings.ts +36 -0
  13. package/src/client/components/inputv3/Rte/context/FlashMessageContext.tsx +68 -0
  14. package/src/client/components/inputv3/Rte/context/SettingsContext.tsx +71 -0
  15. package/src/client/components/inputv3/Rte/context/SharedAutocompleteContext.tsx +71 -0
  16. package/src/client/components/inputv3/Rte/context/SharedHistoryContext.tsx +35 -0
  17. package/src/client/components/inputv3/Rte/currentEditor.ts +42 -0
  18. package/src/client/components/inputv3/Rte/hooks/useFlashMessage.tsx +16 -0
  19. package/src/client/components/inputv3/Rte/hooks/useReport.ts +67 -0
  20. package/src/client/components/inputv3/Rte/images/emoji/1F600.png +0 -0
  21. package/src/client/components/inputv3/Rte/images/emoji/1F641.png +0 -0
  22. package/src/client/components/inputv3/Rte/images/emoji/1F642.png +0 -0
  23. package/src/client/components/inputv3/Rte/images/emoji/2764.png +0 -0
  24. package/src/client/components/inputv3/Rte/images/emoji/LICENSE.md +5 -0
  25. package/src/client/components/inputv3/Rte/images/icons/draggable-block-menu.svg +1 -0
  26. package/src/client/components/inputv3/Rte/images/icons/prettier-error.svg +1 -0
  27. package/src/client/components/inputv3/Rte/images/icons/prettier.svg +1 -0
  28. package/src/client/components/inputv3/Rte/images/image/LICENSE.md +5 -0
  29. package/src/client/components/inputv3/Rte/images/image-broken.svg +4 -0
  30. package/src/client/components/inputv3/Rte/images/logo.svg +1 -0
  31. package/src/client/components/inputv3/Rte/index.tsx +63 -79
  32. package/src/client/components/inputv3/Rte/nodes/AutocompleteNode.tsx +119 -0
  33. package/src/client/components/inputv3/Rte/nodes/EmojiNode.tsx +102 -0
  34. package/src/client/components/inputv3/Rte/nodes/EquationComponent.tsx +141 -0
  35. package/src/client/components/inputv3/Rte/nodes/EquationNode.tsx +174 -0
  36. package/src/client/components/inputv3/Rte/nodes/FigmaNode.tsx +135 -0
  37. package/src/client/components/inputv3/Rte/nodes/ImageComponent.tsx +468 -0
  38. package/src/client/components/inputv3/Rte/nodes/ImageNode.css +43 -0
  39. package/src/client/components/inputv3/Rte/nodes/ImageNode.tsx +266 -0
  40. package/src/client/components/inputv3/Rte/nodes/InlineImageNode/InlineImageComponent.tsx +402 -0
  41. package/src/client/components/inputv3/Rte/nodes/InlineImageNode/InlineImageNode.css +94 -0
  42. package/src/client/components/inputv3/Rte/nodes/InlineImageNode/InlineImageNode.tsx +294 -0
  43. package/src/client/components/inputv3/Rte/nodes/KeywordNode.ts +67 -0
  44. package/src/client/components/inputv3/Rte/nodes/LayoutContainerNode.ts +137 -0
  45. package/src/client/components/inputv3/Rte/nodes/LayoutItemNode.ts +71 -0
  46. package/src/client/components/inputv3/Rte/nodes/MentionNode.ts +130 -0
  47. package/src/client/components/inputv3/Rte/nodes/PageBreakNode/index.css +62 -0
  48. package/src/client/components/inputv3/Rte/nodes/PageBreakNode/index.tsx +170 -0
  49. package/src/client/components/inputv3/Rte/nodes/PlaygroundNodes.ts +76 -0
  50. package/src/client/components/inputv3/Rte/nodes/PollComponent.tsx +249 -0
  51. package/src/client/components/inputv3/Rte/nodes/PollNode.css +187 -0
  52. package/src/client/components/inputv3/Rte/nodes/PollNode.tsx +209 -0
  53. package/src/client/components/inputv3/Rte/nodes/StickyComponent.tsx +261 -0
  54. package/src/client/components/inputv3/Rte/nodes/StickyNode.css +37 -0
  55. package/src/client/components/inputv3/Rte/nodes/StickyNode.tsx +150 -0
  56. package/src/client/components/inputv3/Rte/nodes/TweetNode.tsx +223 -0
  57. package/src/client/components/inputv3/Rte/nodes/YouTubeNode.tsx +184 -0
  58. package/src/client/components/inputv3/Rte/plugins/ActionsPlugin/index.tsx +334 -0
  59. package/src/client/components/inputv3/Rte/plugins/AutoEmbedPlugin/index.tsx +352 -0
  60. package/src/client/components/inputv3/Rte/plugins/AutoLinkPlugin/index.tsx +32 -0
  61. package/src/client/components/inputv3/Rte/plugins/AutocompletePlugin/index.tsx +2529 -0
  62. package/src/client/components/inputv3/Rte/plugins/CodeActionMenuPlugin/components/CopyButton/index.tsx +70 -0
  63. package/src/client/components/inputv3/Rte/plugins/CodeActionMenuPlugin/components/PrettierButton/index.css +14 -0
  64. package/src/client/components/inputv3/Rte/plugins/CodeActionMenuPlugin/components/PrettierButton/index.tsx +156 -0
  65. package/src/client/components/inputv3/Rte/plugins/CodeActionMenuPlugin/index.css +54 -0
  66. package/src/client/components/inputv3/Rte/plugins/CodeActionMenuPlugin/index.tsx +190 -0
  67. package/src/client/components/inputv3/Rte/plugins/CodeActionMenuPlugin/utils.ts +33 -0
  68. package/src/client/components/inputv3/Rte/plugins/CodeHighlightPlugin/index.ts +21 -0
  69. package/src/client/components/inputv3/Rte/plugins/CollapsiblePlugin/Collapsible.css +57 -0
  70. package/src/client/components/inputv3/Rte/plugins/CollapsiblePlugin/CollapsibleContainerNode.ts +168 -0
  71. package/src/client/components/inputv3/Rte/plugins/CollapsiblePlugin/CollapsibleContentNode.ts +127 -0
  72. package/src/client/components/inputv3/Rte/plugins/CollapsiblePlugin/CollapsibleTitleNode.ts +152 -0
  73. package/src/client/components/inputv3/Rte/plugins/CollapsiblePlugin/CollapsibleUtils.ts +17 -0
  74. package/src/client/components/inputv3/Rte/plugins/CollapsiblePlugin/index.ts +284 -0
  75. package/src/client/components/inputv3/Rte/plugins/ComponentPickerPlugin/index.tsx +370 -0
  76. package/src/client/components/inputv3/Rte/plugins/ContextMenuPlugin/index.tsx +270 -0
  77. package/src/client/components/inputv3/Rte/plugins/DocsPlugin/index.tsx +20 -0
  78. package/src/client/components/inputv3/Rte/plugins/DragDropPastePlugin/index.ts +51 -0
  79. package/src/client/components/inputv3/Rte/plugins/DraggableBlockPlugin/index.css +36 -0
  80. package/src/client/components/inputv3/Rte/plugins/DraggableBlockPlugin/index.tsx +43 -0
  81. package/src/client/components/inputv3/Rte/plugins/EmojiPickerPlugin/index.tsx +198 -0
  82. package/src/client/components/inputv3/Rte/plugins/EmojisPlugin/index.ts +75 -0
  83. package/src/client/components/inputv3/Rte/plugins/EquationsPlugin/index.tsx +82 -0
  84. package/src/client/components/inputv3/Rte/plugins/FigmaPlugin/index.tsx +40 -0
  85. package/src/client/components/inputv3/Rte/plugins/FloatingLinkEditorPlugin/index.css +41 -0
  86. package/src/client/components/inputv3/Rte/plugins/FloatingLinkEditorPlugin/index.tsx +393 -0
  87. package/src/client/components/inputv3/Rte/plugins/FloatingTextFormatToolbarPlugin/index.css +141 -0
  88. package/src/client/components/inputv3/Rte/plugins/FloatingTextFormatToolbarPlugin/index.tsx +388 -0
  89. package/src/client/components/inputv3/Rte/plugins/ImagesPlugin/index.tsx +350 -0
  90. package/src/client/components/inputv3/Rte/plugins/InlineImagePlugin/index.tsx +336 -0
  91. package/src/client/components/inputv3/Rte/plugins/KeywordsPlugin/index.ts +56 -0
  92. package/src/client/components/inputv3/Rte/plugins/LayoutPlugin/InsertLayoutDialog.tsx +58 -0
  93. package/src/client/components/inputv3/Rte/plugins/LayoutPlugin/LayoutPlugin.tsx +219 -0
  94. package/src/client/components/inputv3/Rte/plugins/LinkPlugin/index.tsx +34 -0
  95. package/src/client/components/inputv3/Rte/plugins/ListMaxIndentLevelPlugin/index.ts +85 -0
  96. package/src/client/components/inputv3/Rte/plugins/MarkdownShortcutPlugin/index.tsx +16 -0
  97. package/src/client/components/inputv3/Rte/plugins/MarkdownTransformers/index.ts +324 -0
  98. package/src/client/components/inputv3/Rte/plugins/MaxLengthPlugin/index.tsx +53 -0
  99. package/src/client/components/inputv3/Rte/plugins/MentionsPlugin/index.tsx +696 -0
  100. package/src/client/components/inputv3/Rte/plugins/PageBreakPlugin/index.tsx +57 -0
  101. package/src/client/components/inputv3/Rte/plugins/PasteLogPlugin/index.tsx +54 -0
  102. package/src/client/components/inputv3/Rte/plugins/PollPlugin/index.tsx +86 -0
  103. package/src/client/components/inputv3/Rte/plugins/SpeechToTextPlugin/index.ts +125 -0
  104. package/src/client/components/inputv3/Rte/plugins/StickyPlugin/index.ts +22 -0
  105. package/src/client/components/inputv3/Rte/plugins/TabFocusPlugin/index.tsx +65 -0
  106. package/src/client/components/inputv3/Rte/plugins/TableActionMenuPlugin/index.tsx +773 -0
  107. package/src/client/components/inputv3/Rte/plugins/TableCellResizer/index.css +12 -0
  108. package/src/client/components/inputv3/Rte/plugins/TableCellResizer/index.tsx +436 -0
  109. package/src/client/components/inputv3/Rte/plugins/TableHoverActionsPlugin/index.tsx +287 -0
  110. package/src/client/components/inputv3/Rte/plugins/TableOfContentsPlugin/index.css +95 -0
  111. package/src/client/components/inputv3/Rte/plugins/TableOfContentsPlugin/index.tsx +197 -0
  112. package/src/client/components/inputv3/Rte/plugins/TablePlugin.tsx +178 -0
  113. package/src/client/components/inputv3/Rte/plugins/TestRecorderPlugin/index.tsx +468 -0
  114. package/src/client/components/inputv3/Rte/plugins/TreeViewPlugin/index.tsx +26 -0
  115. package/src/client/components/inputv3/Rte/plugins/TwitterPlugin/index.ts +41 -0
  116. package/src/client/components/inputv3/Rte/plugins/TypingPerfPlugin/index.ts +117 -0
  117. package/src/client/components/inputv3/Rte/plugins/YouTubePlugin/index.ts +41 -0
  118. package/src/client/components/inputv3/Rte/shared/canUseDOM.ts +4 -0
  119. package/src/client/components/inputv3/Rte/shared/caretFromPoint.ts +40 -0
  120. package/src/client/components/inputv3/Rte/shared/environment.ts +56 -0
  121. package/src/client/components/inputv3/Rte/shared/invariant.ts +26 -0
  122. package/src/client/components/inputv3/Rte/shared/normalizeClassNames.ts +21 -0
  123. package/src/client/components/inputv3/Rte/shared/react-test-utils.ts +18 -0
  124. package/src/client/components/inputv3/Rte/shared/reactPatches.ts +22 -0
  125. package/src/client/components/inputv3/Rte/shared/simpleDiffWithCursor.ts +49 -0
  126. package/src/client/components/inputv3/Rte/shared/useLayoutEffect.ts +19 -0
  127. package/src/client/components/inputv3/Rte/shared/warnOnlyOnce.ts +20 -0
  128. package/src/client/components/inputv3/Rte/style.less +30 -60
  129. package/src/client/components/inputv3/Rte/themes/CommentEditorTheme.css +13 -0
  130. package/src/client/components/inputv3/Rte/themes/CommentEditorTheme.ts +20 -0
  131. package/src/client/components/inputv3/Rte/themes/PlaygroundEditorTheme.css +447 -0
  132. package/src/client/components/inputv3/Rte/themes/PlaygroundEditorTheme.ts +120 -0
  133. package/src/client/components/inputv3/Rte/themes/StickyEditorTheme.css +13 -0
  134. package/src/client/components/inputv3/Rte/themes/StickyEditorTheme.ts +20 -0
  135. package/src/client/components/inputv3/Rte/ui/ColorPicker.css +88 -0
  136. package/src/client/components/inputv3/Rte/ui/ColorPicker.tsx +365 -0
  137. package/src/client/components/inputv3/Rte/ui/ContentEditable.css +44 -0
  138. package/src/client/components/inputv3/Rte/ui/ContentEditable.tsx +36 -0
  139. package/src/client/components/inputv3/Rte/ui/DropDown.tsx +259 -0
  140. package/src/client/components/inputv3/Rte/ui/DropdownColorPicker.tsx +41 -0
  141. package/src/client/components/inputv3/Rte/ui/EquationEditor.css +38 -0
  142. package/src/client/components/inputv3/Rte/ui/EquationEditor.tsx +56 -0
  143. package/src/client/components/inputv3/Rte/ui/FileInput.tsx +38 -0
  144. package/src/client/components/inputv3/Rte/ui/FlashMessage.css +28 -0
  145. package/src/client/components/inputv3/Rte/ui/FlashMessage.tsx +29 -0
  146. package/src/client/components/inputv3/Rte/ui/ImageResizer.tsx +316 -0
  147. package/src/client/components/inputv3/Rte/ui/Input.css +32 -0
  148. package/src/client/components/inputv3/Rte/ui/KatexRenderer.tsx +54 -0
  149. package/src/client/components/inputv3/Rte/ui/Switch.tsx +36 -0
  150. package/src/client/components/inputv3/Rte/utils/docSerialization.ts +77 -0
  151. package/src/client/components/inputv3/Rte/utils/emoji-list.ts +16615 -0
  152. package/src/client/components/inputv3/Rte/utils/getDOMRangeRect.ts +27 -0
  153. package/src/client/components/inputv3/Rte/utils/getSelectedNode.ts +27 -0
  154. package/src/client/components/inputv3/Rte/utils/guard.ts +10 -0
  155. package/src/client/components/inputv3/Rte/utils/isMobileWidth.ts +7 -0
  156. package/src/client/components/inputv3/Rte/utils/joinClasses.ts +13 -0
  157. package/src/client/components/inputv3/Rte/utils/setFloatingElemPosition.ts +51 -0
  158. package/src/client/components/inputv3/Rte/utils/setFloatingElemPositionForLinkEditor.ts +46 -0
  159. package/src/client/components/inputv3/Rte/utils/swipe.ts +127 -0
  160. package/src/client/components/inputv3/Rte/utils/url.ts +38 -0
  161. package/src/client/components/inputv3/base.tsx +8 -5
  162. package/src/client/components/inputv3/file/index.tsx +11 -5
  163. package/src/common/data/rte/nodes.ts +60 -9
  164. package/src/common/validation/index.ts +21 -2
  165. package/src/common/validation/schema.ts +42 -10
  166. package/src/common/validation/validator.ts +12 -4
  167. package/src/common/validation/validators.ts +82 -53
  168. package/src/server/services/router/http/multipart.ts +0 -1
  169. package/src/server/services/schema/index.ts +24 -2
  170. package/src/server/services/schema/request.ts +3 -2
  171. package/src/server/services/schema/rte.ts +110 -0
  172. package/src/{common/data/rte/index.ts → server/utils/rte.ts} +27 -16
  173. package/src/client/components/inputv3/Rte/ExampleTheme.tsx +0 -42
  174. package/src/client/components/inputv3/Rte/ToolbarPlugin.tsx +0 -167
  175. package/src/client/components/inputv3/Rte/icons/LICENSE.md +0 -5
  176. package/src/client/components/inputv3/Rte/icons/arrow-clockwise.svg +0 -4
  177. package/src/client/components/inputv3/Rte/icons/arrow-counterclockwise.svg +0 -4
  178. package/src/client/components/inputv3/Rte/icons/journal-text.svg +0 -5
  179. package/src/client/components/inputv3/Rte/icons/justify.svg +0 -3
  180. package/src/client/components/inputv3/Rte/icons/text-center.svg +0 -3
  181. package/src/client/components/inputv3/Rte/icons/text-left.svg +0 -3
  182. package/src/client/components/inputv3/Rte/icons/text-paragraph.svg +0 -3
  183. package/src/client/components/inputv3/Rte/icons/text-right.svg +0 -3
  184. package/src/client/components/inputv3/Rte/icons/type-bold.svg +0 -3
  185. package/src/client/components/inputv3/Rte/icons/type-italic.svg +0 -3
  186. package/src/client/components/inputv3/Rte/icons/type-strikethrough.svg +0 -3
  187. package/src/client/components/inputv3/Rte/icons/type-underline.svg +0 -3
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.8",
4
+ "version": "0.4.9",
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,8 @@
13
13
  "framework"
14
14
  ],
15
15
  "dependencies": {
16
+ "@excalidraw/excalidraw": "^0.17.6",
17
+ "@lexical/file": "^0.19.0",
16
18
  "@lexical/headless": "^0.18.0",
17
19
  "@lexical/html": "^0.18.0",
18
20
  "@lexical/react": "^0.18.0",
@@ -36,6 +38,7 @@
36
38
  "express-csp-header": "^5.0.0",
37
39
  "express-fileupload": "^1.2.1",
38
40
  "fast-safe-stringify": "^2.1.1",
41
+ "file-type": "^16.5.3",
39
42
  "formattor": "^0.0.2",
40
43
  "fs-extra": "^10.1.0",
41
44
  "got": "^11.8.3",
@@ -63,6 +66,7 @@
63
66
  "picomatch": "^2.3.1",
64
67
  "preact": "^10.22.1",
65
68
  "preact-render-to-string": "^6.5.5",
69
+ "prettier": "^3.3.3",
66
70
  "react-datetime-picker": "^5.6.0",
67
71
  "react-scrollbars-custom": "^4.0.27",
68
72
  "react-slider": "^2.0.1",
@@ -88,6 +88,8 @@ table {
88
88
  td {
89
89
 
90
90
  cursor: default;
91
+ max-width: 25em;
92
+ overflow: hidden;
91
93
 
92
94
  &.extendable > .row {
93
95
 
@@ -180,7 +180,7 @@ export default function useForm<TFormData extends {}>(
180
180
  fields.current = {} as FieldsAttrs<TFormData>
181
181
  for (const fieldName in schema.fields) {
182
182
 
183
- const validator = schema.fields[fieldName];
183
+ const validator = schema.getFieldValidator(fieldName);
184
184
 
185
185
  fields.current[fieldName] = {
186
186
 
@@ -23,7 +23,7 @@ export type Props = {
23
23
  iconR?: ComponentChild,
24
24
 
25
25
  prefix?: ComponentChild,
26
- children?: ComponentChild,
26
+ children?: ComponentChild | ComponentChild[],
27
27
  suffix?: ComponentChild,
28
28
 
29
29
  tag?: "a" | "button",
@@ -31,6 +31,7 @@ export type Props = {
31
31
  shape?: 'default' | 'icon' | 'tile' | 'pill',
32
32
  size?: TComponentSize,
33
33
  class?: string,
34
+ title?: string,
34
35
 
35
36
  state?: [string, React.StateUpdater<string>],
36
37
  active?: boolean,
@@ -4,7 +4,7 @@
4
4
 
5
5
  // Npm
6
6
  import React from 'react';
7
- import { JSX, ComponentChild } from 'preact';
7
+ import { JSX, ComponentChild, VNode } from 'preact';
8
8
  import type { StateUpdater } from 'preact/hooks';
9
9
 
10
10
  // Libs
@@ -20,7 +20,7 @@ export type Props = JSX.HTMLAttributes<HTMLDivElement> & {
20
20
  id?: string,
21
21
 
22
22
  // Display
23
- content?: JSX.Element,
23
+ content?: ComponentChild | JSX.Element
24
24
  state?: [boolean, StateUpdater<boolean>],
25
25
  width?: number | string,
26
26
  disable?: boolean
@@ -8,15 +8,16 @@ import { ComponentChild, RefObject } from 'preact';
8
8
 
9
9
  // Core
10
10
  import Button, { Props as ButtonProps } from '../button';
11
- import Popover from '../containers/Popover';
11
+ import Popover, { Props as PopoverProps } from '../containers/Popover';
12
12
 
13
13
  /*----------------------------------
14
14
  - TYPES
15
15
  ----------------------------------*/
16
16
 
17
17
  export type Props = ButtonProps & {
18
- content: ComponentChild | (() => ComponentChild),
19
- refDropdown?: RefObject<TDropdownControl>
18
+ label?: ComponentChild,
19
+ refDropdown?: RefObject<TDropdownControl>,
20
+ popover?: Partial<PopoverProps>
20
21
  }
21
22
 
22
23
  export type TDropdownControl = {
@@ -29,8 +30,10 @@ export type TDropdownControl = {
29
30
  export default (props: Props) => {
30
31
 
31
32
  let {
32
- content,
33
+ children,
34
+ label,
33
35
  refDropdown,
36
+ popover,
34
37
  ...buttonProps
35
38
  } = props;
36
39
 
@@ -44,8 +47,15 @@ export default (props: Props) => {
44
47
  }
45
48
 
46
49
  return (
47
- <Popover content={content} state={popoverState}>
48
- <Button {...buttonProps} refElem={refButton} />
50
+ <Popover content={(
51
+ <div class="bg white col menu">
52
+ {children}
53
+ </div>
54
+ )} state={popoverState} {...(popover || {})}>
55
+
56
+ <Button {...buttonProps} iconR={<i src="chevron-down" class="s" />}
57
+ refElem={refButton} children={label} />
58
+
49
59
  </Popover>
50
60
  )
51
61
  }
@@ -9,8 +9,6 @@ import Slider from 'react-slider';
9
9
 
10
10
  // Core libs
11
11
  import { useInput, InputBaseProps } from '../../inputv3/base';
12
- import { default as Validator } from '@common/validation/validator';
13
- import type SchemaValidators from '@common/validation/validators';
14
12
 
15
13
  /*----------------------------------
16
14
  - TYPES
@@ -0,0 +1,271 @@
1
+ /*----------------------------------
2
+ - DEPENDANCES
3
+ ----------------------------------*/
4
+
5
+ // Npm
6
+ import React from 'react';
7
+
8
+ // Lexical
9
+ import { EditorState, createEditor } from 'lexical';
10
+ import { useLexicalComposerContext } from '@lexical/react/LexicalComposerContext';
11
+ import { AutoFocusPlugin } from '@lexical/react/LexicalAutoFocusPlugin';
12
+ import { LexicalComposer } from '@lexical/react/LexicalComposer';
13
+ import { ContentEditable } from '@lexical/react/LexicalContentEditable';
14
+ import { LexicalErrorBoundary } from '@lexical/react/LexicalErrorBoundary';
15
+ import { HistoryPlugin } from '@lexical/react/LexicalHistoryPlugin';
16
+ import { RichTextPlugin } from '@lexical/react/LexicalRichTextPlugin';
17
+ import { OnChangePlugin } from '@lexical/react/LexicalOnChangePlugin';
18
+ import RichEditorUtils from './currentEditor';
19
+ import { CharacterLimitPlugin } from '@lexical/react/LexicalCharacterLimitPlugin';
20
+ import { CheckListPlugin } from '@lexical/react/LexicalCheckListPlugin';
21
+ import { ClearEditorPlugin } from '@lexical/react/LexicalClearEditorPlugin';
22
+ import { ClickableLinkPlugin } from '@lexical/react/LexicalClickableLinkPlugin';
23
+ import { CollaborationPlugin } from '@lexical/react/LexicalCollaborationPlugin';
24
+ import { HashtagPlugin } from '@lexical/react/LexicalHashtagPlugin';
25
+ import { HorizontalRulePlugin } from '@lexical/react/LexicalHorizontalRulePlugin';
26
+ import { ListPlugin } from '@lexical/react/LexicalListPlugin';
27
+ import { PlainTextPlugin } from '@lexical/react/LexicalPlainTextPlugin';
28
+ import { TabIndentationPlugin } from '@lexical/react/LexicalTabIndentationPlugin';
29
+ import { TablePlugin } from '@lexical/react/LexicalTablePlugin';
30
+ import { useLexicalEditable } from '@lexical/react/useLexicalEditable';
31
+
32
+ // Lexical plugins
33
+ //import { CAN_USE_DOM } from 'shared/canUseDOM';
34
+
35
+ import { useSettings } from './context/SettingsContext';
36
+ import { useSharedHistoryContext } from './context/SharedHistoryContext';
37
+ import ActionsPlugin from './plugins/ActionsPlugin';
38
+ import AutocompletePlugin from './plugins/AutocompletePlugin';
39
+ import AutoEmbedPlugin from './plugins/AutoEmbedPlugin';
40
+ import AutoLinkPlugin from './plugins/AutoLinkPlugin';
41
+ import CodeActionMenuPlugin from './plugins/CodeActionMenuPlugin';
42
+ import CodeHighlightPlugin from './plugins/CodeHighlightPlugin';
43
+ import CollapsiblePlugin from './plugins/CollapsiblePlugin';
44
+ import ComponentPickerPlugin from './plugins/ComponentPickerPlugin';
45
+ import ContextMenuPlugin from './plugins/ContextMenuPlugin';
46
+ import DragDropPaste from './plugins/DragDropPastePlugin';
47
+ import DraggableBlockPlugin from './plugins/DraggableBlockPlugin';
48
+ import EmojiPickerPlugin from './plugins/EmojiPickerPlugin';
49
+ import EmojisPlugin from './plugins/EmojisPlugin';
50
+ import FloatingLinkEditorPlugin from './plugins/FloatingLinkEditorPlugin';
51
+ import FloatingTextFormatToolbarPlugin from './plugins/FloatingTextFormatToolbarPlugin';
52
+ import ImagesPlugin from './plugins/ImagesPlugin';
53
+ import InlineImagePlugin from './plugins/InlineImagePlugin';
54
+ import KeywordsPlugin from './plugins/KeywordsPlugin';
55
+ import { LayoutPlugin } from './plugins/LayoutPlugin/LayoutPlugin';
56
+ import LinkPlugin from './plugins/LinkPlugin';
57
+ import ListMaxIndentLevelPlugin from './plugins/ListMaxIndentLevelPlugin';
58
+ import MarkdownShortcutPlugin from './plugins/MarkdownShortcutPlugin';
59
+ import { MaxLengthPlugin } from './plugins/MaxLengthPlugin';
60
+ import MentionsPlugin from './plugins/MentionsPlugin';
61
+ import PageBreakPlugin from './plugins/PageBreakPlugin';
62
+ import PollPlugin from './plugins/PollPlugin';
63
+ import SpeechToTextPlugin from './plugins/SpeechToTextPlugin';
64
+ import TabFocusPlugin from './plugins/TabFocusPlugin';
65
+ import TableCellActionMenuPlugin from './plugins/TableActionMenuPlugin';
66
+ import TableCellResizer from './plugins/TableCellResizer';
67
+ import TableHoverActionsPlugin from './plugins/TableHoverActionsPlugin';
68
+ import TableOfContentsPlugin from './plugins/TableOfContentsPlugin';
69
+ import TreeViewPlugin from './plugins/TreeViewPlugin';
70
+ import TwitterPlugin from './plugins/TwitterPlugin';
71
+ import YouTubePlugin from './plugins/YouTubePlugin';
72
+
73
+ // Core libs
74
+ import editorNodes from '@common/data/rte/nodes';
75
+ import type { Props as TRteProps } from '.';
76
+
77
+ // Special componets
78
+ import ExampleTheme from './themes/PlaygroundEditorTheme';
79
+ import ToolbarPlugin from './ToolbarPlugin';
80
+
81
+ export const EMPTY_STATE = '{"root":{"children":[{"children":[],"direction":null,"format":"","indent":0,"type":"paragraph","version":1}],"direction":null,"format":"","indent":0,"type":"root","version":1}}';
82
+
83
+ /*----------------------------------
84
+ - TYPES
85
+ ----------------------------------*/
86
+
87
+ export type Props = {
88
+ preview?: boolean,
89
+ }
90
+
91
+ const ValueControlPlugin = ({ props, value }) => {
92
+
93
+ const [editor] = useLexicalComposerContext();
94
+
95
+ React.useEffect(() => {
96
+ if (props.value && props.value !== value) {
97
+
98
+ const initialEditorState = editor.parseEditorState(props.value)
99
+ editor.setEditorState(initialEditorState);
100
+ }
101
+ }, [props.value]);
102
+
103
+ return null;
104
+ }
105
+
106
+ /*----------------------------------
107
+ - COMPOSANT
108
+ ----------------------------------*/
109
+ export default ({ value, setValue, props }: {
110
+ value: string,
111
+ setValue: (value: string) => void,
112
+ props: TRteProps
113
+ }) => {
114
+
115
+ /*----------------------------------
116
+ - INIT
117
+ ----------------------------------*/
118
+
119
+ // Trigger onchange oly when finished typing
120
+ const refCommit = React.useRef<NodeJS.Timeout | null>(null);
121
+
122
+ const { historyState } = useSharedHistoryContext();
123
+ const {
124
+ settings: {
125
+ isCollab,
126
+ isAutocomplete,
127
+ isMaxLength,
128
+ isCharLimit,
129
+ hasLinkAttributes,
130
+ isCharLimitUtf8,
131
+ isRichText,
132
+ showTreeView,
133
+ showTableOfContents,
134
+ shouldUseLexicalContextMenu,
135
+ shouldPreserveNewLinesInMarkdown,
136
+ tableCellMerge,
137
+ tableCellBackgroundColor,
138
+ },
139
+ } = useSettings();
140
+
141
+ const [floatingAnchorElem, setFloatingAnchorElem] = React.useState<HTMLDivElement | null>(null);
142
+ const [isSmallWidthViewport, setIsSmallWidthViewport] = React.useState<boolean>(false);
143
+ const [isLinkEditMode, setIsLinkEditMode] = React.useState<boolean>(false);
144
+
145
+ /*----------------------------------
146
+ - ACTIONS
147
+ ----------------------------------*/
148
+
149
+ const onChange = (editorState: EditorState) => {
150
+ editorState.read(() => {
151
+
152
+ if (refCommit.current !== null)
153
+ clearTimeout(refCommit.current);
154
+
155
+ refCommit.current = setTimeout(() => {
156
+
157
+ const stateJson = JSON.stringify(editorState.toJSON());
158
+
159
+ setValue(stateJson);
160
+
161
+ }, 100);
162
+ });
163
+ };
164
+
165
+ /*----------------------------------
166
+ - RENDER
167
+ ----------------------------------*/
168
+ return (
169
+ <LexicalComposer initialConfig={{
170
+ editorState: value || EMPTY_STATE,
171
+ nodes: editorNodes,
172
+ // Handling of errors during update
173
+ onError(error: Error) { throw error; },
174
+ // The editor theme
175
+ theme: ExampleTheme,
176
+ }}>
177
+ <div className="editor-container">
178
+ <ToolbarPlugin setIsLinkEditMode={setIsLinkEditMode} />
179
+ <div className="editor-inner reading">
180
+ <RichTextPlugin
181
+ contentEditable={
182
+ <ContentEditable
183
+ className="editor-input"
184
+ aria-placeholder={"Type text here ..."}
185
+ placeholder={
186
+ <div className="editor-placeholder">Type text here ...</div>
187
+ }
188
+ />
189
+ }
190
+ ErrorBoundary={LexicalErrorBoundary}
191
+ />
192
+
193
+ <HistoryPlugin externalHistoryState={historyState} />
194
+ <AutoFocusPlugin />
195
+ <OnChangePlugin onChange={onChange} />
196
+ <ValueControlPlugin props={props} value={value} />
197
+
198
+ {isMaxLength && <MaxLengthPlugin maxLength={30} />}
199
+ <DragDropPaste />
200
+ <AutoFocusPlugin />
201
+ <ClearEditorPlugin />
202
+ <ComponentPickerPlugin />
203
+ <EmojiPickerPlugin />
204
+ <AutoEmbedPlugin />
205
+
206
+ <MentionsPlugin />
207
+ <EmojisPlugin />
208
+ <HashtagPlugin />
209
+ <KeywordsPlugin />
210
+ <SpeechToTextPlugin />
211
+ <AutoLinkPlugin />
212
+ <CodeHighlightPlugin />
213
+ <ListPlugin />
214
+ <CheckListPlugin />
215
+ <ListMaxIndentLevelPlugin maxDepth={7} />
216
+ <TablePlugin
217
+ hasCellMerge={tableCellMerge}
218
+ hasCellBackgroundColor={tableCellBackgroundColor}
219
+ />
220
+ <TableCellResizer />
221
+ <ImagesPlugin />
222
+ <InlineImagePlugin />
223
+ <LinkPlugin hasLinkAttributes={hasLinkAttributes} />
224
+ <PollPlugin />
225
+ <TwitterPlugin />
226
+ <YouTubePlugin />
227
+ <ClickableLinkPlugin />
228
+ <HorizontalRulePlugin />
229
+ {/* <EquationsPlugin /> */}
230
+ {/* <ExcalidrawPlugin /> */}
231
+ <TabFocusPlugin />
232
+ <TabIndentationPlugin />
233
+ <CollapsiblePlugin />
234
+ <PageBreakPlugin />
235
+ <LayoutPlugin />
236
+
237
+ <MarkdownShortcutPlugin />
238
+
239
+ {floatingAnchorElem && !isSmallWidthViewport && (
240
+ <>
241
+ <DraggableBlockPlugin anchorElem={floatingAnchorElem} />
242
+ <CodeActionMenuPlugin anchorElem={floatingAnchorElem} />
243
+ <FloatingLinkEditorPlugin
244
+ anchorElem={floatingAnchorElem}
245
+ isLinkEditMode={isLinkEditMode}
246
+ setIsLinkEditMode={setIsLinkEditMode}
247
+ />
248
+ <TableCellActionMenuPlugin
249
+ anchorElem={floatingAnchorElem}
250
+ cellMerge={true}
251
+ />
252
+ <TableHoverActionsPlugin anchorElem={floatingAnchorElem} />
253
+ <FloatingTextFormatToolbarPlugin
254
+ anchorElem={floatingAnchorElem}
255
+ setIsLinkEditMode={setIsLinkEditMode}
256
+ />
257
+ </>
258
+ )}
259
+
260
+ {(isCharLimit || isCharLimitUtf8) && (
261
+ <CharacterLimitPlugin
262
+ charset={isCharLimit ? 'UTF-16' : 'UTF-8'}
263
+ maxLength={5}
264
+ />
265
+ )}
266
+ {isAutocomplete && <AutocompletePlugin />}
267
+ </div>
268
+ </div>
269
+ </LexicalComposer>
270
+ )
271
+ }
@@ -0,0 +1,220 @@
1
+ /*----------------------------------
2
+ - DEPENDANCES
3
+ ----------------------------------*/
4
+
5
+ // npm
6
+ import React, { JSX } from 'react';
7
+ import {
8
+ $createParagraphNode,
9
+ $getSelection,
10
+ $isRangeSelection,
11
+ LexicalEditor,
12
+ } from 'lexical';
13
+
14
+ import {
15
+ $setBlocksType,
16
+ } from '@lexical/selection';
17
+
18
+ import {
19
+ $createHeadingNode,
20
+ $createQuoteNode,
21
+ HeadingTagType,
22
+ } from '@lexical/rich-text';
23
+
24
+ import {
25
+ INSERT_CHECK_LIST_COMMAND,
26
+ INSERT_ORDERED_LIST_COMMAND,
27
+ INSERT_UNORDERED_LIST_COMMAND,
28
+ } from '@lexical/list';
29
+
30
+ import {
31
+ $createCodeNode,
32
+ } from '@lexical/code';
33
+
34
+ // Core
35
+ import Button from '@client/components/button';
36
+ import DropDown from '@client/components/dropdown';
37
+
38
+ /*----------------------------------
39
+ - TYPES
40
+ ----------------------------------*/
41
+
42
+ const formatParagraph = (editor: LexicalEditor) => {
43
+ editor.update(() => {
44
+ const selection = $getSelection();
45
+ if ($isRangeSelection(selection)) {
46
+ $setBlocksType(selection, () => $createParagraphNode());
47
+ }
48
+ });
49
+ };
50
+
51
+ const formatHeading = (headingSize: HeadingTagType) => (editor: LexicalEditor, blockType: typeof blockTypeNames[number]) => {
52
+ if (blockType !== headingSize) {
53
+ editor.update(() => {
54
+ const selection = $getSelection();
55
+ $setBlocksType(selection, () => $createHeadingNode(headingSize));
56
+ });
57
+ }
58
+ };
59
+
60
+ const formatBulletList = (editor: LexicalEditor, blockType: typeof blockTypeNames[number]) => {
61
+ if (blockType !== 'bullet') {
62
+ editor.dispatchCommand(INSERT_UNORDERED_LIST_COMMAND, undefined);
63
+ } else {
64
+ formatParagraph(editor);
65
+ }
66
+ };
67
+
68
+ const formatCheckList = (editor: LexicalEditor, blockType: typeof blockTypeNames[number]) => {
69
+ if (blockType !== 'check') {
70
+ editor.dispatchCommand(INSERT_CHECK_LIST_COMMAND, undefined);
71
+ } else {
72
+ formatParagraph(editor);
73
+ }
74
+ };
75
+
76
+ const formatNumberedList = (editor: LexicalEditor, blockType: typeof blockTypeNames[number]) => {
77
+ if (blockType !== 'number') {
78
+ editor.dispatchCommand(INSERT_ORDERED_LIST_COMMAND, undefined);
79
+ } else {
80
+ formatParagraph(editor);
81
+ }
82
+ };
83
+
84
+ const formatQuote = (editor: LexicalEditor, blockType: typeof blockTypeNames[number]) => {
85
+ if (blockType !== 'quote') {
86
+ editor.update(() => {
87
+ const selection = $getSelection();
88
+ $setBlocksType(selection, () => $createQuoteNode());
89
+ });
90
+ }
91
+ };
92
+
93
+ const formatCode = (editor: LexicalEditor, blockType: typeof blockTypeNames[number]) => {
94
+ if (blockType !== 'code') {
95
+ editor.update(() => {
96
+ let selection = $getSelection();
97
+
98
+ if (selection !== null) {
99
+ if (selection.isCollapsed()) {
100
+ $setBlocksType(selection, () => $createCodeNode());
101
+ } else {
102
+ const textContent = selection.getTextContent();
103
+ const codeNode = $createCodeNode();
104
+ selection.insertNodes([codeNode]);
105
+ selection = $getSelection();
106
+ if ($isRangeSelection(selection)) {
107
+ selection.insertRawText(textContent);
108
+ }
109
+ }
110
+ }
111
+ });
112
+ }
113
+ };
114
+
115
+ const blockTypes: {
116
+ label: string;
117
+ value: string;
118
+ icon: string;
119
+ onClick: (editor: LexicalEditor, blockType: string) => void;
120
+ }[] = [{
121
+ label: 'Bulleted List',
122
+ value: 'bullet',
123
+ icon: /* @icon */'list-ul',
124
+ onClick: formatBulletList,
125
+ }, {
126
+ label: 'Check List',
127
+ value: 'check',
128
+ icon: /* @icon */'check-square',
129
+ onClick: formatCheckList,
130
+ }, {
131
+ label: 'Code Block',
132
+ value: 'code',
133
+ icon: /* @icon */'code',
134
+ onClick: formatCode,
135
+ }, {
136
+ label: 'Heading 1',
137
+ value: 'h1',
138
+ icon: /* @icon */'h1',
139
+ onClick: formatHeading('h1'),
140
+ }, {
141
+ label: 'Heading 2',
142
+ value: 'h2',
143
+ icon: /* @icon */'h2',
144
+ onClick: formatHeading('h2'),
145
+ }, {
146
+ label: 'Heading 3',
147
+ value: 'h3',
148
+ icon: /* @icon */'h3',
149
+ onClick: formatHeading('h3'),
150
+ }, {
151
+ label: 'Heading 4',
152
+ value: 'h4',
153
+ icon: /* @icon */'h4',
154
+ onClick: formatHeading('h4'),
155
+ }, {
156
+ label: 'Heading 5',
157
+ value: 'h5',
158
+ icon: /* @icon */'h5',
159
+ onClick: formatHeading('h5'),
160
+ }, {
161
+ label: 'Heading 6',
162
+ value: 'h6',
163
+ icon: /* @icon */'h6',
164
+ onClick: formatHeading('h6'),
165
+ }, {
166
+ label: 'Numbered List',
167
+ value: 'number',
168
+ icon: /* @icon */'list-ol',
169
+ onClick: formatNumberedList,
170
+
171
+ }, {
172
+ label: 'Normal',
173
+ value: 'paragraph',
174
+ icon: /* @icon */'paragraph',
175
+ onClick: formatParagraph,
176
+ }, {
177
+ label: 'Quote',
178
+ value: 'quote',
179
+ icon: /* @icon */'quote-left',
180
+ onClick: formatQuote,
181
+ }];
182
+
183
+ export const blockTypeNames = blockTypes.map((type) => type.value);
184
+
185
+ export const rootTypeToRootName = {
186
+ root: 'Root',
187
+ table: 'Table',
188
+ };
189
+
190
+ /*----------------------------------
191
+ - COMPONENT
192
+ ----------------------------------*/
193
+ export default function BlockFormatDropDown({
194
+ editor,
195
+ blockType,
196
+ rootType,
197
+ disabled = false,
198
+ }: {
199
+ blockType: typeof blockTypeNames[number];
200
+ rootType: keyof typeof rootTypeToRootName;
201
+ editor: LexicalEditor;
202
+ disabled?: boolean;
203
+ }): JSX.Element {
204
+
205
+ const currentBlockType = blockTypes.find((type) => type.value === blockType);
206
+
207
+ return (
208
+ <DropDown disabled={disabled} icon={currentBlockType ? currentBlockType.icon : 'question'} size="s"
209
+ label={currentBlockType ? currentBlockType.label : 'Unknown Block Type'}
210
+ popover={{ tag: 'li' }}
211
+ >
212
+ {blockTypes.map((block) => (
213
+ <Button icon={block.icon}
214
+ onClick={() => block.onClick(editor, blockType)}>
215
+ {block.label}
216
+ </Button>
217
+ ))}
218
+ </DropDown>
219
+ );
220
+ }