@collabchron/notiq 0.2.0 → 1.0.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 (282) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +230 -39
  3. package/dist/CodeActionMenuPlugin-EINOY4U4.mjs +15 -0
  4. package/dist/DynamicBlockComponent-NRQJ4WW4.mjs +161 -0
  5. package/dist/EquationComponent-CB6DFIHV.mjs +154 -0
  6. package/dist/ExcalidrawComponent-XW6646OH.mjs +528 -0
  7. package/dist/ExcalidrawPlugin-ZFHT62IF.mjs +14 -0
  8. package/dist/ExportPlugin-V2RLM63S.mjs +11 -0
  9. package/dist/FloatingLinkEditorPlugin-TRTCMSP4.mjs +12 -0
  10. package/dist/FloatingTextFormatToolbarPlugin-F2GY6LMI.mjs +30 -0
  11. package/dist/HintComponet-BRL6EAMS.mjs +217 -0
  12. package/dist/InlineImageComponent-UWIUWBHI.mjs +453 -0
  13. package/dist/MobileToolbar-BOOZAMQE.mjs +268 -0
  14. package/dist/SlashCommand-GMT5JI33.mjs +28 -0
  15. package/dist/StoryBuilderComponent-JGDBM5JU.mjs +562 -0
  16. package/{src/components/editor/plugins/TableCellActionMenuPlugin/index.tsx → dist/TableCellActionMenuPlugin-PGK2K3VG.mjs} +667 -759
  17. package/{src/components/editor/plugins/TableHoverActionsPlugin/index.tsx → dist/TableHoverActionsPlugin-GJVE6VRW.mjs} +258 -314
  18. package/dist/TemplatePlugin-ZD3QEVTI.mjs +9 -0
  19. package/dist/ToolbarPlugin-7TOZRD2R.mjs +1547 -0
  20. package/dist/babel-JZ2EV6AX.mjs +7233 -0
  21. package/dist/background-color-XZTYLGO2.mjs +362 -0
  22. package/dist/block-format-YJCV2DIY.mjs +15 -0
  23. package/dist/chunk-2FNEAMSP.mjs +127 -0
  24. package/dist/chunk-3CPBODXA.mjs +84 -0
  25. package/dist/chunk-3G37YKTV.mjs +83 -0
  26. package/dist/chunk-3JVFG7ER.mjs +184 -0
  27. package/dist/chunk-456TN7IM.mjs +110 -0
  28. package/dist/chunk-4EXYCTGJ.mjs +27 -0
  29. package/{src/utils/getSelectedNode.ts → dist/chunk-4HBCVSE6.mjs} +26 -27
  30. package/dist/chunk-4MEDW3T6.mjs +125 -0
  31. package/dist/chunk-4VWFVWYP.mjs +36 -0
  32. package/dist/chunk-5BAKY5KN.mjs +84 -0
  33. package/dist/chunk-5QSNIVIG.mjs +333 -0
  34. package/dist/chunk-64Z3FI7T.mjs +37 -0
  35. package/{src/components/editor/nodes/Stepper/index.tsx → dist/chunk-6RNZQOH2.mjs} +214 -260
  36. package/dist/chunk-77KXU36M.mjs +64 -0
  37. package/dist/chunk-77UA6HYR.mjs +165 -0
  38. package/dist/chunk-7NZAPJ4G.mjs +102 -0
  39. package/dist/chunk-7VUMHWWL.mjs +152 -0
  40. package/dist/chunk-AMMKBSST.mjs +1256 -0
  41. package/dist/chunk-BIU7WTLX.mjs +95 -0
  42. package/dist/chunk-EGMI62PP.mjs +83 -0
  43. package/dist/chunk-EHNQD5KO.mjs +88 -0
  44. package/dist/chunk-FSM26655.mjs +37 -0
  45. package/{src/components/editor/nodes/Hint/index.tsx → dist/chunk-G53GLEAY.mjs} +158 -190
  46. package/dist/chunk-GK35L7UY.mjs +28 -0
  47. package/dist/chunk-GXYD4VZM.mjs +193 -0
  48. package/dist/chunk-GYIOYVCN.mjs +538 -0
  49. package/dist/chunk-GZPNVR7L.mjs +157 -0
  50. package/dist/chunk-JXDPPUJI.mjs +52 -0
  51. package/dist/chunk-K36V4SIW.mjs +141 -0
  52. package/dist/chunk-KJ6AJ44Q.mjs +128 -0
  53. package/dist/chunk-KJV3FAZ7.mjs +142 -0
  54. package/{src/components/editor/plugins/ImagesPlugin/index.tsx → dist/chunk-LGG4IUIA.mjs} +189 -222
  55. package/dist/chunk-LQN3CMKV.mjs +1906 -0
  56. package/dist/chunk-N3WN46VL.mjs +236 -0
  57. package/dist/chunk-PBD6LMLC.mjs +366 -0
  58. package/dist/chunk-POGRR73N.mjs +33 -0
  59. package/{src/components/editor/utils/editorFormatting.ts → dist/chunk-PZSUSXQG.mjs} +238 -282
  60. package/dist/chunk-QEIFVK5M.mjs +29 -0
  61. package/dist/chunk-QHIQKMVN.mjs +427 -0
  62. package/dist/chunk-TCYK7DM7.mjs +36 -0
  63. package/dist/chunk-TTHQCW5F.mjs +47 -0
  64. package/dist/chunk-U47ABU5Z.mjs +53 -0
  65. package/dist/chunk-WDG7J2DY.mjs +116 -0
  66. package/dist/chunk-WJRHXI2C.mjs +733 -0
  67. package/dist/chunk-XLER2DHM.mjs +357 -0
  68. package/dist/chunk-XWC4TK2N.mjs +315 -0
  69. package/dist/chunk-YHPNOWFH.mjs +15 -0
  70. package/dist/chunk-YKC3SO4Z.mjs +32 -0
  71. package/dist/chunk-YMBXLRW5.mjs +374 -0
  72. package/dist/chunk-YPHOEJ46.mjs +64 -0
  73. package/dist/chunk-YUDCJRJM.mjs +25 -0
  74. package/dist/chunk-Z4EWP7BI.mjs +65 -0
  75. package/dist/chunk-ZB5LZQKC.mjs +191 -0
  76. package/dist/chunk-ZJRKATOJ.mjs +65 -0
  77. package/dist/color-BPKOPQKN.mjs +12 -0
  78. package/dist/estree-XC56IUFX.mjs +4414 -0
  79. package/dist/font-FEZ3GKSF.mjs +13 -0
  80. package/dist/font-size-EK775WRH.mjs +15 -0
  81. package/dist/html-S3ACX7NI.mjs +2738 -0
  82. package/dist/image-2PJIAYAT.mjs +993 -0
  83. package/dist/index.d.mts +145 -0
  84. package/dist/index.d.ts +145 -0
  85. package/dist/index.js +57855 -0
  86. package/dist/index.mjs +1790 -0
  87. package/dist/insert-gif-SAIDYURE.mjs +100 -0
  88. package/dist/insert-image-U3RJN3OW.mjs +259 -0
  89. package/dist/insert-node-5P2CRJ7S.mjs +201 -0
  90. package/dist/insert-poll-HCPM7MO6.mjs +33 -0
  91. package/dist/insert-table-24XYUS2W.mjs +66 -0
  92. package/dist/markdown-SNVBOSRA.mjs +3487 -0
  93. package/dist/poll-component-2R4MDLHS.mjs +303 -0
  94. package/dist/postcss-ONF3VDIM.mjs +5051 -0
  95. package/dist/standalone-EOIALU3M.mjs +2373 -0
  96. package/dist/stepper-FSARL6X6.mjs +304 -0
  97. package/dist/styles/notiq.css +1149 -0
  98. package/dist/text-align-VLECWO4H.mjs +118 -0
  99. package/dist/text-format-BG5WOOPZ.mjs +16 -0
  100. package/dist/typescript-AMPI6OVS.mjs +13135 -0
  101. package/package.json +94 -10
  102. package/src/styles/notiq.css +1149 -0
  103. package/src/styles/tailwind-plugin.ts +134 -0
  104. package/components.json +0 -21
  105. package/eslint.config.mjs +0 -16
  106. package/next.config.ts +0 -12
  107. package/postcss.config.mjs +0 -5
  108. package/public/file.svg +0 -1
  109. package/public/globe.svg +0 -1
  110. package/public/images/icons/plus.svg +0 -10
  111. package/public/next.svg +0 -1
  112. package/public/vercel.svg +0 -1
  113. package/public/window.svg +0 -1
  114. package/src/app/actions.ts +0 -2
  115. package/src/app/api/ai/route.ts +0 -175
  116. package/src/app/api/edgestore/[...edgestore]/route.ts +0 -28
  117. package/src/app/favicon.ico +0 -0
  118. package/src/app/globals.css +0 -205
  119. package/src/app/layout.tsx +0 -38
  120. package/src/app/page.tsx +0 -12
  121. package/src/components/editor/Core.tsx +0 -220
  122. package/src/components/editor/hooks/instructions-messages.ts +0 -300
  123. package/src/components/editor/hooks/use-mobile.ts +0 -19
  124. package/src/components/editor/hooks/useReport.ts +0 -67
  125. package/src/components/editor/hooks/useResizeObservert.ts +0 -22
  126. package/src/components/editor/index.tsx +0 -39
  127. package/src/components/editor/lexical-on-change.tsx +0 -28
  128. package/src/components/editor/nodes/CollapsibleNode/CollapsibleContainerNode.ts +0 -92
  129. package/src/components/editor/nodes/CollapsibleNode/CollapsibleContentNode.ts +0 -65
  130. package/src/components/editor/nodes/CollapsibleNode/CollapsibleTitleNode.ts +0 -105
  131. package/src/components/editor/nodes/EquationNode/EquationComponent.tsx +0 -143
  132. package/src/components/editor/nodes/EquationNode/EquationNode.tsx +0 -170
  133. package/src/components/editor/nodes/ExcalidrawNode/ExcalidrawComponent.tsx +0 -228
  134. package/src/components/editor/nodes/ExcalidrawNode/ExcalidrawImage.tsx +0 -137
  135. package/src/components/editor/nodes/ExcalidrawNode/ImageResizer.tsx +0 -317
  136. package/src/components/editor/nodes/ExcalidrawNode/index.tsx +0 -204
  137. package/src/components/editor/nodes/FigmaNode/FigmaNode.tsx +0 -134
  138. package/src/components/editor/nodes/Hint/HintComponet.tsx +0 -221
  139. package/src/components/editor/nodes/ImageNode/index.tsx +0 -328
  140. package/src/components/editor/nodes/InlineImageNode/InlineImageComponent.tsx +0 -383
  141. package/src/components/editor/nodes/InlineImageNode/InlineImageNode.css +0 -94
  142. package/src/components/editor/nodes/InlineImageNode/InlineImageNode.tsx +0 -309
  143. package/src/components/editor/nodes/LayoutNode/LayoutContainerNode.ts +0 -146
  144. package/src/components/editor/nodes/LayoutNode/LayoutItemNode.ts +0 -79
  145. package/src/components/editor/nodes/PollNode/index.tsx +0 -204
  146. package/src/components/editor/nodes/TweetNode/index.tsx +0 -214
  147. package/src/components/editor/nodes/index.ts +0 -81
  148. package/src/components/editor/plugins/AutoEmbedPlugin/index.tsx +0 -350
  149. package/src/components/editor/plugins/AutoLinkPlugin/index.tsx +0 -56
  150. package/src/components/editor/plugins/CodeActionMenuPlugin/components/CopyButton.tsx +0 -70
  151. package/src/components/editor/plugins/CodeActionMenuPlugin/components/PrettierButton.tsx +0 -192
  152. package/src/components/editor/plugins/CodeActionMenuPlugin/index.tsx +0 -217
  153. package/src/components/editor/plugins/CodeActionMenuPlugin/utils.ts +0 -26
  154. package/src/components/editor/plugins/CodeHighlightPlugin/index.ts +0 -21
  155. package/src/components/editor/plugins/CollapsiblePlugin/Collapsible.css +0 -76
  156. package/src/components/editor/plugins/CollapsiblePlugin/index.ts +0 -228
  157. package/src/components/editor/plugins/DragDropPastePlugin/index.tsx +0 -44
  158. package/src/components/editor/plugins/DraggableBlockPlugin/index.tsx +0 -52
  159. package/src/components/editor/plugins/EquationsPlugin/index.tsx +0 -85
  160. package/src/components/editor/plugins/ExcalidrawPlugin/index.tsx +0 -98
  161. package/src/components/editor/plugins/FigmaPlugin/index.tsx +0 -42
  162. package/src/components/editor/plugins/FloatingLinkEditorPlugin/index.tsx +0 -445
  163. package/src/components/editor/plugins/FloatingTextFormatToolbarPlugin/index.tsx +0 -275
  164. package/src/components/editor/plugins/InlineImagePlugin/index.tsx +0 -351
  165. package/src/components/editor/plugins/LayoutPlugin/index.tsx +0 -238
  166. package/src/components/editor/plugins/LinkPlugin/index.tsx +0 -36
  167. package/src/components/editor/plugins/LinkWithMetaData/index.tsx +0 -271
  168. package/src/components/editor/plugins/MarkdownShortcutPlugin/index.tsx +0 -11
  169. package/src/components/editor/plugins/MarkdownTransformers/index.tsx +0 -304
  170. package/src/components/editor/plugins/PollPlugin/index.tsx +0 -49
  171. package/src/components/editor/plugins/ShortcutsPlugin/index.tsx +0 -180
  172. package/src/components/editor/plugins/ShortcutsPlugin/shortcuts.ts +0 -253
  173. package/src/components/editor/plugins/SlashCommand/index.tsx +0 -621
  174. package/src/components/editor/plugins/SpeechToTextPlugin/index.ts +0 -127
  175. package/src/components/editor/plugins/TabFocusPlugin/index.ts +0 -58
  176. package/src/components/editor/plugins/TableCellResizer/index.tsx +0 -438
  177. package/src/components/editor/plugins/TablePlugin/index.tsx +0 -99
  178. package/src/components/editor/plugins/ToolbarPlugin/index.tsx +0 -522
  179. package/src/components/editor/plugins/TwitterPlugin/index.ts +0 -35
  180. package/src/components/editor/plugins/YouTubeNode/index.tsx +0 -179
  181. package/src/components/editor/plugins/YouTubePlugin/index.ts +0 -41
  182. package/src/components/editor/themes/editor-theme.ts +0 -113
  183. package/src/components/editor/themes/theme.css +0 -377
  184. package/src/components/editor/utils/ai.ts +0 -291
  185. package/src/components/editor/utils/canUseDOM.ts +0 -12
  186. package/src/components/editor/utils/environment.ts +0 -50
  187. package/src/components/editor/utils/extract-data.ts +0 -166
  188. package/src/components/editor/utils/getAllLexicalChildren.ts +0 -13
  189. package/src/components/editor/utils/getDOMRangeRect.ts +0 -27
  190. package/src/components/editor/utils/getSelectedNode.ts +0 -27
  191. package/src/components/editor/utils/gif.ts +0 -29
  192. package/src/components/editor/utils/invariant.ts +0 -15
  193. package/src/components/editor/utils/setFloatingElemPosition.ts +0 -51
  194. package/src/components/editor/utils/setFloatingElemPositionForLinkEditor.ts +0 -40
  195. package/src/components/editor/utils/setNodePlaceholderFromSelection/getNodePlaceholder.ts +0 -51
  196. package/src/components/editor/utils/setNodePlaceholderFromSelection/setNodePlaceholderFromSelection.ts +0 -15
  197. package/src/components/editor/utils/setNodePlaceholderFromSelection/setPlaceholderOnSelection.ts +0 -114
  198. package/src/components/editor/utils/setNodePlaceholderFromSelection/styles.css +0 -6
  199. package/src/components/editor/utils/url.ts +0 -109
  200. package/src/components/editor/utils/useLayoutEffect.ts +0 -13
  201. package/src/components/providers/QueryProvider.tsx +0 -15
  202. package/src/components/providers/SharedHistoryContext.tsx +0 -28
  203. package/src/components/providers/ToolbarContext.tsx +0 -123
  204. package/src/components/providers/theme-provider.tsx +0 -11
  205. package/src/components/theme/ModeToggle.tsx +0 -40
  206. package/src/components/ui/FileInput.tsx +0 -40
  207. package/src/components/ui/Input.css +0 -32
  208. package/src/components/ui/Select.css +0 -42
  209. package/src/components/ui/Select.tsx +0 -36
  210. package/src/components/ui/TextInput.tsx +0 -48
  211. package/src/components/ui/ai/ai-button.tsx +0 -574
  212. package/src/components/ui/ai/border.tsx +0 -99
  213. package/src/components/ui/ai/placeholder-input-vanish.tsx +0 -282
  214. package/src/components/ui/button.tsx +0 -89
  215. package/src/components/ui/card.tsx +0 -76
  216. package/src/components/ui/checkbox.tsx +0 -30
  217. package/src/components/ui/command.tsx +0 -153
  218. package/src/components/ui/dialog/Dialog.css +0 -25
  219. package/src/components/ui/dialog/Dialog.tsx +0 -34
  220. package/src/components/ui/dialog.tsx +0 -122
  221. package/src/components/ui/drop-downs/background-color.tsx +0 -183
  222. package/src/components/ui/drop-downs/block-format.tsx +0 -159
  223. package/src/components/ui/drop-downs/code.tsx +0 -42
  224. package/src/components/ui/drop-downs/color.tsx +0 -177
  225. package/src/components/ui/drop-downs/font-size.tsx +0 -138
  226. package/src/components/ui/drop-downs/font.tsx +0 -155
  227. package/src/components/ui/drop-downs/index.tsx +0 -122
  228. package/src/components/ui/drop-downs/insert-node.tsx +0 -213
  229. package/src/components/ui/drop-downs/text-align.tsx +0 -123
  230. package/src/components/ui/drop-downs/text-format.tsx +0 -104
  231. package/src/components/ui/dropdown-menu.tsx +0 -201
  232. package/src/components/ui/equation/EquationEditor.css +0 -38
  233. package/src/components/ui/equation/EquationEditor.tsx +0 -56
  234. package/src/components/ui/equation/KatexEquationAlterer.css +0 -41
  235. package/src/components/ui/equation/KatexEquationAlterer.tsx +0 -83
  236. package/src/components/ui/equation/KatexRenderer.tsx +0 -66
  237. package/src/components/ui/excalidraw/ExcalidrawModal.css +0 -64
  238. package/src/components/ui/excalidraw/ExcalidrawModal.tsx +0 -234
  239. package/src/components/ui/excalidraw/Modal.css +0 -62
  240. package/src/components/ui/excalidraw/Modal.tsx +0 -110
  241. package/src/components/ui/hover-card.tsx +0 -29
  242. package/src/components/ui/image/error-image.tsx +0 -17
  243. package/src/components/ui/image/file-upload.tsx +0 -240
  244. package/src/components/ui/image/image-resizer.tsx +0 -297
  245. package/src/components/ui/image/image-toolbar.tsx +0 -264
  246. package/src/components/ui/image/index.tsx +0 -408
  247. package/src/components/ui/image/lazy-image.tsx +0 -68
  248. package/src/components/ui/image/lazy-video.tsx +0 -71
  249. package/src/components/ui/input.tsx +0 -22
  250. package/src/components/ui/models/custom-dialog.tsx +0 -320
  251. package/src/components/ui/models/insert-gif.tsx +0 -90
  252. package/src/components/ui/models/insert-image.tsx +0 -52
  253. package/src/components/ui/models/insert-poll.tsx +0 -29
  254. package/src/components/ui/models/insert-table.tsx +0 -62
  255. package/src/components/ui/models/use-model.tsx +0 -91
  256. package/src/components/ui/poll/poll-component.tsx +0 -304
  257. package/src/components/ui/popover.tsx +0 -33
  258. package/src/components/ui/progress.tsx +0 -28
  259. package/src/components/ui/scroll-area.tsx +0 -48
  260. package/src/components/ui/separator.tsx +0 -31
  261. package/src/components/ui/skeleton.tsx +0 -15
  262. package/src/components/ui/sonner.tsx +0 -31
  263. package/src/components/ui/stepper/step.tsx +0 -179
  264. package/src/components/ui/stepper/stepper.tsx +0 -89
  265. package/src/components/ui/textarea.tsx +0 -22
  266. package/src/components/ui/toggle.tsx +0 -71
  267. package/src/components/ui/tooltip.tsx +0 -32
  268. package/src/components/ui/write/text-format-floting-toolbar.tsx +0 -346
  269. package/src/lib/edgestore.ts +0 -9
  270. package/src/lib/pinecone-client.ts +0 -0
  271. package/src/lib/utils.ts +0 -6
  272. package/src/utils/docSerialization.ts +0 -77
  273. package/src/utils/emoji-list.ts +0 -16615
  274. package/src/utils/getDOMRangeRect.ts +0 -27
  275. package/src/utils/getThemeSelector.ts +0 -25
  276. package/src/utils/isMobileWidth.ts +0 -7
  277. package/src/utils/joinClasses.ts +0 -13
  278. package/src/utils/setFloatingElemPosition.ts +0 -74
  279. package/src/utils/setFloatingElemPositionForLinkEditor.ts +0 -46
  280. package/src/utils/swipe.ts +0 -127
  281. package/src/utils/url.ts +0 -38
  282. package/tsconfig.json +0 -27
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Chinonso Chikelue (fluantiX)
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md CHANGED
@@ -1,71 +1,262 @@
1
- # Notiq
1
+ <div align="center">
2
+ <img src="public/logo.png" alt="Notiq Logo" width="120" />
3
+ <h1>Notiq</h1>
4
+ <p>
5
+ <strong>A powerful, AI-enhanced rich text editor built with Lexical, Next.js, TypeScript, and Tailwind CSS.</strong>
6
+ </p>
7
+ <p>
8
+ Create beautiful documents with intelligent writing assistance and advanced content blocks.
9
+ </p>
10
+ </div>
2
11
 
3
- A modern, extensible note-taking and document editor built with Next.js, TypeScript, Tailwind CSS, and Lexical. Features include rich text editing, image and media embeds, equations, polls, and more.
12
+ ![Notiq Banner](public/og-image.png)
4
13
 
5
- ## Features
14
+ ## 📸 Screenshots
6
15
 
7
- - ⚡️ Fast, responsive editor powered by Lexical
8
- - 🖼️ Image, inline image, and media embeds (YouTube, Twitter, Figma, GIFs)
9
- - 🧮 Equation and math support (KaTeX)
10
- - 📊 Polls, tables, and code blocks
11
- - 🎨 Customizable themes with Tailwind CSS
12
- - 🗂️ Modular plugin architecture
13
- - 🌐 Next.js app with API routes
16
+ <div align="center">
17
+ <h3>Desktop View</h3>
18
+ <img src="public/screenshots/desktop.png" alt="Desktop Screenshot" width="100%" />
19
+ </div>
14
20
 
15
- ## Getting Started
21
+ <div align="center">
22
+ <h3>Mobile View</h3>
23
+ <img src="public/screenshots/mobile.png" alt="Mobile Screenshot" width="300" />
24
+ </div>
16
25
 
17
- ### Prerequisites
26
+ ## ✨ Features
18
27
 
19
- - Node.js (v18+ recommended)
20
- - pnpm (or npm/yarn)
28
+ ### 🤖 AI-Powered Writing Assistant
29
+ - **Smart Writing**: GPT-4 integration for content improvement, grammar fixes, and style adjustments
30
+ - **AI Chat**: Ask questions about your document content and get contextual responses
31
+ - **Auto-completion**: Intelligent text suggestions and completions
32
+ - **Content Enhancement**: Make text longer/shorter, create step-by-step guides, simplify language
33
+
34
+ ### ✏️ Rich Text Editor
35
+ - **Lexical Framework**: Built on Facebook's modern Lexical editor framework
36
+ - **WYSIWYG Editing**: What-you-see-is-what-you-get editing experience
37
+ - **Markdown Support**: Full markdown shortcuts and live transformers
38
+ - **Slash Commands**: Type "/" for quick content insertion and formatting
39
+ - **Floating Toolbars**: Context-sensitive formatting tools
40
+
41
+ ### 🧩 Advanced Content Blocks
42
+ - **Media**: Images, inline images, YouTube videos, Twitter embeds
43
+ - **Interactive**: Polls, step-by-step guides, collapsible sections
44
+ - **Technical**: Code blocks with syntax highlighting, mathematical equations (KaTeX)
45
+ - **Design**: Excalidraw drawings, Figma embeds
46
+ - **Layout**: Multi-column layouts, resizable panels, tables
47
+ - **Callouts**: Hint blocks and special callout sections
48
+
49
+ ### 🎨 User Experience
50
+ - **Drag & Drop**: Draggable blocks and content reordering
51
+ - **Speech-to-Text**: Voice input capabilities
52
+ - **Link Previews**: Rich link previews with metadata
53
+ - **Theme Support**: Dark/light mode with seamless switching
54
+ - **Keyboard Shortcuts**: Comprehensive shortcut system
55
+ - **Real-time Collaboration**: Shared editing context
56
+
57
+ ## 🚀 Library Usage
58
+
59
+ Notiq can be used as a standalone editor in your React/Next.js projects.
21
60
 
22
61
  ### Installation
23
62
 
24
63
  ```bash
64
+ npm install @collabchron/notiq
65
+ ```
66
+
67
+ ### Integration
68
+
69
+ #### 1. Configure Tailwind CSS
70
+
71
+ Add the Notiq plugin to your `tailwind.config.js`:
72
+
73
+ ```javascript
74
+ import { notiqPlugin } from '@collabchron/notiq';
75
+
76
+ export default {
77
+ content: [
78
+ // ... your content paths
79
+ "./node_modules/@collabchron/notiq/dist/**/*.{js,mjs}",
80
+ ],
81
+ plugins: [
82
+ notiqPlugin,
83
+ require('@tailwindcss/typography'),
84
+ ],
85
+ }
86
+ ```
87
+
88
+ #### 2. Usage in your component
89
+
90
+ ```tsx
91
+ "use client";
92
+
93
+ import { Editor } from "@collabchron/notiq";
94
+
95
+ export default function MyEditorPage() {
96
+ return (
97
+ <Editor
98
+ isEditable={true}
99
+ aiConfig={{
100
+ apiEndpoint: "/api/ai", // Your AI completion endpoint
101
+ }}
102
+ uploadConfig={{
103
+ uploadHandler: async (file) => {
104
+ // Your custom upload logic (e.g., S3, Cloudinary)
105
+ return { url: "https://your-storage.com/file.png" };
106
+ }
107
+ }}
108
+ />
109
+ );
110
+ }
111
+ ```
112
+
113
+ ## 🛠️ Local Development
114
+
115
+ If you want to contribute or run the development environment:
116
+
117
+ ### Installation
118
+
119
+ ```bash
120
+ npm install
121
+
122
+ # or
123
+
124
+ yarn install
125
+
126
+ # or
127
+
25
128
  pnpm install
26
129
  ```
27
130
 
131
+ ### Environment Setup
132
+
133
+ Create a `.env.local` file with your API keys:
134
+
135
+ ```env
136
+ OPENAI_API_KEY=your_openai_api_key_here
137
+
138
+ NEXT_PUBLIC_EDGESTORE_ACCESS_KEY=your_edgestore_key
139
+
140
+ NEXT_PUBLIC_EDGESTORE_SECRET_KEY=your_edgestore_secret
141
+ ```
142
+
28
143
  ### Development
29
144
 
30
145
  ```bash
146
+ npm run dev
147
+
148
+ # or
149
+
150
+ yarn dev
151
+
152
+ # or
153
+
31
154
  pnpm dev
32
155
  ```
33
156
 
34
- Open [http://localhost:3000](http://localhost:3000) in your browser.
157
+ Open [http://localhost:3000](http://localhost:3000) to start writing!
35
158
 
36
- ### Build
159
+ ## 🏗️ Architecture
37
160
 
38
- ```bash
39
- pnpm build
161
+ ### Core Components
162
+
163
+ - **Editor Core** (`/src/components/editor/Core.tsx`) - Main editor container with Lexical integration
164
+ - **Plugins** (`/src/components/editor/plugins/`) - 40+ feature plugins for rich functionality
165
+ - **Nodes** (`/src/components/editor/nodes/`) - 20+ custom content block types
166
+ - **AI Integration** (`/src/components/ui/ai/`) - AI-powered writing assistance
167
+ - **Toolbar System** - Rich formatting toolbar with contextual actions
168
+
169
+ ### Plugin System
170
+
171
+ Notiq uses an extensible plugin architecture:
172
+
173
+ ```tsx
174
+ import { Editor } from '@/components/editor'
175
+
176
+ function MyApp() {
177
+ return (
178
+ <Editor
179
+ plugins={[
180
+ // Built-in plugins
181
+ 'toolbar',
182
+ 'slash-commands',
183
+ 'ai-assistant',
184
+ 'drag-drop',
185
+ // Custom plugins
186
+ MyCustomPlugin
187
+ ]}
188
+ />
189
+ )
190
+ }
40
191
  ```
41
192
 
42
- ## Project Structure
193
+ ## 🎯 Use Cases
194
+
195
+ - **Documentation**: Technical docs, API references, user guides
196
+ - **Content Creation**: Blog posts, articles, marketing content
197
+ - **Note-taking**: Personal notes, meeting minutes, research
198
+ - **Collaborative Writing**: Team documents, shared knowledge bases
199
+ - **Educational Content**: Tutorials, courses, interactive lessons
200
+
201
+ ## 🛠️ Development
202
+
203
+ ### Adding Custom Nodes
204
+
205
+ ```tsx
206
+ import { DecoratorNode } from 'lexical'
207
+
208
+ export class MyCustomNode extends DecoratorNode<JSX.Element> {
209
+ static getType(): string {
210
+ return 'my-custom-node'
211
+ }
212
+
213
+ createDOM(): HTMLElement {
214
+ return document.createElement('div')
215
+ }
216
+
217
+ decorate(): JSX.Element {
218
+ return <MyCustomComponent />
219
+ }
220
+ }
221
+ ```
222
+
223
+ ### Creating Plugins
224
+
225
+ ```tsx
226
+ import { useLexicalComposerContext } from '@lexical/react/LexicalComposerContext'
227
+
228
+ export function MyPlugin() {
229
+ const [editor] = useLexicalComposerContext()
230
+
231
+ // Plugin logic here
232
+
233
+ return null
234
+ }
235
+ ```
236
+
237
+ ## 📦 Building for Production
238
+
239
+ ```bash
240
+ npm run build
241
+ npm run start
242
+ ```
43
243
 
44
- - `src/app/` — Next.js app routes and layout
45
- - `src/components/editor/` — Editor core, plugins, nodes, and UI
46
- - `src/components/ui/` — Reusable UI components
47
- - `src/lib/` — Utility libraries (EdgeStore, Pinecone, etc.)
48
- - `public/` — Static assets
244
+ ## 🤝 Contributing
49
245
 
50
- ## Editor Plugins & Nodes
246
+ We welcome contributions! Please see our [Contributing Guidelines](CONTRIBUTING.md) for details on how to get started, submitting bug reports, and suggesting enhancements.
51
247
 
52
- - **Plugins:** Toolbar, Floating Toolbar, AutoEmbed, Equations, Excalidraw, Inline Images, Polls, Tables, Code Actions, Slash Commands, etc.
53
- - **Nodes:** ImageNode, InlineImageNode, EquationNode, ExcalidrawNode, PollNode, etc.
248
+ Please note that this project is released with a [Contributor Covenant Code of Conduct](CODE_OF_CONDUCT.md). By participating in this project you agree to abide by its terms.
54
249
 
55
- ## Customization
250
+ ## 📄 License
56
251
 
57
- - Tailwind CSS config: `tailwind.config.ts`
58
- - ESLint config: `eslint.config.mjs`
59
- - Editor themes: `src/components/editor/themes/`
252
+ MIT License - see the [LICENSE](LICENSE) file for details.
60
253
 
61
- ## Contributing
254
+ ## 🆘 Support
62
255
 
63
- 1. Fork the repo
64
- 2. Create your feature branch (`git checkout -b feature/foo`)
65
- 3. Commit your changes (`git commit -am 'Add feature'`)
66
- 4. Push to the branch (`git push origin feature/foo`)
67
- 5. Create a Pull Request
256
+ - 📖 [Documentation](https://github.com/chinonsochikelue/notiq)
257
+ - 🐛 [Report Issues](https://github.com/chinonsochikelue/notiq/issues)
258
+ - 💬 [Discussions](https://github.com/chinonsochikelue/notiq/discussions)
68
259
 
69
- ## License
260
+ ---
70
261
 
71
- MIT
262
+ Built with ❤️ using [Lexical](https://lexical.dev/), [Next.js](https://nextjs.org/), and [OpenAI](https://openai.com/)
@@ -0,0 +1,15 @@
1
+ import {
2
+ CodeActionMenuPlugin
3
+ } from "./chunk-PBD6LMLC.mjs";
4
+ import "./chunk-TTHQCW5F.mjs";
5
+ import "./chunk-GK35L7UY.mjs";
6
+ import "./chunk-EGMI62PP.mjs";
7
+ import "./chunk-KJ6AJ44Q.mjs";
8
+ import "./chunk-64Z3FI7T.mjs";
9
+ import "./chunk-WDG7J2DY.mjs";
10
+ import "./chunk-BIU7WTLX.mjs";
11
+ import "./chunk-YHPNOWFH.mjs";
12
+ import "./chunk-77KXU36M.mjs";
13
+ export {
14
+ CodeActionMenuPlugin as default
15
+ };
@@ -0,0 +1,161 @@
1
+ "use client";
2
+ import {
3
+ DynamicBlockNode
4
+ } from "./chunk-5BAKY5KN.mjs";
5
+ import {
6
+ Badge
7
+ } from "./chunk-FSM26655.mjs";
8
+ import {
9
+ Card,
10
+ CardContent,
11
+ CardHeader,
12
+ CardTitle
13
+ } from "./chunk-3G37YKTV.mjs";
14
+ import {
15
+ Button
16
+ } from "./chunk-BIU7WTLX.mjs";
17
+ import {
18
+ cn
19
+ } from "./chunk-YHPNOWFH.mjs";
20
+ import {
21
+ React,
22
+ __spreadValues,
23
+ init_react_shim
24
+ } from "./chunk-77KXU36M.mjs";
25
+
26
+ // src/components/editor/nodes/DynamicBlockNode/DynamicBlockComponent.tsx
27
+ init_react_shim();
28
+ import { useState, useEffect, useRef } from "react";
29
+ import { useLexicalComposerContext } from "@lexical/react/LexicalComposerContext";
30
+ import { $getNodeByKey } from "lexical";
31
+ import { Play, Pause, Settings, Eye, EyeOff, Zap } from "lucide-react";
32
+ function DynamicBlockComponent({ nodeKey, payload }) {
33
+ var _a;
34
+ const [editor] = useLexicalComposerContext();
35
+ const [currentBlockId, setCurrentBlockId] = useState(payload.currentBlockId || ((_a = payload.blocks[0]) == null ? void 0 : _a.id));
36
+ const [isPreviewMode, setIsPreviewMode] = useState(false);
37
+ const [isPlaying, setIsPlaying] = useState(false);
38
+ const [showSettings, setShowSettings] = useState(false);
39
+ const containerRef = useRef(null);
40
+ const timeoutRef = useRef(void 0);
41
+ const currentBlock = payload.blocks.find((block) => block.id === currentBlockId);
42
+ const activeTriggers = payload.triggers.filter(
43
+ (trigger) => trigger.targetBlockId === currentBlockId || payload.blocks.some((block) => block.id === trigger.targetBlockId)
44
+ );
45
+ const executeTrigger = (trigger) => {
46
+ const targetBlock = payload.blocks.find((block) => block.id === trigger.targetBlockId);
47
+ if (!targetBlock) return;
48
+ switch (trigger.action) {
49
+ case "show":
50
+ case "replace":
51
+ setCurrentBlockId(trigger.targetBlockId);
52
+ break;
53
+ case "hide":
54
+ setCurrentBlockId("");
55
+ break;
56
+ case "animate":
57
+ setCurrentBlockId("");
58
+ setTimeout(() => setCurrentBlockId(trigger.targetBlockId), 100);
59
+ break;
60
+ }
61
+ };
62
+ useEffect(() => {
63
+ if (!isPreviewMode || !containerRef.current) return;
64
+ const container = containerRef.current;
65
+ const timeTriggers = activeTriggers.filter((t) => t.type === "time");
66
+ const clickTriggers = activeTriggers.filter((t) => t.type === "click");
67
+ const hoverTriggers = activeTriggers.filter((t) => t.type === "hover");
68
+ if (isPlaying && timeTriggers.length > 0) {
69
+ timeTriggers.forEach((trigger) => {
70
+ const delay = typeof trigger.condition === "number" ? trigger.condition * 1e3 : 3e3;
71
+ timeoutRef.current = setTimeout(() => executeTrigger(trigger), delay);
72
+ });
73
+ }
74
+ const handleClick = () => {
75
+ clickTriggers.forEach(executeTrigger);
76
+ };
77
+ const handleMouseEnter = () => {
78
+ hoverTriggers.forEach(executeTrigger);
79
+ };
80
+ container.addEventListener("click", handleClick);
81
+ container.addEventListener("mouseenter", handleMouseEnter);
82
+ return () => {
83
+ container.removeEventListener("click", handleClick);
84
+ container.removeEventListener("mouseenter", handleMouseEnter);
85
+ if (timeoutRef.current) {
86
+ clearTimeout(timeoutRef.current);
87
+ }
88
+ };
89
+ }, [isPreviewMode, isPlaying, activeTriggers, currentBlockId]);
90
+ const updatePayload = (newPayload) => {
91
+ editor.update(() => {
92
+ const node = $getNodeByKey(nodeKey);
93
+ if ($isDynamicBlockNode(node)) {
94
+ node.updatePayload(__spreadValues(__spreadValues({}, payload), newPayload));
95
+ }
96
+ });
97
+ };
98
+ const renderContentBlock = (block) => {
99
+ const animationClass = block.animation && block.animation !== "none" ? `animate-${block.animation === "fade" ? "fade-in" : block.animation === "slide" ? "slide-in-right" : "bounce-in"}` : "";
100
+ switch (block.type) {
101
+ case "text":
102
+ return /* @__PURE__ */ React.createElement(
103
+ "div",
104
+ {
105
+ className: cn("prose prose-sm max-w-none", animationClass),
106
+ style: block.styles,
107
+ dangerouslySetInnerHTML: { __html: block.content }
108
+ }
109
+ );
110
+ case "image":
111
+ return /* @__PURE__ */ React.createElement(
112
+ "img",
113
+ {
114
+ src: block.content || "/placeholder.svg",
115
+ alt: "Dynamic content",
116
+ className: cn("max-w-full h-auto rounded-lg", animationClass),
117
+ style: block.styles
118
+ }
119
+ );
120
+ case "video":
121
+ return /* @__PURE__ */ React.createElement(
122
+ "video",
123
+ {
124
+ src: block.content,
125
+ controls: true,
126
+ className: cn("max-w-full h-auto rounded-lg", animationClass),
127
+ style: block.styles
128
+ }
129
+ );
130
+ case "html":
131
+ return /* @__PURE__ */ React.createElement(
132
+ "div",
133
+ {
134
+ className: cn("w-full", animationClass),
135
+ style: block.styles,
136
+ dangerouslySetInnerHTML: { __html: block.content }
137
+ }
138
+ );
139
+ default:
140
+ return /* @__PURE__ */ React.createElement("div", { className: "text-muted-foreground" }, "Unknown content type");
141
+ }
142
+ };
143
+ return /* @__PURE__ */ React.createElement(Card, { className: "w-full my-4 border-2 border-dashed border-accent/30 bg-gradient-to-br from-background to-accent/5" }, /* @__PURE__ */ React.createElement(CardHeader, { className: "pb-3" }, /* @__PURE__ */ React.createElement("div", { className: "flex items-center justify-between" }, /* @__PURE__ */ React.createElement("div", { className: "flex items-center gap-2" }, /* @__PURE__ */ React.createElement(Zap, { className: "w-5 h-5 text-accent" }), /* @__PURE__ */ React.createElement(CardTitle, { className: "text-lg font-semibold" }, payload.title), /* @__PURE__ */ React.createElement(Badge, { variant: "secondary", className: "text-xs" }, "Dynamic Block")), /* @__PURE__ */ React.createElement("div", { className: "flex items-center gap-2" }, /* @__PURE__ */ React.createElement(Button, { variant: "ghost", size: "sm", onClick: () => setIsPreviewMode(!isPreviewMode), className: "h-8 px-2" }, isPreviewMode ? /* @__PURE__ */ React.createElement(EyeOff, { className: "w-4 h-4" }) : /* @__PURE__ */ React.createElement(Eye, { className: "w-4 h-4" }), isPreviewMode ? "Edit" : "Preview"), isPreviewMode && /* @__PURE__ */ React.createElement(Button, { variant: "ghost", size: "sm", onClick: () => setIsPlaying(!isPlaying), className: "h-8 px-2" }, isPlaying ? /* @__PURE__ */ React.createElement(Pause, { className: "w-4 h-4" }) : /* @__PURE__ */ React.createElement(Play, { className: "w-4 h-4" })), /* @__PURE__ */ React.createElement(Button, { variant: "ghost", size: "sm", onClick: () => setShowSettings(!showSettings), className: "h-8 px-2" }, /* @__PURE__ */ React.createElement(Settings, { className: "w-4 h-4" }))))), /* @__PURE__ */ React.createElement(CardContent, { ref: containerRef, className: "space-y-4" }, /* @__PURE__ */ React.createElement("div", { className: "min-h-[200px] p-4 rounded-lg border bg-card/50 relative overflow-hidden" }, currentBlock ? /* @__PURE__ */ React.createElement("div", { className: "transition-all duration-300 ease-in-out" }, renderContentBlock(currentBlock)) : /* @__PURE__ */ React.createElement("div", { className: "flex items-center justify-center h-full text-muted-foreground" }, /* @__PURE__ */ React.createElement("div", { className: "text-center" }, /* @__PURE__ */ React.createElement(Zap, { className: "w-12 h-12 mx-auto mb-2 opacity-50" }), /* @__PURE__ */ React.createElement("p", null, "No content block selected"), /* @__PURE__ */ React.createElement("p", { className: "text-sm" }, "Configure blocks and triggers below")))), !isPreviewMode && /* @__PURE__ */ React.createElement("div", { className: "space-y-3" }, /* @__PURE__ */ React.createElement("div", { className: "flex items-center justify-between" }, /* @__PURE__ */ React.createElement("h4", { className: "font-medium text-sm" }, "Content Blocks (", payload.blocks.length, ")"), /* @__PURE__ */ React.createElement(Button, { size: "sm", variant: "outline", className: "h-7 text-xs bg-transparent" }, "Add Block")), /* @__PURE__ */ React.createElement("div", { className: "grid grid-cols-2 md:grid-cols-3 gap-2" }, payload.blocks.map((block) => /* @__PURE__ */ React.createElement(
144
+ Button,
145
+ {
146
+ key: block.id,
147
+ variant: currentBlockId === block.id ? "default" : "outline",
148
+ size: "sm",
149
+ onClick: () => setCurrentBlockId(block.id),
150
+ className: "h-auto p-2 flex flex-col items-start text-left"
151
+ },
152
+ /* @__PURE__ */ React.createElement("div", { className: "font-medium text-xs capitalize" }, block.type),
153
+ /* @__PURE__ */ React.createElement("div", { className: "text-xs text-muted-foreground truncate w-full" }, block.content.substring(0, 30), "...")
154
+ )))), !isPreviewMode && activeTriggers.length > 0 && /* @__PURE__ */ React.createElement("div", { className: "space-y-2" }, /* @__PURE__ */ React.createElement("h4", { className: "font-medium text-sm" }, "Active Triggers (", activeTriggers.length, ")"), /* @__PURE__ */ React.createElement("div", { className: "flex flex-wrap gap-2" }, activeTriggers.map((trigger) => /* @__PURE__ */ React.createElement(Badge, { key: trigger.id, variant: "outline", className: "text-xs" }, trigger.type, ": ", trigger.action, trigger.type === "time" && ` (${trigger.condition}s)`)))), isPreviewMode && /* @__PURE__ */ React.createElement("div", { className: "text-center p-3 bg-accent/10 rounded-lg border border-accent/20" }, /* @__PURE__ */ React.createElement("p", { className: "text-sm text-accent font-medium" }, "Preview Mode Active"), /* @__PURE__ */ React.createElement("p", { className: "text-xs text-muted-foreground mt-1" }, activeTriggers.some((t) => t.type === "click") && "Click to trigger interactions \u2022 ", activeTriggers.some((t) => t.type === "hover") && "Hover to trigger interactions \u2022 ", activeTriggers.some((t) => t.type === "time") && "Press play for time-based triggers"))));
155
+ }
156
+ function $isDynamicBlockNode(node) {
157
+ return node instanceof DynamicBlockNode;
158
+ }
159
+ export {
160
+ DynamicBlockComponent as default
161
+ };
@@ -0,0 +1,154 @@
1
+ import {
2
+ $isEquationNode,
3
+ KatexRenderer
4
+ } from "./chunk-3JVFG7ER.mjs";
5
+ import {
6
+ React,
7
+ init_react_shim
8
+ } from "./chunk-77KXU36M.mjs";
9
+
10
+ // src/components/editor/nodes/EquationNode/EquationComponent.tsx
11
+ init_react_shim();
12
+ import { useLexicalComposerContext } from "@lexical/react/LexicalComposerContext";
13
+ import { useLexicalEditable } from "@lexical/react/useLexicalEditable";
14
+ import { mergeRegister } from "@lexical/utils";
15
+ import {
16
+ $getNodeByKey,
17
+ $getSelection,
18
+ $isNodeSelection,
19
+ COMMAND_PRIORITY_HIGH,
20
+ KEY_ESCAPE_COMMAND,
21
+ SELECTION_CHANGE_COMMAND
22
+ } from "lexical";
23
+ import * as React2 from "react";
24
+ import { useCallback, useEffect, useRef, useState } from "react";
25
+ import { ErrorBoundary } from "react-error-boundary";
26
+
27
+ // src/components/ui/equation/EquationEditor.tsx
28
+ init_react_shim();
29
+ import { isHTMLElement } from "lexical";
30
+ import { forwardRef } from "react";
31
+ function EquationEditor({ equation, setEquation, inline }, forwardedRef) {
32
+ const onChange = (event) => {
33
+ setEquation(event.target.value);
34
+ };
35
+ return inline && isHTMLElement(forwardedRef) ? /* @__PURE__ */ React.createElement("span", { className: "EquationEditor_inputBackground" }, /* @__PURE__ */ React.createElement("span", { className: "EquationEditor_dollarSign" }, "$"), /* @__PURE__ */ React.createElement(
36
+ "input",
37
+ {
38
+ className: "EquationEditor_inlineEditor",
39
+ value: equation,
40
+ onChange,
41
+ autoFocus: true,
42
+ ref: forwardedRef
43
+ }
44
+ ), /* @__PURE__ */ React.createElement("span", { className: "EquationEditor_dollarSign" }, "$")) : /* @__PURE__ */ React.createElement("div", { className: "EquationEditor_inputBackground" }, /* @__PURE__ */ React.createElement("span", { className: "EquationEditor_dollarSign" }, "$$\n"), /* @__PURE__ */ React.createElement(
45
+ "textarea",
46
+ {
47
+ className: "EquationEditor_blockEditor",
48
+ value: equation,
49
+ onChange,
50
+ ref: forwardedRef
51
+ }
52
+ ), /* @__PURE__ */ React.createElement("span", { className: "EquationEditor_dollarSign" }, "\n$$"));
53
+ }
54
+ var EquationEditor_default = forwardRef(EquationEditor);
55
+
56
+ // src/components/editor/nodes/EquationNode/EquationComponent.tsx
57
+ function EquationComponent({
58
+ equation,
59
+ inline,
60
+ nodeKey
61
+ }) {
62
+ const [editor] = useLexicalComposerContext();
63
+ const isEditable = useLexicalEditable();
64
+ const [equationValue, setEquationValue] = useState(equation);
65
+ const [showEquationEditor, setShowEquationEditor] = useState(false);
66
+ const inputRef = useRef(null);
67
+ const onHide = useCallback(
68
+ (restoreSelection) => {
69
+ setShowEquationEditor(false);
70
+ editor.update(() => {
71
+ const node = $getNodeByKey(nodeKey);
72
+ if ($isEquationNode(node)) {
73
+ node.setEquation(equationValue);
74
+ if (restoreSelection) {
75
+ node.selectNext(0, 0);
76
+ }
77
+ }
78
+ });
79
+ },
80
+ [editor, equationValue, nodeKey]
81
+ );
82
+ useEffect(() => {
83
+ if (!showEquationEditor && equationValue !== equation) {
84
+ setEquationValue(equation);
85
+ }
86
+ }, [showEquationEditor, equation, equationValue]);
87
+ useEffect(() => {
88
+ if (!isEditable) {
89
+ return;
90
+ }
91
+ if (showEquationEditor) {
92
+ return mergeRegister(
93
+ editor.registerCommand(
94
+ SELECTION_CHANGE_COMMAND,
95
+ (payload) => {
96
+ const activeElement = document.activeElement;
97
+ const inputElem = inputRef.current;
98
+ if (inputElem !== activeElement) {
99
+ onHide();
100
+ }
101
+ return false;
102
+ },
103
+ COMMAND_PRIORITY_HIGH
104
+ ),
105
+ editor.registerCommand(
106
+ KEY_ESCAPE_COMMAND,
107
+ (payload) => {
108
+ const activeElement = document.activeElement;
109
+ const inputElem = inputRef.current;
110
+ if (inputElem === activeElement) {
111
+ onHide(true);
112
+ return true;
113
+ }
114
+ return false;
115
+ },
116
+ COMMAND_PRIORITY_HIGH
117
+ )
118
+ );
119
+ } else {
120
+ return editor.registerUpdateListener(({ editorState }) => {
121
+ const isSelected = editorState.read(() => {
122
+ const selection = $getSelection();
123
+ return $isNodeSelection(selection) && selection.has(nodeKey) && selection.getNodes().length === 1;
124
+ });
125
+ if (isSelected) {
126
+ setShowEquationEditor(true);
127
+ }
128
+ });
129
+ }
130
+ }, [editor, nodeKey, onHide, showEquationEditor, isEditable]);
131
+ return /* @__PURE__ */ React2.createElement(React2.Fragment, null, showEquationEditor && isEditable ? /* @__PURE__ */ React2.createElement(
132
+ EquationEditor_default,
133
+ {
134
+ equation: equationValue,
135
+ setEquation: setEquationValue,
136
+ inline,
137
+ ref: inputRef
138
+ }
139
+ ) : /* @__PURE__ */ React2.createElement(ErrorBoundary, { onError: (e) => editor._onError(e), fallback: null }, /* @__PURE__ */ React2.createElement(
140
+ KatexRenderer,
141
+ {
142
+ equation: equationValue,
143
+ inline,
144
+ onDoubleClick: () => {
145
+ if (isEditable) {
146
+ setShowEquationEditor(true);
147
+ }
148
+ }
149
+ }
150
+ )));
151
+ }
152
+ export {
153
+ EquationComponent as default
154
+ };