@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,438 @@
1
+ import type {TableCellNode, TableDOMCell, TableMapType} from '@lexical/table';
2
+ import type {LexicalEditor} from 'lexical';
3
+
4
+
5
+ import {useLexicalComposerContext} from '@lexical/react/LexicalComposerContext';
6
+ import {useLexicalEditable} from '@lexical/react/useLexicalEditable';
7
+ import {
8
+ $computeTableMapSkipCellCheck,
9
+ $getTableNodeFromLexicalNodeOrThrow,
10
+ $getTableRowIndexFromTableCellNode,
11
+ $isTableCellNode,
12
+ $isTableRowNode,
13
+ getDOMCellFromTarget,
14
+ getTableElement,
15
+ TableNode,
16
+ } from '@lexical/table';
17
+ import {calculateZoomLevel} from '@lexical/utils';
18
+ import {$getNearestNodeFromDOMNode, isHTMLElement} from 'lexical';
19
+ import * as React from 'react';
20
+ import {
21
+ MouseEventHandler,
22
+ useCallback,
23
+ useEffect,
24
+ useMemo,
25
+ useRef,
26
+ useState,
27
+ } from 'react';
28
+ import {createPortal} from 'react-dom';
29
+
30
+ type MousePosition = {
31
+ x: number;
32
+ y: number;
33
+ };
34
+
35
+ type MouseDraggingDirection = 'right' | 'bottom';
36
+
37
+ const MIN_ROW_HEIGHT = 33;
38
+ const MIN_COLUMN_WIDTH = 92;
39
+
40
+ function TableCellResizer({editor}: {editor: LexicalEditor}): React.JSX.Element {
41
+ const targetRef = useRef<HTMLElement | null>(null);
42
+ const resizerRef = useRef<HTMLDivElement | null>(null);
43
+ const tableRectRef = useRef<ClientRect | null>(null);
44
+
45
+ const mouseStartPosRef = useRef<MousePosition | null>(null);
46
+ const [mouseCurrentPos, updateMouseCurrentPos] =
47
+ useState<MousePosition | null>(null);
48
+
49
+ const [activeCell, updateActiveCell] = useState<TableDOMCell | null>(null);
50
+ const [isMouseDown, updateIsMouseDown] = useState<boolean>(false);
51
+ const [draggingDirection, updateDraggingDirection] =
52
+ useState<MouseDraggingDirection | null>(null);
53
+
54
+ const resetState = useCallback(() => {
55
+ updateActiveCell(null);
56
+ targetRef.current = null;
57
+ updateDraggingDirection(null);
58
+ mouseStartPosRef.current = null;
59
+ tableRectRef.current = null;
60
+ }, []);
61
+
62
+ const isMouseDownOnEvent = (event: MouseEvent) => {
63
+ return (event.buttons & 1) === 1;
64
+ };
65
+
66
+ useEffect(() => {
67
+ return editor.registerNodeTransform(TableNode, (tableNode) => {
68
+ if (tableNode.getColWidths()) {
69
+ return tableNode;
70
+ }
71
+
72
+ const numColumns = tableNode.getColumnCount();
73
+ const columnWidth = MIN_COLUMN_WIDTH;
74
+
75
+ tableNode.setColWidths(Array(numColumns).fill(columnWidth));
76
+ return tableNode;
77
+ });
78
+ }, [editor]);
79
+
80
+ useEffect(() => {
81
+ const onMouseMove = (event: MouseEvent) => {
82
+ const target = event.target;
83
+ if (!isHTMLElement(target)) {
84
+ return;
85
+ }
86
+
87
+ if (draggingDirection) {
88
+ updateMouseCurrentPos({
89
+ x: event.clientX,
90
+ y: event.clientY,
91
+ });
92
+ return;
93
+ }
94
+ updateIsMouseDown(isMouseDownOnEvent(event));
95
+ if (resizerRef.current && resizerRef.current.contains(target)) {
96
+ return;
97
+ }
98
+
99
+ if (targetRef.current !== target) {
100
+ targetRef.current = target;
101
+ const cell = getDOMCellFromTarget(target);
102
+
103
+ if (cell && activeCell !== cell) {
104
+ editor.getEditorState().read(
105
+ () => {
106
+ const tableCellNode = $getNearestNodeFromDOMNode(cell.elem);
107
+ if (!tableCellNode) {
108
+ throw new Error('TableCellResizer: Table cell node not found.');
109
+ }
110
+
111
+ const tableNode =
112
+ $getTableNodeFromLexicalNodeOrThrow(tableCellNode);
113
+ const tableElement = getTableElement(
114
+ tableNode,
115
+ editor.getElementByKey(tableNode.getKey()),
116
+ );
117
+
118
+ if (!tableElement) {
119
+ throw new Error('TableCellResizer: Table element not found.');
120
+ }
121
+
122
+ targetRef.current = target as HTMLElement;
123
+ tableRectRef.current = tableElement.getBoundingClientRect();
124
+ updateActiveCell(cell);
125
+ },
126
+ {editor},
127
+ );
128
+ } else if (cell == null) {
129
+ resetState();
130
+ }
131
+ }
132
+ };
133
+
134
+ const onMouseDown = () => {
135
+ updateIsMouseDown(true);
136
+ };
137
+
138
+ const onMouseUp = () => {
139
+ updateIsMouseDown(false);
140
+ };
141
+
142
+ const removeRootListener = editor.registerRootListener(
143
+ (rootElement, prevRootElement) => {
144
+ prevRootElement?.removeEventListener('mousemove', onMouseMove);
145
+ prevRootElement?.removeEventListener('mousedown', onMouseDown);
146
+ prevRootElement?.removeEventListener('mouseup', onMouseUp);
147
+ rootElement?.addEventListener('mousemove', onMouseMove);
148
+ rootElement?.addEventListener('mousedown', onMouseDown);
149
+ rootElement?.addEventListener('mouseup', onMouseUp);
150
+ },
151
+ );
152
+
153
+ return () => {
154
+ removeRootListener();
155
+ };
156
+ }, [activeCell, draggingDirection, editor, resetState]);
157
+
158
+ const isHeightChanging = (direction: MouseDraggingDirection) => {
159
+ if (direction === 'bottom') {
160
+ return true;
161
+ }
162
+ return false;
163
+ };
164
+
165
+ const updateRowHeight = useCallback(
166
+ (heightChange: number) => {
167
+ if (!activeCell) {
168
+ throw new Error('TableCellResizer: Expected active cell.');
169
+ }
170
+
171
+ editor.update(
172
+ () => {
173
+ const tableCellNode = $getNearestNodeFromDOMNode(activeCell.elem);
174
+ if (!$isTableCellNode(tableCellNode)) {
175
+ throw new Error('TableCellResizer: Table cell node not found.');
176
+ }
177
+
178
+ const tableNode = $getTableNodeFromLexicalNodeOrThrow(tableCellNode);
179
+
180
+ const tableRowIndex =
181
+ $getTableRowIndexFromTableCellNode(tableCellNode) +
182
+ tableCellNode.getRowSpan() -
183
+ 1;
184
+
185
+ const tableRows = tableNode.getChildren();
186
+
187
+ if (tableRowIndex >= tableRows.length || tableRowIndex < 0) {
188
+ throw new Error('Expected table cell to be inside of table row.');
189
+ }
190
+
191
+ const tableRow = tableRows[tableRowIndex];
192
+
193
+ if (!$isTableRowNode(tableRow)) {
194
+ throw new Error('Expected table row');
195
+ }
196
+
197
+ let height = tableRow.getHeight();
198
+ if (height === undefined) {
199
+ const rowCells = tableRow.getChildren<TableCellNode>();
200
+ height = Math.min(
201
+ ...rowCells.map(
202
+ (cell) => getCellNodeHeight(cell, editor) ?? Infinity,
203
+ ),
204
+ );
205
+ }
206
+
207
+ const newHeight = Math.max(height + heightChange, MIN_ROW_HEIGHT);
208
+ tableRow.setHeight(newHeight);
209
+ },
210
+ {tag: 'skip-scroll-into-view'},
211
+ );
212
+ },
213
+ [activeCell, editor],
214
+ );
215
+
216
+ const getCellNodeHeight = (
217
+ cell: TableCellNode,
218
+ activeEditor: LexicalEditor,
219
+ ): number | undefined => {
220
+ const domCellNode = activeEditor.getElementByKey(cell.getKey());
221
+ return domCellNode?.clientHeight;
222
+ };
223
+
224
+ const getCellColumnIndex = (
225
+ tableCellNode: TableCellNode,
226
+ tableMap: TableMapType,
227
+ ) => {
228
+ for (let row = 0; row < tableMap.length; row++) {
229
+ for (let column = 0; column < tableMap[row].length; column++) {
230
+ if (tableMap[row][column].cell === tableCellNode) {
231
+ return column;
232
+ }
233
+ }
234
+ }
235
+ };
236
+
237
+ const updateColumnWidth = useCallback(
238
+ (widthChange: number) => {
239
+ if (!activeCell) {
240
+ throw new Error('TableCellResizer: Expected active cell.');
241
+ }
242
+ editor.update(
243
+ () => {
244
+ const tableCellNode = $getNearestNodeFromDOMNode(activeCell.elem);
245
+ if (!$isTableCellNode(tableCellNode)) {
246
+ throw new Error('TableCellResizer: Table cell node not found.');
247
+ }
248
+
249
+ const tableNode = $getTableNodeFromLexicalNodeOrThrow(tableCellNode);
250
+ const [tableMap] = $computeTableMapSkipCellCheck(
251
+ tableNode,
252
+ null,
253
+ null,
254
+ );
255
+ const columnIndex = getCellColumnIndex(tableCellNode, tableMap);
256
+ if (columnIndex === undefined) {
257
+ throw new Error('TableCellResizer: Table column not found.');
258
+ }
259
+
260
+ const colWidths = tableNode.getColWidths();
261
+ if (!colWidths) {
262
+ return;
263
+ }
264
+ const width = colWidths[columnIndex];
265
+ if (width === undefined) {
266
+ return;
267
+ }
268
+ const newColWidths = [...colWidths];
269
+ const newWidth = Math.max(width + widthChange, MIN_COLUMN_WIDTH);
270
+ newColWidths[columnIndex] = newWidth;
271
+ tableNode.setColWidths(newColWidths);
272
+ },
273
+ {tag: 'skip-scroll-into-view'},
274
+ );
275
+ },
276
+ [activeCell, editor],
277
+ );
278
+
279
+ const mouseUpHandler = useCallback(
280
+ (direction: MouseDraggingDirection) => {
281
+ const handler = (event: MouseEvent) => {
282
+ event.preventDefault();
283
+ event.stopPropagation();
284
+
285
+ if (!activeCell) {
286
+ throw new Error('TableCellResizer: Expected active cell.');
287
+ }
288
+
289
+ if (mouseStartPosRef.current) {
290
+ const {x, y} = mouseStartPosRef.current;
291
+
292
+ if (activeCell === null) {
293
+ return;
294
+ }
295
+ const zoom = calculateZoomLevel(event.target as Element);
296
+
297
+ if (isHeightChanging(direction)) {
298
+ const heightChange = (event.clientY - y) / zoom;
299
+ updateRowHeight(heightChange);
300
+ } else {
301
+ const widthChange = (event.clientX - x) / zoom;
302
+ updateColumnWidth(widthChange);
303
+ }
304
+
305
+ resetState();
306
+ document.removeEventListener('mouseup', handler);
307
+ }
308
+ };
309
+ return handler;
310
+ },
311
+ [activeCell, resetState, updateColumnWidth, updateRowHeight],
312
+ );
313
+
314
+ const toggleResize = useCallback(
315
+ (direction: MouseDraggingDirection): MouseEventHandler<HTMLDivElement> =>
316
+ (event) => {
317
+ event.preventDefault();
318
+ event.stopPropagation();
319
+
320
+ if (!activeCell) {
321
+ throw new Error('TableCellResizer: Expected active cell.');
322
+ }
323
+
324
+ mouseStartPosRef.current = {
325
+ x: event.clientX,
326
+ y: event.clientY,
327
+ };
328
+ updateMouseCurrentPos(mouseStartPosRef.current);
329
+ updateDraggingDirection(direction);
330
+
331
+ document.addEventListener('mouseup', mouseUpHandler(direction));
332
+ },
333
+ [activeCell, mouseUpHandler],
334
+ );
335
+
336
+ const getResizers = useCallback(() => {
337
+ if (activeCell) {
338
+ const {height, width, top, left} =
339
+ activeCell.elem.getBoundingClientRect();
340
+ const zoom = calculateZoomLevel(activeCell.elem);
341
+ const zoneWidth = 10; // Pixel width of the zone where you can drag the edge
342
+ const styles = {
343
+ bottom: {
344
+ backgroundColor: 'none',
345
+ "zIndex":"10",
346
+ cursor: 'row-resize',
347
+ height: `${zoneWidth}px`,
348
+ left: `${window.pageXOffset + left}px`,
349
+ top: `${window.pageYOffset + top + height - zoneWidth / 2}px`,
350
+ width: `${width}px`,
351
+ },
352
+ right: {
353
+ backgroundColor: 'none',
354
+ "zIndex":"10",
355
+ cursor: 'col-resize',
356
+ height: `${height}px`,
357
+ left: `${window.pageXOffset + left + width - zoneWidth / 2}px`,
358
+ top: `${window.pageYOffset + top}px`,
359
+ width: `${zoneWidth}px`,
360
+ },
361
+ };
362
+
363
+ const tableRect = tableRectRef.current;
364
+
365
+ if (draggingDirection && mouseCurrentPos && tableRect) {
366
+ if (isHeightChanging(draggingDirection)) {
367
+ styles[draggingDirection].left = `${
368
+ window.pageXOffset + tableRect.left
369
+ }px`;
370
+ styles[draggingDirection].top = `${
371
+ window.pageYOffset + mouseCurrentPos.y / zoom
372
+ }px`;
373
+ styles[draggingDirection].height = '3px';
374
+ styles[draggingDirection].width = `${tableRect.width}px`;
375
+ } else {
376
+ styles[draggingDirection].top = `${
377
+ window.pageYOffset + tableRect.top
378
+ }px`;
379
+ styles[draggingDirection].left = `${
380
+ window.pageXOffset + mouseCurrentPos.x / zoom
381
+ }px`;
382
+ styles[draggingDirection].width = '3px';
383
+ styles[draggingDirection].height = `${tableRect.height}px`;
384
+ }
385
+
386
+ styles[draggingDirection].backgroundColor = '#adf';
387
+ }
388
+
389
+ return styles;
390
+ }
391
+
392
+ return {
393
+ bottom: null,
394
+ left: null,
395
+ right: null,
396
+ top: null,
397
+ };
398
+ }, [activeCell, draggingDirection, mouseCurrentPos]);
399
+
400
+ const resizerStyles = getResizers();
401
+
402
+
403
+
404
+ return (
405
+ <div ref={resizerRef}>
406
+ {activeCell != null && !isMouseDown && (
407
+ <>
408
+ <div
409
+ className=" absolute TableCellResizer__ui"
410
+ style={resizerStyles.right || undefined}
411
+ onMouseDown={toggleResize('right')}
412
+ />
413
+ <div
414
+ className="absolute TableCellResizer__ui"
415
+ style={resizerStyles.bottom || undefined}
416
+ onMouseDown={toggleResize('bottom')}
417
+ />
418
+ </>
419
+ )}
420
+ </div>
421
+ );
422
+ }
423
+ export default function TableCellResizerPlugin(): null | React.ReactPortal {
424
+ const [editor] = useLexicalComposerContext();
425
+ const isEditable = useLexicalEditable();
426
+ const [mounted, setMounted] = useState(false);
427
+
428
+ useEffect(() => {
429
+ setMounted(true);
430
+ }, []);
431
+
432
+ const portal = useMemo(() => {
433
+ if (!mounted || !isEditable) return null;
434
+ return createPortal(<TableCellResizer editor={editor} />, document.body);
435
+ }, [mounted, isEditable, editor]);
436
+
437
+ return portal;
438
+ }