@collabchron/notiq 0.2.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 (188) hide show
  1. package/README.md +71 -0
  2. package/components.json +21 -0
  3. package/eslint.config.mjs +16 -0
  4. package/next.config.ts +12 -0
  5. package/package.json +108 -0
  6. package/postcss.config.mjs +5 -0
  7. package/public/file.svg +1 -0
  8. package/public/globe.svg +1 -0
  9. package/public/images/icons/plus.svg +10 -0
  10. package/public/next.svg +1 -0
  11. package/public/vercel.svg +1 -0
  12. package/public/window.svg +1 -0
  13. package/src/app/actions.ts +2 -0
  14. package/src/app/api/ai/route.ts +175 -0
  15. package/src/app/api/edgestore/[...edgestore]/route.ts +28 -0
  16. package/src/app/favicon.ico +0 -0
  17. package/src/app/globals.css +205 -0
  18. package/src/app/layout.tsx +38 -0
  19. package/src/app/page.tsx +12 -0
  20. package/src/components/editor/Core.tsx +220 -0
  21. package/src/components/editor/hooks/instructions-messages.ts +300 -0
  22. package/src/components/editor/hooks/use-mobile.ts +19 -0
  23. package/src/components/editor/hooks/useReport.ts +67 -0
  24. package/src/components/editor/hooks/useResizeObservert.ts +22 -0
  25. package/src/components/editor/index.tsx +39 -0
  26. package/src/components/editor/lexical-on-change.tsx +28 -0
  27. package/src/components/editor/nodes/CollapsibleNode/CollapsibleContainerNode.ts +92 -0
  28. package/src/components/editor/nodes/CollapsibleNode/CollapsibleContentNode.ts +65 -0
  29. package/src/components/editor/nodes/CollapsibleNode/CollapsibleTitleNode.ts +105 -0
  30. package/src/components/editor/nodes/EquationNode/EquationComponent.tsx +143 -0
  31. package/src/components/editor/nodes/EquationNode/EquationNode.tsx +170 -0
  32. package/src/components/editor/nodes/ExcalidrawNode/ExcalidrawComponent.tsx +228 -0
  33. package/src/components/editor/nodes/ExcalidrawNode/ExcalidrawImage.tsx +137 -0
  34. package/src/components/editor/nodes/ExcalidrawNode/ImageResizer.tsx +317 -0
  35. package/src/components/editor/nodes/ExcalidrawNode/index.tsx +204 -0
  36. package/src/components/editor/nodes/FigmaNode/FigmaNode.tsx +134 -0
  37. package/src/components/editor/nodes/Hint/HintComponet.tsx +221 -0
  38. package/src/components/editor/nodes/Hint/index.tsx +190 -0
  39. package/src/components/editor/nodes/ImageNode/index.tsx +328 -0
  40. package/src/components/editor/nodes/InlineImageNode/InlineImageComponent.tsx +383 -0
  41. package/src/components/editor/nodes/InlineImageNode/InlineImageNode.css +94 -0
  42. package/src/components/editor/nodes/InlineImageNode/InlineImageNode.tsx +309 -0
  43. package/src/components/editor/nodes/LayoutNode/LayoutContainerNode.ts +146 -0
  44. package/src/components/editor/nodes/LayoutNode/LayoutItemNode.ts +79 -0
  45. package/src/components/editor/nodes/PollNode/index.tsx +204 -0
  46. package/src/components/editor/nodes/Stepper/index.tsx +260 -0
  47. package/src/components/editor/nodes/TweetNode/index.tsx +214 -0
  48. package/src/components/editor/nodes/index.ts +81 -0
  49. package/src/components/editor/plugins/AutoEmbedPlugin/index.tsx +350 -0
  50. package/src/components/editor/plugins/AutoLinkPlugin/index.tsx +56 -0
  51. package/src/components/editor/plugins/CodeActionMenuPlugin/components/CopyButton.tsx +70 -0
  52. package/src/components/editor/plugins/CodeActionMenuPlugin/components/PrettierButton.tsx +192 -0
  53. package/src/components/editor/plugins/CodeActionMenuPlugin/index.tsx +217 -0
  54. package/src/components/editor/plugins/CodeActionMenuPlugin/utils.ts +26 -0
  55. package/src/components/editor/plugins/CodeHighlightPlugin/index.ts +21 -0
  56. package/src/components/editor/plugins/CollapsiblePlugin/Collapsible.css +76 -0
  57. package/src/components/editor/plugins/CollapsiblePlugin/index.ts +228 -0
  58. package/src/components/editor/plugins/DragDropPastePlugin/index.tsx +44 -0
  59. package/src/components/editor/plugins/DraggableBlockPlugin/index.tsx +52 -0
  60. package/src/components/editor/plugins/EquationsPlugin/index.tsx +85 -0
  61. package/src/components/editor/plugins/ExcalidrawPlugin/index.tsx +98 -0
  62. package/src/components/editor/plugins/FigmaPlugin/index.tsx +42 -0
  63. package/src/components/editor/plugins/FloatingLinkEditorPlugin/index.tsx +445 -0
  64. package/src/components/editor/plugins/FloatingTextFormatToolbarPlugin/index.tsx +275 -0
  65. package/src/components/editor/plugins/ImagesPlugin/index.tsx +222 -0
  66. package/src/components/editor/plugins/InlineImagePlugin/index.tsx +351 -0
  67. package/src/components/editor/plugins/LayoutPlugin/index.tsx +238 -0
  68. package/src/components/editor/plugins/LinkPlugin/index.tsx +36 -0
  69. package/src/components/editor/plugins/LinkWithMetaData/index.tsx +271 -0
  70. package/src/components/editor/plugins/MarkdownShortcutPlugin/index.tsx +11 -0
  71. package/src/components/editor/plugins/MarkdownTransformers/index.tsx +304 -0
  72. package/src/components/editor/plugins/PollPlugin/index.tsx +49 -0
  73. package/src/components/editor/plugins/ShortcutsPlugin/index.tsx +180 -0
  74. package/src/components/editor/plugins/ShortcutsPlugin/shortcuts.ts +253 -0
  75. package/src/components/editor/plugins/SlashCommand/index.tsx +621 -0
  76. package/src/components/editor/plugins/SpeechToTextPlugin/index.ts +127 -0
  77. package/src/components/editor/plugins/TabFocusPlugin/index.ts +58 -0
  78. package/src/components/editor/plugins/TableCellActionMenuPlugin/index.tsx +759 -0
  79. package/src/components/editor/plugins/TableCellResizer/index.tsx +438 -0
  80. package/src/components/editor/plugins/TableHoverActionsPlugin/index.tsx +314 -0
  81. package/src/components/editor/plugins/TablePlugin/index.tsx +99 -0
  82. package/src/components/editor/plugins/ToolbarPlugin/index.tsx +522 -0
  83. package/src/components/editor/plugins/TwitterPlugin/index.ts +35 -0
  84. package/src/components/editor/plugins/YouTubeNode/index.tsx +179 -0
  85. package/src/components/editor/plugins/YouTubePlugin/index.ts +41 -0
  86. package/src/components/editor/themes/editor-theme.ts +113 -0
  87. package/src/components/editor/themes/theme.css +377 -0
  88. package/src/components/editor/utils/ai.ts +291 -0
  89. package/src/components/editor/utils/canUseDOM.ts +12 -0
  90. package/src/components/editor/utils/editorFormatting.ts +282 -0
  91. package/src/components/editor/utils/environment.ts +50 -0
  92. package/src/components/editor/utils/extract-data.ts +166 -0
  93. package/src/components/editor/utils/getAllLexicalChildren.ts +13 -0
  94. package/src/components/editor/utils/getDOMRangeRect.ts +27 -0
  95. package/src/components/editor/utils/getSelectedNode.ts +27 -0
  96. package/src/components/editor/utils/gif.ts +29 -0
  97. package/src/components/editor/utils/invariant.ts +15 -0
  98. package/src/components/editor/utils/setFloatingElemPosition.ts +51 -0
  99. package/src/components/editor/utils/setFloatingElemPositionForLinkEditor.ts +40 -0
  100. package/src/components/editor/utils/setNodePlaceholderFromSelection/getNodePlaceholder.ts +51 -0
  101. package/src/components/editor/utils/setNodePlaceholderFromSelection/setNodePlaceholderFromSelection.ts +15 -0
  102. package/src/components/editor/utils/setNodePlaceholderFromSelection/setPlaceholderOnSelection.ts +114 -0
  103. package/src/components/editor/utils/setNodePlaceholderFromSelection/styles.css +6 -0
  104. package/src/components/editor/utils/url.ts +109 -0
  105. package/src/components/editor/utils/useLayoutEffect.ts +13 -0
  106. package/src/components/providers/QueryProvider.tsx +15 -0
  107. package/src/components/providers/SharedHistoryContext.tsx +28 -0
  108. package/src/components/providers/ToolbarContext.tsx +123 -0
  109. package/src/components/providers/theme-provider.tsx +11 -0
  110. package/src/components/theme/ModeToggle.tsx +40 -0
  111. package/src/components/ui/FileInput.tsx +40 -0
  112. package/src/components/ui/Input.css +32 -0
  113. package/src/components/ui/Select.css +42 -0
  114. package/src/components/ui/Select.tsx +36 -0
  115. package/src/components/ui/TextInput.tsx +48 -0
  116. package/src/components/ui/ai/ai-button.tsx +574 -0
  117. package/src/components/ui/ai/border.tsx +99 -0
  118. package/src/components/ui/ai/placeholder-input-vanish.tsx +282 -0
  119. package/src/components/ui/button.tsx +89 -0
  120. package/src/components/ui/card.tsx +76 -0
  121. package/src/components/ui/checkbox.tsx +30 -0
  122. package/src/components/ui/command.tsx +153 -0
  123. package/src/components/ui/dialog/Dialog.css +25 -0
  124. package/src/components/ui/dialog/Dialog.tsx +34 -0
  125. package/src/components/ui/dialog.tsx +122 -0
  126. package/src/components/ui/drop-downs/background-color.tsx +183 -0
  127. package/src/components/ui/drop-downs/block-format.tsx +159 -0
  128. package/src/components/ui/drop-downs/code.tsx +42 -0
  129. package/src/components/ui/drop-downs/color.tsx +177 -0
  130. package/src/components/ui/drop-downs/font-size.tsx +138 -0
  131. package/src/components/ui/drop-downs/font.tsx +155 -0
  132. package/src/components/ui/drop-downs/index.tsx +122 -0
  133. package/src/components/ui/drop-downs/insert-node.tsx +213 -0
  134. package/src/components/ui/drop-downs/text-align.tsx +123 -0
  135. package/src/components/ui/drop-downs/text-format.tsx +104 -0
  136. package/src/components/ui/dropdown-menu.tsx +201 -0
  137. package/src/components/ui/equation/EquationEditor.css +38 -0
  138. package/src/components/ui/equation/EquationEditor.tsx +56 -0
  139. package/src/components/ui/equation/KatexEquationAlterer.css +41 -0
  140. package/src/components/ui/equation/KatexEquationAlterer.tsx +83 -0
  141. package/src/components/ui/equation/KatexRenderer.tsx +66 -0
  142. package/src/components/ui/excalidraw/ExcalidrawModal.css +64 -0
  143. package/src/components/ui/excalidraw/ExcalidrawModal.tsx +234 -0
  144. package/src/components/ui/excalidraw/Modal.css +62 -0
  145. package/src/components/ui/excalidraw/Modal.tsx +110 -0
  146. package/src/components/ui/hover-card.tsx +29 -0
  147. package/src/components/ui/image/error-image.tsx +17 -0
  148. package/src/components/ui/image/file-upload.tsx +240 -0
  149. package/src/components/ui/image/image-resizer.tsx +297 -0
  150. package/src/components/ui/image/image-toolbar.tsx +264 -0
  151. package/src/components/ui/image/index.tsx +408 -0
  152. package/src/components/ui/image/lazy-image.tsx +68 -0
  153. package/src/components/ui/image/lazy-video.tsx +71 -0
  154. package/src/components/ui/input.tsx +22 -0
  155. package/src/components/ui/models/custom-dialog.tsx +320 -0
  156. package/src/components/ui/models/insert-gif.tsx +90 -0
  157. package/src/components/ui/models/insert-image.tsx +52 -0
  158. package/src/components/ui/models/insert-poll.tsx +29 -0
  159. package/src/components/ui/models/insert-table.tsx +62 -0
  160. package/src/components/ui/models/use-model.tsx +91 -0
  161. package/src/components/ui/poll/poll-component.tsx +304 -0
  162. package/src/components/ui/popover.tsx +33 -0
  163. package/src/components/ui/progress.tsx +28 -0
  164. package/src/components/ui/scroll-area.tsx +48 -0
  165. package/src/components/ui/separator.tsx +31 -0
  166. package/src/components/ui/skeleton.tsx +15 -0
  167. package/src/components/ui/sonner.tsx +31 -0
  168. package/src/components/ui/stepper/step.tsx +179 -0
  169. package/src/components/ui/stepper/stepper.tsx +89 -0
  170. package/src/components/ui/textarea.tsx +22 -0
  171. package/src/components/ui/toggle.tsx +71 -0
  172. package/src/components/ui/tooltip.tsx +32 -0
  173. package/src/components/ui/write/text-format-floting-toolbar.tsx +346 -0
  174. package/src/lib/edgestore.ts +9 -0
  175. package/src/lib/pinecone-client.ts +0 -0
  176. package/src/lib/utils.ts +6 -0
  177. package/src/utils/docSerialization.ts +77 -0
  178. package/src/utils/emoji-list.ts +16615 -0
  179. package/src/utils/getDOMRangeRect.ts +27 -0
  180. package/src/utils/getSelectedNode.ts +27 -0
  181. package/src/utils/getThemeSelector.ts +25 -0
  182. package/src/utils/isMobileWidth.ts +7 -0
  183. package/src/utils/joinClasses.ts +13 -0
  184. package/src/utils/setFloatingElemPosition.ts +74 -0
  185. package/src/utils/setFloatingElemPositionForLinkEditor.ts +46 -0
  186. package/src/utils/swipe.ts +127 -0
  187. package/src/utils/url.ts +38 -0
  188. package/tsconfig.json +27 -0
@@ -0,0 +1,309 @@
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
+
9
+ import type {
10
+ DOMConversionMap,
11
+ DOMConversionOutput,
12
+ DOMExportOutput,
13
+ EditorConfig,
14
+ LexicalEditor,
15
+ LexicalNode,
16
+ LexicalUpdateJSON,
17
+ NodeKey,
18
+ SerializedEditor,
19
+ SerializedLexicalNode,
20
+ Spread,
21
+ } from 'lexical';
22
+ import type {JSX} from 'react';
23
+
24
+ import {
25
+ addClassNamesToElement,
26
+ removeClassNamesFromElement,
27
+ } from '@lexical/utils';
28
+ import {
29
+ $applyNodeReplacement,
30
+ createEditor,
31
+ DecoratorNode,
32
+ isHTMLElement,
33
+ } from 'lexical';
34
+ import * as React from 'react';
35
+
36
+ const InlineImageComponent = React.lazy(() => import('./InlineImageComponent'));
37
+
38
+ export type Position = 'left' | 'right' | 'full' | undefined;
39
+
40
+ export interface InlineImagePayload {
41
+ altText: string;
42
+ caption?: LexicalEditor;
43
+ height?: number;
44
+ key?: NodeKey;
45
+ showCaption?: boolean;
46
+ src: string;
47
+ width?: number;
48
+ position?: Position;
49
+ }
50
+
51
+ export interface UpdateInlineImagePayload {
52
+ altText?: string;
53
+ showCaption?: boolean;
54
+ position?: Position;
55
+ }
56
+
57
+ function $convertInlineImageElement(domNode: Node): null | DOMConversionOutput {
58
+ if (isHTMLElement(domNode) && domNode.nodeName === 'IMG') {
59
+ const {alt: altText, src, width, height} = domNode as HTMLImageElement;
60
+ const node = $createInlineImageNode({altText, height, src, width});
61
+ return {node};
62
+ }
63
+ return null;
64
+ }
65
+
66
+ export type SerializedInlineImageNode = Spread<
67
+ {
68
+ altText: string;
69
+ caption: SerializedEditor;
70
+ height?: number;
71
+ showCaption: boolean;
72
+ src: string;
73
+ width?: number;
74
+ position?: Position;
75
+ },
76
+ SerializedLexicalNode
77
+ >;
78
+
79
+ function getPositionClass(position: Position | undefined): string | undefined {
80
+ return typeof position === 'string' ? `position-${position}` : undefined;
81
+ }
82
+
83
+ export class InlineImageNode extends DecoratorNode<JSX.Element> {
84
+ __src: string;
85
+ __altText: string;
86
+ __width: 'inherit' | number;
87
+ __height: 'inherit' | number;
88
+ __showCaption: boolean;
89
+ __caption: LexicalEditor;
90
+ __position: Position;
91
+
92
+ static getType(): string {
93
+ return 'inline-image';
94
+ }
95
+
96
+ static clone(node: InlineImageNode): InlineImageNode {
97
+ return new InlineImageNode(
98
+ node.__src,
99
+ node.__altText,
100
+ node.__position,
101
+ node.__width,
102
+ node.__height,
103
+ node.__showCaption,
104
+ node.__caption,
105
+ node.__key,
106
+ );
107
+ }
108
+
109
+ static importJSON(
110
+ serializedNode: SerializedInlineImageNode,
111
+ ): InlineImageNode {
112
+ const {altText, height, width, src, showCaption, position} = serializedNode;
113
+ return $createInlineImageNode({
114
+ altText,
115
+ height,
116
+ position,
117
+ showCaption,
118
+ src,
119
+ width,
120
+ }).updateFromJSON(serializedNode);
121
+ }
122
+
123
+ updateFromJSON(
124
+ serializedNode: LexicalUpdateJSON<SerializedInlineImageNode>,
125
+ ): this {
126
+ const {caption} = serializedNode;
127
+ const node = super.updateFromJSON(serializedNode);
128
+ const nestedEditor = node.__caption;
129
+ const editorState = nestedEditor.parseEditorState(caption.editorState);
130
+ if (!editorState.isEmpty()) {
131
+ nestedEditor.setEditorState(editorState);
132
+ }
133
+ return node;
134
+ }
135
+
136
+ static importDOM(): DOMConversionMap | null {
137
+ return {
138
+ img: (node: Node) => ({
139
+ conversion: $convertInlineImageElement,
140
+ priority: 0,
141
+ }),
142
+ };
143
+ }
144
+
145
+ constructor(
146
+ src: string,
147
+ altText: string,
148
+ position: Position,
149
+ width?: 'inherit' | number,
150
+ height?: 'inherit' | number,
151
+ showCaption?: boolean,
152
+ caption?: LexicalEditor,
153
+ key?: NodeKey,
154
+ ) {
155
+ super(key);
156
+ this.__src = src;
157
+ this.__altText = altText;
158
+ this.__width = width || 'inherit';
159
+ this.__height = height || 'inherit';
160
+ this.__showCaption = showCaption || false;
161
+ this.__caption = caption || createEditor();
162
+ this.__position = position;
163
+ }
164
+
165
+ exportDOM(): DOMExportOutput {
166
+ const element = document.createElement('img');
167
+ element.setAttribute('src', this.__src);
168
+ element.setAttribute('alt', this.__altText);
169
+ element.setAttribute('width', this.__width.toString());
170
+ element.setAttribute('height', this.__height.toString());
171
+ return {element};
172
+ }
173
+
174
+ exportJSON(): SerializedInlineImageNode {
175
+ return {
176
+ ...super.exportJSON(),
177
+ altText: this.getAltText(),
178
+ caption: this.__caption.toJSON(),
179
+ height: this.__height === 'inherit' ? 0 : this.__height,
180
+ position: this.__position,
181
+ showCaption: this.__showCaption,
182
+ src: this.getSrc(),
183
+ width: this.__width === 'inherit' ? 0 : this.__width,
184
+ };
185
+ }
186
+
187
+ getSrc(): string {
188
+ return this.__src;
189
+ }
190
+
191
+ getAltText(): string {
192
+ return this.__altText;
193
+ }
194
+
195
+ setAltText(altText: string): void {
196
+ const writable = this.getWritable();
197
+ writable.__altText = altText;
198
+ }
199
+
200
+ setWidthAndHeight(
201
+ width: 'inherit' | number,
202
+ height: 'inherit' | number,
203
+ ): void {
204
+ const writable = this.getWritable();
205
+ writable.__width = width;
206
+ writable.__height = height;
207
+ }
208
+
209
+ getShowCaption(): boolean {
210
+ return this.__showCaption;
211
+ }
212
+
213
+ setShowCaption(showCaption: boolean): void {
214
+ const writable = this.getWritable();
215
+ writable.__showCaption = showCaption;
216
+ }
217
+
218
+ getPosition(): Position {
219
+ return this.__position;
220
+ }
221
+
222
+ setPosition(position: Position): void {
223
+ const writable = this.getWritable();
224
+ writable.__position = position;
225
+ }
226
+
227
+ update(payload: UpdateInlineImagePayload): void {
228
+ const writable = this.getWritable();
229
+ const {altText, showCaption, position} = payload;
230
+ if (altText !== undefined) {
231
+ writable.__altText = altText;
232
+ }
233
+ if (showCaption !== undefined) {
234
+ writable.__showCaption = showCaption;
235
+ }
236
+ if (position !== undefined) {
237
+ writable.__position = position;
238
+ }
239
+ }
240
+
241
+ // View
242
+
243
+ createDOM(config: EditorConfig): HTMLElement {
244
+ const span = document.createElement('span');
245
+ for (const cls of [
246
+ config.theme.inlineImage,
247
+ getPositionClass(this.__position),
248
+ ]) {
249
+ if (cls) {
250
+ addClassNamesToElement(span, cls);
251
+ }
252
+ }
253
+ return span;
254
+ }
255
+
256
+ updateDOM(prevNode: this, dom: HTMLElement, config: EditorConfig): false {
257
+ const position = this.__position;
258
+ if (position !== prevNode.__position) {
259
+ removeClassNamesFromElement(dom, getPositionClass(prevNode.__position));
260
+ addClassNamesToElement(dom, getPositionClass(position));
261
+ }
262
+ return false;
263
+ }
264
+
265
+ decorate(): JSX.Element {
266
+ return (
267
+ <InlineImageComponent
268
+ src={this.__src}
269
+ altText={this.__altText}
270
+ width={this.__width}
271
+ height={this.__height}
272
+ nodeKey={this.getKey()}
273
+ showCaption={this.__showCaption}
274
+ caption={this.__caption}
275
+ position={this.__position}
276
+ />
277
+ );
278
+ }
279
+ }
280
+
281
+ export function $createInlineImageNode({
282
+ altText,
283
+ position,
284
+ height,
285
+ src,
286
+ width,
287
+ showCaption,
288
+ caption,
289
+ key,
290
+ }: InlineImagePayload): InlineImageNode {
291
+ return $applyNodeReplacement(
292
+ new InlineImageNode(
293
+ src,
294
+ altText,
295
+ position,
296
+ width,
297
+ height,
298
+ showCaption,
299
+ caption,
300
+ key,
301
+ ),
302
+ );
303
+ }
304
+
305
+ export function $isInlineImageNode(
306
+ node: LexicalNode | null | undefined,
307
+ ): node is InlineImageNode {
308
+ return node instanceof InlineImageNode;
309
+ }
@@ -0,0 +1,146 @@
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
+
9
+ import type {
10
+ DOMConversionMap,
11
+ DOMConversionOutput,
12
+ DOMExportOutput,
13
+ EditorConfig,
14
+ LexicalNode,
15
+ LexicalUpdateJSON,
16
+ NodeKey,
17
+ SerializedElementNode,
18
+ Spread,
19
+ } from 'lexical';
20
+
21
+ import {addClassNamesToElement} from '@lexical/utils';
22
+ import {ElementNode} from 'lexical';
23
+
24
+ export type SerializedLayoutContainerNode = Spread<
25
+ {
26
+ templateColumns: string;
27
+ },
28
+ SerializedElementNode
29
+ >;
30
+
31
+ function $convertLayoutContainerElement(
32
+ domNode: HTMLElement,
33
+ ): DOMConversionOutput | null {
34
+ const styleAttributes = window.getComputedStyle(domNode);
35
+ const templateColumns = styleAttributes.getPropertyValue(
36
+ 'grid-template-columns',
37
+ );
38
+ if (templateColumns) {
39
+ const node = $createLayoutContainerNode(templateColumns);
40
+ return {node};
41
+ }
42
+ return null;
43
+ }
44
+
45
+ export class LayoutContainerNode extends ElementNode {
46
+ __templateColumns: string;
47
+
48
+ constructor(templateColumns: string, key?: NodeKey) {
49
+ super(key);
50
+ this.__templateColumns = templateColumns;
51
+ }
52
+
53
+ static getType(): string {
54
+ return 'layout-container';
55
+ }
56
+
57
+ static clone(node: LayoutContainerNode): LayoutContainerNode {
58
+ return new LayoutContainerNode(node.__templateColumns, node.__key);
59
+ }
60
+
61
+ createDOM(config: EditorConfig): HTMLElement {
62
+ const dom = document.createElement('div');
63
+ dom.style.gridTemplateColumns = this.__templateColumns;
64
+ if (typeof config.theme.layoutContainer === 'string') {
65
+ addClassNamesToElement(dom, config.theme.layoutContainer);
66
+ }
67
+ return dom;
68
+ }
69
+
70
+ exportDOM(): DOMExportOutput {
71
+ const element = document.createElement('div');
72
+ element.style.gridTemplateColumns = this.__templateColumns;
73
+ element.setAttribute('data-lexical-layout-container', 'true');
74
+ return {element};
75
+ }
76
+
77
+ updateDOM(prevNode: this, dom: HTMLElement): boolean {
78
+ if (prevNode.__templateColumns !== this.__templateColumns) {
79
+ dom.style.gridTemplateColumns = this.__templateColumns;
80
+ }
81
+ return false;
82
+ }
83
+
84
+ static importDOM(): DOMConversionMap | null {
85
+ return {
86
+ div: (domNode: HTMLElement) => {
87
+ if (!domNode.hasAttribute('data-lexical-layout-container')) {
88
+ return null;
89
+ }
90
+ return {
91
+ conversion: $convertLayoutContainerElement,
92
+ priority: 2,
93
+ };
94
+ },
95
+ };
96
+ }
97
+
98
+ static importJSON(json: SerializedLayoutContainerNode): LayoutContainerNode {
99
+ return $createLayoutContainerNode().updateFromJSON(json);
100
+ }
101
+
102
+ updateFromJSON(
103
+ serializedNode: LexicalUpdateJSON<SerializedLayoutContainerNode>,
104
+ ): this {
105
+ return super
106
+ .updateFromJSON(serializedNode)
107
+ .setTemplateColumns(serializedNode.templateColumns);
108
+ }
109
+
110
+ isShadowRoot(): boolean {
111
+ return true;
112
+ }
113
+
114
+ canBeEmpty(): boolean {
115
+ return false;
116
+ }
117
+
118
+ exportJSON(): SerializedLayoutContainerNode {
119
+ return {
120
+ ...super.exportJSON(),
121
+ templateColumns: this.__templateColumns,
122
+ };
123
+ }
124
+
125
+ getTemplateColumns(): string {
126
+ return this.getLatest().__templateColumns;
127
+ }
128
+
129
+ setTemplateColumns(templateColumns: string): this {
130
+ const self = this.getWritable();
131
+ self.__templateColumns = templateColumns;
132
+ return self;
133
+ }
134
+ }
135
+
136
+ export function $createLayoutContainerNode(
137
+ templateColumns: string = '',
138
+ ): LayoutContainerNode {
139
+ return new LayoutContainerNode(templateColumns);
140
+ }
141
+
142
+ export function $isLayoutContainerNode(
143
+ node: LexicalNode | null | undefined,
144
+ ): node is LayoutContainerNode {
145
+ return node instanceof LayoutContainerNode;
146
+ }
@@ -0,0 +1,79 @@
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
+
9
+ import type {
10
+ DOMConversionMap,
11
+ DOMConversionOutput,
12
+ EditorConfig,
13
+ LexicalNode,
14
+ SerializedElementNode,
15
+ } from 'lexical';
16
+
17
+ import {addClassNamesToElement} from '@lexical/utils';
18
+ import {ElementNode} from 'lexical';
19
+
20
+ export type SerializedLayoutItemNode = SerializedElementNode;
21
+
22
+ function $convertLayoutItemElement(): DOMConversionOutput | null {
23
+ return {node: $createLayoutItemNode()};
24
+ }
25
+
26
+ export class LayoutItemNode extends ElementNode {
27
+ static getType(): string {
28
+ return 'layout-item';
29
+ }
30
+
31
+ static clone(node: LayoutItemNode): LayoutItemNode {
32
+ return new LayoutItemNode(node.__key);
33
+ }
34
+
35
+ createDOM(config: EditorConfig): HTMLElement {
36
+ const dom = document.createElement('div');
37
+ dom.setAttribute('data-lexical-layout-item', 'true');
38
+ if (typeof config.theme.layoutItem === 'string') {
39
+ addClassNamesToElement(dom, config.theme.layoutItem);
40
+ }
41
+ return dom;
42
+ }
43
+
44
+ updateDOM(): boolean {
45
+ return false;
46
+ }
47
+
48
+ static importDOM(): DOMConversionMap | null {
49
+ return {
50
+ div: (domNode: HTMLElement) => {
51
+ if (!domNode.hasAttribute('data-lexical-layout-item')) {
52
+ return null;
53
+ }
54
+ return {
55
+ conversion: $convertLayoutItemElement,
56
+ priority: 2,
57
+ };
58
+ },
59
+ };
60
+ }
61
+
62
+ static importJSON(serializedNode: SerializedLayoutItemNode): LayoutItemNode {
63
+ return $createLayoutItemNode().updateFromJSON(serializedNode);
64
+ }
65
+
66
+ isShadowRoot(): boolean {
67
+ return true;
68
+ }
69
+ }
70
+
71
+ export function $createLayoutItemNode(): LayoutItemNode {
72
+ return new LayoutItemNode();
73
+ }
74
+
75
+ export function $isLayoutItemNode(
76
+ node: LexicalNode | null | undefined,
77
+ ): node is LayoutItemNode {
78
+ return node instanceof LayoutItemNode;
79
+ }