@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
@@ -0,0 +1,1547 @@
1
+ import {
2
+ CodeList
3
+ } from "./chunk-TTHQCW5F.mjs";
4
+ import {
5
+ INSERT_TEMPLATE_COMMAND
6
+ } from "./chunk-YKC3SO4Z.mjs";
7
+ import {
8
+ EXPORT_MARKDOWN_COMMAND,
9
+ EXPORT_PDF_COMMAND
10
+ } from "./chunk-ZJRKATOJ.mjs";
11
+ import {
12
+ Toggle
13
+ } from "./chunk-Z4EWP7BI.mjs";
14
+ import {
15
+ getSelectedNode
16
+ } from "./chunk-4HBCVSE6.mjs";
17
+ import "./chunk-EGMI62PP.mjs";
18
+ import "./chunk-KJ6AJ44Q.mjs";
19
+ import "./chunk-64Z3FI7T.mjs";
20
+ import {
21
+ SPEECH_TO_TEXT_COMMAND,
22
+ SUPPORT_SPEECH_RECOGNITION
23
+ } from "./chunk-77UA6HYR.mjs";
24
+ import {
25
+ $isDynamicBlockNode
26
+ } from "./chunk-5BAKY5KN.mjs";
27
+ import {
28
+ SHORTCUTS
29
+ } from "./chunk-ZB5LZQKC.mjs";
30
+ import {
31
+ blockTypeToBlockName,
32
+ useToolbarState
33
+ } from "./chunk-7NZAPJ4G.mjs";
34
+ import {
35
+ Separator
36
+ } from "./chunk-TCYK7DM7.mjs";
37
+ import {
38
+ $isPollNode
39
+ } from "./chunk-GZPNVR7L.mjs";
40
+ import {
41
+ sanitizeUrl
42
+ } from "./chunk-4VWFVWYP.mjs";
43
+ import {
44
+ $isStoryBuilderNode
45
+ } from "./chunk-4MEDW3T6.mjs";
46
+ import {
47
+ Dialog,
48
+ DialogContent,
49
+ DialogDescription,
50
+ DialogHeader,
51
+ DialogTitle,
52
+ DialogTrigger
53
+ } from "./chunk-WDG7J2DY.mjs";
54
+ import {
55
+ Button
56
+ } from "./chunk-BIU7WTLX.mjs";
57
+ import {
58
+ cn
59
+ } from "./chunk-YHPNOWFH.mjs";
60
+ import {
61
+ React,
62
+ init_react_shim
63
+ } from "./chunk-77KXU36M.mjs";
64
+
65
+ // src/components/editor/plugins/ToolbarPlugin/index.tsx
66
+ init_react_shim();
67
+ import React2, { useCallback, useEffect, useState as useState2 } from "react";
68
+ import {
69
+ $getNodeByKey,
70
+ $getSelection,
71
+ $isElementNode,
72
+ $isLineBreakNode,
73
+ $isRangeSelection,
74
+ $isRootOrShadowRoot,
75
+ BLUR_COMMAND,
76
+ CAN_REDO_COMMAND,
77
+ CAN_UNDO_COMMAND,
78
+ COMMAND_PRIORITY_CRITICAL,
79
+ FOCUS_COMMAND,
80
+ FORMAT_TEXT_COMMAND,
81
+ REDO_COMMAND,
82
+ SELECTION_CHANGE_COMMAND,
83
+ UNDO_COMMAND
84
+ } from "lexical";
85
+
86
+ // src/components/editor/plugins/TemplatePlugin/TemplateDialog.tsx
87
+ init_react_shim();
88
+ import { useLexicalComposerContext } from "@lexical/react/LexicalComposerContext";
89
+ import { LayoutTemplate } from "lucide-react";
90
+ import { useState } from "react";
91
+
92
+ // src/components/editor/templates/data.ts
93
+ init_react_shim();
94
+ var TEMPLATES = [
95
+ {
96
+ id: "meeting-notes",
97
+ name: "Meeting Notes",
98
+ description: "Standard meeting minutes format",
99
+ content: `# Meeting Notes
100
+ Date:
101
+ attendees:
102
+
103
+ ## Agenda
104
+ 1.
105
+ 2.
106
+
107
+ ## Action Items
108
+ - [ ]
109
+ - [ ]
110
+ `
111
+ },
112
+ {
113
+ id: "daily-journal",
114
+ name: "Daily Journal",
115
+ description: "Reflect on your day",
116
+ content: `# Daily Journal
117
+ Date:
118
+
119
+ ## Highlights
120
+ -
121
+
122
+ ## Challenges
123
+ -
124
+
125
+ ## Plan for Tomorrow
126
+ -
127
+ `
128
+ },
129
+ {
130
+ id: "product-spec",
131
+ name: "Product Specification",
132
+ description: "Define a new feature or product",
133
+ content: `# Product Spec: [Title]
134
+
135
+ ## Problem Statement
136
+ What problem are we solving?
137
+
138
+ ## Solution
139
+ Describe the solution.
140
+
141
+ ## Requirements
142
+ - Requirement 1
143
+ - Requirement 2
144
+ `
145
+ }
146
+ ];
147
+
148
+ // src/components/editor/plugins/TemplatePlugin/TemplateDialog.tsx
149
+ function TemplateDialog() {
150
+ const [editor] = useLexicalComposerContext();
151
+ const [open, setOpen] = useState(false);
152
+ const insertTemplate = (content) => {
153
+ editor.dispatchCommand(INSERT_TEMPLATE_COMMAND, content);
154
+ setOpen(false);
155
+ };
156
+ return /* @__PURE__ */ React.createElement(Dialog, { open, onOpenChange: setOpen }, /* @__PURE__ */ React.createElement(DialogTrigger, { asChild: true }, /* @__PURE__ */ React.createElement(Button, { variant: "outline", size: "Toolbar", className: "border-none", tip: "Insert Template" }, /* @__PURE__ */ React.createElement(LayoutTemplate, { className: "size-4" }))), /* @__PURE__ */ React.createElement(DialogContent, { className: "sm:max-w-[425px]" }, /* @__PURE__ */ React.createElement(DialogHeader, null, /* @__PURE__ */ React.createElement(DialogTitle, null, "Choose a Template"), /* @__PURE__ */ React.createElement(DialogDescription, null, "Select a template to get started quickly.")), /* @__PURE__ */ React.createElement("div", { className: "grid gap-4 py-4" }, TEMPLATES.map((template) => /* @__PURE__ */ React.createElement(
157
+ Button,
158
+ {
159
+ key: template.id,
160
+ variant: "outline",
161
+ className: "justify-start h-auto flex-col items-start gap-1",
162
+ onClick: () => insertTemplate(template.content)
163
+ },
164
+ /* @__PURE__ */ React.createElement("span", { className: "font-medium" }, template.name),
165
+ /* @__PURE__ */ React.createElement("span", { className: "text-xs text-muted-foreground" }, template.description)
166
+ )))));
167
+ }
168
+
169
+ // src/components/editor/plugins/ToolbarPlugin/index.tsx
170
+ import { Bold, Code, DownloadIcon, FileJson, FileText, Italic, Link, Mic, Redo2Icon, Underline, Undo2Icon } from "lucide-react";
171
+ import {
172
+ $findMatchingParent,
173
+ $getNearestNodeOfType,
174
+ $isEditorIsNestedEditor,
175
+ mergeRegister
176
+ } from "@lexical/utils";
177
+ import {
178
+ $getSelectionStyleValueForProperty
179
+ } from "@lexical/selection";
180
+ import { $isLinkNode, TOGGLE_LINK_COMMAND } from "@lexical/link";
181
+ import { $isTableNode, $isTableSelection } from "@lexical/table";
182
+ import { $isListNode, ListNode } from "@lexical/list";
183
+ import { $isHeadingNode } from "@lexical/rich-text";
184
+ import { $isCodeNode, CODE_LANGUAGE_MAP } from "@lexical/code";
185
+ import dynamic from "next/dynamic";
186
+
187
+ // src/utils/htmlExport.tsx
188
+ init_react_shim();
189
+ import { $getRoot } from "lexical";
190
+ import { $generateHtmlFromNodes } from "@lexical/html";
191
+ function exportEditorToHTML(editor) {
192
+ return editor.getEditorState().read(() => {
193
+ const root = $getRoot();
194
+ const rootElement = editor.getRootElement();
195
+ if (!rootElement) {
196
+ return "<div></div>";
197
+ }
198
+ const htmlString = $generateHtmlFromNodes(editor, null);
199
+ const children = root.getChildren();
200
+ const specialNodesHTML = [];
201
+ children.forEach((child) => {
202
+ const specialHTML = convertSpecialNodeToHTML(child);
203
+ if (specialHTML) {
204
+ specialNodesHTML.push(specialHTML);
205
+ }
206
+ });
207
+ let finalHTML = htmlString;
208
+ if (specialNodesHTML.length > 0) {
209
+ const clonedElement = rootElement.cloneNode(true);
210
+ const cleanElement = (element) => {
211
+ element.classList.remove(
212
+ "editor-content",
213
+ "relative",
214
+ "z-20",
215
+ "outline-none",
216
+ "focus:outline-none",
217
+ "focus:ring-0",
218
+ "selection:bg-blue-100",
219
+ "dark:selection:bg-blue-900/30",
220
+ "transition-all",
221
+ "duration-200",
222
+ "ease-in-out"
223
+ );
224
+ element.removeAttribute("contenteditable");
225
+ element.removeAttribute("role");
226
+ element.removeAttribute("spellcheck");
227
+ element.removeAttribute("data-lexical-editor");
228
+ Array.from(element.children).forEach((child) => {
229
+ cleanElement(child);
230
+ });
231
+ };
232
+ cleanElement(clonedElement);
233
+ const regularHTML = clonedElement.innerHTML || "<div></div>";
234
+ finalHTML = specialNodesHTML.length > 0 ? regularHTML + "\n\n" + specialNodesHTML.join("\n\n") : regularHTML;
235
+ }
236
+ return finalHTML;
237
+ });
238
+ }
239
+ function downloadHTML(htmlContent, filename = "document.html") {
240
+ const fullHTML = `<!DOCTYPE html>
241
+ <html lang="en">
242
+ <head>
243
+ <meta charset="UTF-8">
244
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
245
+ <title>Exported Document</title>
246
+ <script src="https://cdn.tailwindcss.com"></script>
247
+ <script>
248
+ tailwind.config = {
249
+ darkMode: 'class',
250
+ theme: {
251
+ extend: {
252
+ colors: {
253
+ background: 'oklch(1 0 0)',
254
+ foreground: 'oklch(0.145 0 0)',
255
+ card: 'oklch(1 0 0)',
256
+ 'card-foreground': 'oklch(0.145 0 0)',
257
+ popover: 'oklch(1 0 0)',
258
+ 'popover-foreground': 'oklch(0.145 0 0)',
259
+ primary: 'oklch(0.205 0 0)',
260
+ 'primary-foreground': 'oklch(0.985 0 0)',
261
+ secondary: 'oklch(0.97 0 0)',
262
+ 'secondary-foreground': 'oklch(0.205 0 0)',
263
+ muted: 'oklch(0.97 0 0)',
264
+ 'muted-foreground': 'oklch(0.556 0 0)',
265
+ accent: 'oklch(0.97 0 0)',
266
+ 'accent-foreground': 'oklch(0.205 0 0)',
267
+ destructive: 'oklch(0.577 0.245 27.325)',
268
+ 'destructive-foreground': 'oklch(0.577 0.245 27.325)',
269
+ border: 'oklch(0.922 0 0)',
270
+ input: 'oklch(0.922 0 0)',
271
+ ring: 'oklch(0.708 0 0)',
272
+ },
273
+ fontFamily: {
274
+ sans: ['Inter', 'system-ui', 'sans-serif'],
275
+ mono: ['Monaco', 'Consolas', 'monospace'],
276
+ },
277
+ typography: {
278
+ DEFAULT: {
279
+ css: {
280
+ maxWidth: 'none',
281
+ color: 'oklch(0.145 0 0)',
282
+ lineHeight: '1.75',
283
+ }
284
+ }
285
+ }
286
+ }
287
+ }
288
+ }
289
+ </script>
290
+ <style>
291
+ @import url('https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&display=swap');
292
+
293
+ body {
294
+ font-family: 'Inter', system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
295
+ line-height: 1.75;
296
+ color: oklch(0.145 0 0);
297
+ background-color: oklch(1 0 0);
298
+ font-weight: 400;
299
+ letter-spacing: 0.025em;
300
+ -webkit-font-smoothing: antialiased;
301
+ -moz-osx-font-smoothing: grayscale;
302
+ }
303
+
304
+ .dark body {
305
+ color: oklch(0.985 0 0);
306
+ background-color: oklch(0.145 0 0);
307
+ }
308
+
309
+ /* Preserve editor content styling */
310
+ .editor-content,
311
+ .prose {
312
+ max-width: none !important;
313
+ font-size: 1.125rem;
314
+ line-height: 1.75;
315
+ letter-spacing: 0.025em;
316
+ }
317
+
318
+ /* Typography styles matching the editor */
319
+ h1, h2, h3, h4, h5, h6 {
320
+ font-weight: 600;
321
+ line-height: 1.25;
322
+ margin-top: 2rem;
323
+ margin-bottom: 1rem;
324
+ letter-spacing: -0.025em;
325
+ }
326
+
327
+ h1 { font-size: 2.25rem; }
328
+ h2 { font-size: 1.875rem; }
329
+ h3 { font-size: 1.5rem; }
330
+ h4 { font-size: 1.25rem; }
331
+ h5 { font-size: 1.125rem; }
332
+ h6 { font-size: 1rem; }
333
+
334
+ p {
335
+ margin-bottom: 1.25rem;
336
+ line-height: 1.75;
337
+ }
338
+
339
+ /* List styles */
340
+ ul, ol {
341
+ margin-bottom: 1.25rem;
342
+ padding-left: 1.75rem;
343
+ }
344
+
345
+ li {
346
+ margin-bottom: 0.5rem;
347
+ line-height: 1.75;
348
+ }
349
+
350
+ /* Blockquote styles */
351
+ blockquote {
352
+ border-left: 4px solid oklch(0.708 0 0);
353
+ margin: 1.5rem 0;
354
+ padding-left: 1.5rem;
355
+ color: oklch(0.556 0 0);
356
+ font-style: italic;
357
+ font-size: 1.125rem;
358
+ }
359
+
360
+ /* Code styles */
361
+ code {
362
+ background-color: oklch(0.97 0 0);
363
+ color: oklch(0.205 0 0);
364
+ padding: 0.25rem 0.5rem;
365
+ border-radius: 0.375rem;
366
+ font-family: 'Monaco', 'Consolas', 'Courier New', monospace;
367
+ font-size: 0.875rem;
368
+ }
369
+
370
+ pre {
371
+ background-color: oklch(0.97 0 0);
372
+ color: oklch(0.205 0 0);
373
+ padding: 1.5rem;
374
+ border-radius: 0.75rem;
375
+ overflow-x: auto;
376
+ margin: 1.5rem 0;
377
+ font-family: 'Monaco', 'Consolas', 'Courier New', monospace;
378
+ line-height: 1.5;
379
+ }
380
+
381
+ pre code {
382
+ background: none;
383
+ padding: 0;
384
+ border-radius: 0;
385
+ color: inherit;
386
+ }
387
+
388
+ /* Table styles */
389
+ table {
390
+ border-collapse: collapse;
391
+ width: 100%;
392
+ margin: 1.5rem 0;
393
+ border-radius: 0.5rem;
394
+ overflow: hidden;
395
+ border: 1px solid oklch(0.922 0 0);
396
+ }
397
+
398
+ th, td {
399
+ border: 1px solid oklch(0.922 0 0);
400
+ padding: 0.75rem 1rem;
401
+ text-align: left;
402
+ line-height: 1.5;
403
+ }
404
+
405
+ th {
406
+ background-color: oklch(0.97 0 0);
407
+ font-weight: 600;
408
+ color: oklch(0.205 0 0);
409
+ }
410
+
411
+ /* Image styles */
412
+ img {
413
+ max-width: 100%;
414
+ height: auto;
415
+ border-radius: 0.5rem;
416
+ margin: 1.5rem 0;
417
+ }
418
+
419
+ /* Link styles */
420
+ a {
421
+ color: oklch(0.488 0.243 264.376);
422
+ text-decoration: underline;
423
+ text-decoration-color: oklch(0.488 0.243 264.376 / 0.3);
424
+ text-underline-offset: 0.25rem;
425
+ transition: all 0.2s ease;
426
+ }
427
+
428
+ a:hover {
429
+ text-decoration-color: oklch(0.488 0.243 264.376);
430
+ }
431
+
432
+ /* Enhanced styles for special components */
433
+ /* Poll component styles */
434
+ .poll-container {
435
+ background: white;
436
+ border: 1px solid #e5e7eb;
437
+ border-radius: 0.5rem;
438
+ box-shadow: 0 1px 3px 0 rgba(0, 0, 0, 0.1);
439
+ margin: 1.5rem 0;
440
+ }
441
+
442
+ .poll-option {
443
+ position: relative;
444
+ overflow: hidden;
445
+ }
446
+
447
+ .poll-progress {
448
+ position: absolute;
449
+ top: 0;
450
+ left: 0;
451
+ height: 100%;
452
+ background: rgba(59, 130, 246, 0.3);
453
+ border-radius: 0.375rem;
454
+ transition: width 1s ease;
455
+ }
456
+
457
+ /* Story builder styles */
458
+ .story-node {
459
+ transition: opacity 0.4s ease-in-out, transform 0.4s ease-in-out;
460
+ transform: translateY(0);
461
+ }
462
+
463
+ .story-node.hidden {
464
+ display: none;
465
+ opacity: 0;
466
+ transform: translateY(20px);
467
+ }
468
+
469
+ .story-choice {
470
+ transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
471
+ }
472
+
473
+ .story-choice:hover {
474
+ transform: translateY(-2px);
475
+ box-shadow: 0 8px 25px rgba(0, 0, 0, 0.15);
476
+ }
477
+
478
+ .story-choice:active {
479
+ transform: translateY(-1px);
480
+ transition: all 0.1s ease;
481
+ }
482
+
483
+ .story-choice:disabled {
484
+ cursor: not-allowed;
485
+ opacity: 0.5;
486
+ }
487
+
488
+ .story-choice:disabled:hover {
489
+ transform: none;
490
+ box-shadow: none;
491
+ }
492
+
493
+ /* Dynamic block styles */
494
+ .dynamic-block-container {
495
+ border: 2px dashed #93c5fd;
496
+ background: linear-gradient(135deg, #ffffff 0%, #eff6ff 100%);
497
+ }
498
+
499
+ .block-selector {
500
+ cursor: pointer;
501
+ transition: all 0.2s ease;
502
+ }
503
+
504
+ .block-selector:hover {
505
+ transform: translateY(-1px);
506
+ box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
507
+ }
508
+
509
+ /* Dark mode styles */
510
+ .dark code {
511
+ background-color: oklch(0.269 0 0);
512
+ color: oklch(0.985 0 0);
513
+ }
514
+
515
+ .dark pre {
516
+ background-color: oklch(0.269 0 0);
517
+ color: oklch(0.985 0 0);
518
+ }
519
+
520
+ .dark th {
521
+ background-color: oklch(0.269 0 0);
522
+ color: oklch(0.985 0 0);
523
+ }
524
+
525
+ .dark table,
526
+ .dark th,
527
+ .dark td {
528
+ border-color: oklch(0.269 0 0);
529
+ }
530
+
531
+ .dark blockquote {
532
+ border-left-color: oklch(0.439 0 0);
533
+ color: oklch(0.708 0 0);
534
+ }
535
+
536
+ .dark .poll-container {
537
+ background: #1f2937;
538
+ border-color: #374151;
539
+ }
540
+
541
+ .dark .dynamic-block-container {
542
+ border-color: #3b82f6;
543
+ background: linear-gradient(135deg, #1f2937 0%, #1e3a8a 100%);
544
+ }
545
+
546
+ /* Container styling to match editor */
547
+ .document-container {
548
+ max-width: 80rem;
549
+ margin: 0 auto;
550
+ padding: 2rem 1rem;
551
+ background-color: oklch(1 0 0);
552
+ min-height: 100vh;
553
+ }
554
+
555
+ .dark .document-container {
556
+ background-color: oklch(0.145 0 0);
557
+ }
558
+
559
+ @media (min-width: 768px) {
560
+ .document-container {
561
+ padding: 4rem 3rem;
562
+ border-radius: 1rem;
563
+ margin: 2rem auto;
564
+ min-height: calc(100vh - 4rem);
565
+ box-shadow: 0 25px 50px -12px rgba(0, 0, 0, 0.05);
566
+ border: 1px solid oklch(0.922 0 0 / 0.5);
567
+ }
568
+
569
+ .dark .document-container {
570
+ border-color: oklch(0.269 0 0 / 0.5);
571
+ box-shadow: 0 25px 50px -12px rgba(0, 0, 0, 0.2);
572
+ }
573
+ }
574
+
575
+ /* Print styles */
576
+ @media print {
577
+ .document-container {
578
+ box-shadow: none;
579
+ border: none;
580
+ margin: 0;
581
+ padding: 1rem;
582
+ }
583
+ }
584
+ </style>
585
+ </head>
586
+ <body>
587
+ <div class="document-container">
588
+ ${htmlContent}
589
+ </div>
590
+
591
+ <script>
592
+ // Dark mode detection
593
+ if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) {
594
+ document.documentElement.classList.add('dark');
595
+ }
596
+
597
+ // Listen for dark mode changes
598
+ window.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', e => {
599
+ if (e.matches) {
600
+ document.documentElement.classList.add('dark');
601
+ } else {
602
+ document.documentElement.classList.remove('dark');
603
+ }
604
+ });
605
+
606
+ window.showStoryNode = function(nodeId) {
607
+ console.log('[v0] Navigating to story node:', nodeId);
608
+
609
+ // Hide all story nodes with smooth transition
610
+ const allNodes = document.querySelectorAll('.story-node');
611
+ allNodes.forEach(node => {
612
+ node.style.opacity = '0';
613
+ node.style.transform = 'translateY(20px)';
614
+ });
615
+
616
+ // After transition, hide nodes and show target
617
+ setTimeout(() => {
618
+ allNodes.forEach(node => {
619
+ node.classList.add('hidden');
620
+ });
621
+
622
+ const targetNode = document.getElementById('story-node-' + nodeId);
623
+ if (targetNode) {
624
+ console.log('[v0] Found target node:', targetNode);
625
+ targetNode.classList.remove('hidden');
626
+ targetNode.style.opacity = '0';
627
+ targetNode.style.transform = 'translateY(20px)';
628
+
629
+ // Scroll to the story container smoothly
630
+ const storyContainer = document.getElementById('story-container');
631
+ if (storyContainer) {
632
+ storyContainer.scrollIntoView({
633
+ behavior: 'smooth',
634
+ block: 'start',
635
+ inline: 'nearest'
636
+ });
637
+ }
638
+
639
+ // Fade in the new node
640
+ setTimeout(() => {
641
+ targetNode.style.opacity = '1';
642
+ targetNode.style.transform = 'translateY(0)';
643
+ }, 100);
644
+ } else {
645
+ console.error('[v0] Target node not found:', nodeId);
646
+ }
647
+ }, 200);
648
+ };
649
+
650
+ window.restartStory = function() {
651
+ console.log('[v0] Restarting story');
652
+ // Find the first story node (should be the start node)
653
+ const firstNode = document.querySelector('.story-node[data-node-id]');
654
+ if (firstNode) {
655
+ const startNodeId = firstNode.getAttribute('data-node-id');
656
+ console.log('[v0] Found start node:', startNodeId);
657
+ window.showStoryNode(startNodeId);
658
+ } else {
659
+ console.error('[v0] No story nodes found');
660
+ }
661
+ };
662
+
663
+ window.showDynamicBlock = function(containerId, blockId) {
664
+ const container = document.getElementById('dynamic-content-' + containerId);
665
+ if (container) {
666
+ // Update active button styling
667
+ container.parentElement.querySelectorAll('.block-selector').forEach(btn => {
668
+ btn.classList.remove('bg-blue-100', 'border-blue-500');
669
+ btn.classList.add('bg-gray-50', 'border-gray-200');
670
+ });
671
+
672
+ // Find and highlight the clicked button
673
+ const clickedBtn = event.target.closest('.block-selector');
674
+ if (clickedBtn) {
675
+ clickedBtn.classList.remove('bg-gray-50', 'border-gray-200');
676
+ clickedBtn.classList.add('bg-blue-100', 'border-blue-500');
677
+ }
678
+
679
+ // Simple content update (in a real implementation, you'd embed the actual block data)
680
+ container.innerHTML = '<div class="text-center text-gray-500 p-8">Selected block: ' + blockId + '</div>';
681
+ }
682
+ };
683
+
684
+ document.addEventListener('DOMContentLoaded', function() {
685
+ console.log('[v0] DOM loaded, initializing story');
686
+
687
+ // Ensure the first story node is visible and others are hidden
688
+ const storyNodes = document.querySelectorAll('.story-node');
689
+ console.log('[v0] Found story nodes:', storyNodes.length);
690
+
691
+ if (storyNodes.length > 0) {
692
+ storyNodes.forEach((node, index) => {
693
+ if (index === 0) {
694
+ console.log('[v0] Showing first node:', node.id);
695
+ node.classList.remove('hidden');
696
+ node.style.opacity = '1';
697
+ node.style.transform = 'translateY(0)';
698
+ } else {
699
+ console.log('[v0] Hiding node:', node.id);
700
+ node.classList.add('hidden');
701
+ node.style.opacity = '0';
702
+ node.style.transform = 'translateY(20px)';
703
+ }
704
+ });
705
+ }
706
+ });
707
+ </script>
708
+ </body>
709
+ </html>`;
710
+ const blob = new Blob([fullHTML], { type: "text/html" });
711
+ const url = URL.createObjectURL(blob);
712
+ const link = document.createElement("a");
713
+ link.href = url;
714
+ link.download = filename;
715
+ document.body.appendChild(link);
716
+ link.click();
717
+ document.body.removeChild(link);
718
+ URL.revokeObjectURL(url);
719
+ }
720
+ function convertSpecialNodeToHTML(node) {
721
+ if ($isPollNode(node)) {
722
+ return convertPollNodeToHTML(node);
723
+ }
724
+ if ($isStoryBuilderNode(node)) {
725
+ return convertStoryBuilderNodeToHTML(node);
726
+ }
727
+ if ($isDynamicBlockNode(node)) {
728
+ return convertDynamicBlockNodeToHTML(node);
729
+ }
730
+ return null;
731
+ }
732
+ function convertPollNodeToHTML(node) {
733
+ const question = node.exportJSON().question;
734
+ const options = node.exportJSON().options;
735
+ const optionsHTML = options.map((option, index) => {
736
+ const totalVotes = options.reduce((sum, opt) => sum + opt.votes.length, 0);
737
+ const votes = option.votes.length;
738
+ const percentage = totalVotes > 0 ? votes / totalVotes * 100 : 0;
739
+ return `
740
+ <div class="poll-option flex flex-row items-center justify-center gap-x-2 mb-3">
741
+ <div>
742
+ <input type="checkbox" disabled class="rounded border-gray-300" />
743
+ </div>
744
+ <div class="flex relative overflow-hidden flex-1">
745
+ <div
746
+ class="poll-progress h-9 overflow-hidden bg-blue-500/30 dark:bg-blue-300/50 rounded-md absolute top-0 left-0 w-full py-2 transition-all duration-1000"
747
+ style="width: ${percentage}%"
748
+ ></div>
749
+ <span class="absolute text-xs font-bold right-2 top-1">
750
+ ${votes > 0 ? votes === 1 ? "1 vote" : `${votes} votes` : ""}
751
+ </span>
752
+ <div class="overflow-hidden ring-0 outline-none bg-transparent border border-gray-300 rounded-md px-3 py-2 w-full">
753
+ ${option.text}
754
+ </div>
755
+ </div>
756
+ </div>
757
+ `;
758
+ }).join("");
759
+ return `
760
+ <div class="poll-container bg-white dark:bg-gray-800 border border-gray-200 dark:border-gray-700 rounded-lg shadow-sm my-6">
761
+ <div class="p-6 text-center border-b border-gray-200 dark:border-gray-700">
762
+ <h3 class="text-xl font-semibold text-gray-900 dark:text-gray-100">${question}</h3>
763
+ </div>
764
+ <div class="p-6 space-y-2">
765
+ ${optionsHTML}
766
+ </div>
767
+ </div>
768
+ `;
769
+ }
770
+ function convertStoryBuilderNodeToHTML(node) {
771
+ const data = node.exportJSON();
772
+ const { title, nodes } = data;
773
+ const startNode = nodes.find((n) => n.isStart) || nodes[0];
774
+ if (!startNode) {
775
+ return `
776
+ <div class="bg-white dark:bg-gray-800 border border-gray-200 dark:border-gray-700 rounded-lg shadow-sm my-6 p-6">
777
+ <h3 class="text-xl font-semibold mb-4">${title}</h3>
778
+ <p class="text-gray-600 dark:text-gray-400">No story content available.</p>
779
+ </div>
780
+ `;
781
+ }
782
+ const renderStoryNode = (storyNode, index) => {
783
+ const choicesHTML = storyNode.choices.map((choice) => {
784
+ const targetNode = nodes.find((n) => n.id === choice.targetId);
785
+ return `
786
+ <button
787
+ class="story-choice w-full justify-start text-left h-auto p-4 group transition-all duration-300 border-2 border-gray-200 dark:border-gray-700 rounded-lg hover:border-blue-500 hover:bg-blue-50 dark:hover:bg-blue-900/20 hover:shadow-lg hover:scale-[1.02] mb-3 ${!targetNode ? "opacity-50 cursor-not-allowed" : "cursor-pointer"}"
788
+ onclick="${targetNode ? `window.showStoryNode('${choice.targetId}')` : ""}"
789
+ ${!targetNode ? "disabled" : ""}
790
+ >
791
+ <div class="flex items-start gap-4 w-full">
792
+ <div class="text-2xl">\u27A4</div>
793
+ <div class="flex-1">
794
+ <div class="font-semibold text-base group-hover:text-blue-600 transition-colors">
795
+ ${choice.text}
796
+ </div>
797
+ </div>
798
+ <svg class="w-5 h-5 opacity-0 group-hover:opacity-100 transition-opacity text-blue-600" fill="none" stroke="currentColor" viewBox="0 0 24 24">
799
+ <path strokeLinecap="round" strokeLinejoin="round" strokeWidth="2" d="M9 5l7 7-7 7"></path>
800
+ </svg>
801
+ </div>
802
+ </button>
803
+ `;
804
+ }).join("");
805
+ return `
806
+ <div id="story-node-${storyNode.id}" class="story-node ${storyNode.id !== startNode.id ? "hidden" : ""}" data-node-id="${storyNode.id}">
807
+ <div class="prose prose-xl max-w-none mb-6">
808
+ <h2 class="text-3xl font-bold mb-6 text-gray-900 dark:text-gray-100">
809
+ ${storyNode.title}
810
+ </h2>
811
+ <div class="text-lg leading-relaxed text-gray-700 dark:text-gray-300 whitespace-pre-wrap">
812
+ ${storyNode.content}
813
+ </div>
814
+ </div>
815
+
816
+ ${storyNode.choices.length > 0 ? `
817
+ <div class="space-y-4 mt-8">
818
+ <h3 class="font-bold text-xl flex items-center gap-2 text-gray-900 dark:text-gray-100">
819
+ <span class="text-blue-600">\u{1F3AF}</span>
820
+ What's your next move?
821
+ </h3>
822
+ <div class="grid gap-3">
823
+ ${choicesHTML}
824
+ </div>
825
+ </div>
826
+ ` : ""}
827
+
828
+ ${storyNode.isEnd ? `
829
+ <div class="text-center py-8 bg-gray-50 dark:bg-gray-800 border-2 border-gray-200 dark:border-gray-700 rounded-2xl mt-8">
830
+ <div class="text-6xl mb-4">\u{1F3AD}</div>
831
+ <span class="inline-flex items-center px-6 py-3 rounded-full text-lg font-medium bg-gray-100 text-gray-800 dark:bg-gray-700 dark:text-gray-200">
832
+ The End
833
+ </span>
834
+ <p class="text-gray-600 dark:text-gray-400 mt-4">Thank you for experiencing this story!</p>
835
+ <button
836
+ onclick="window.restartStory()"
837
+ class="mt-4 px-6 py-2 bg-blue-600 text-white rounded-lg hover:bg-blue-700 transition-colors"
838
+ >
839
+ Start Over
840
+ </button>
841
+ </div>
842
+ ` : ""}
843
+ </div>
844
+ `;
845
+ };
846
+ const allNodesHTML = nodes.map(renderStoryNode).join("");
847
+ return `
848
+ <div class="bg-white dark:bg-gray-800 border border-gray-200 dark:border-gray-700 rounded-lg shadow-lg my-6 overflow-hidden">
849
+ <div class="bg-gradient-to-br from-blue-50 via-blue-25 to-purple-50 dark:from-blue-900/20 dark:via-blue-800/10 dark:to-purple-900/20 border-b border-gray-200 dark:border-gray-700 p-6">
850
+ <div class="flex items-center gap-4">
851
+ <div class="p-3 bg-blue-100 dark:bg-blue-800 rounded-2xl">
852
+ <svg class="w-8 h-8 text-blue-600 dark:text-blue-300" fill="none" stroke="currentColor" viewBox="0 0 24 24">
853
+ <path strokeLinecap="round" strokeLinejoin="round" strokeWidth="2" d="M8 16H6a2 2 0 01-2-2V6a2 2 0 012-2h8a2 2 0 012 2v2m-6 12h8a2 2 0 002-2v-8a2 2 0 00-2-2h-8a2 2 0 00-2 2v8a2 2 0 002 2z"></path>
854
+ </svg>
855
+ </div>
856
+ <div>
857
+ <h2 class="text-2xl font-bold text-gray-900 dark:text-gray-100">${title}</h2>
858
+ <p class="text-sm text-gray-600 dark:text-gray-400 flex items-center gap-2 mt-1">
859
+ <svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
860
+ <path strokeLinecap="round" strokeLinejoin="round" strokeWidth="2" d="M12 8v4l3 3m6-3a9 9 0 11-18 0 9 9 0 0118 0z"></path>
861
+ </svg>
862
+ Interactive Story \u2022 ${nodes.length} Chapters
863
+ </p>
864
+ </div>
865
+ </div>
866
+ </div>
867
+
868
+ <div class="p-8" id="story-container">
869
+ ${allNodesHTML}
870
+ </div>
871
+ </div>
872
+ `;
873
+ }
874
+ function convertDynamicBlockNodeToHTML(node) {
875
+ const payload = node.getPayload();
876
+ const { title, blocks, currentBlockId } = payload;
877
+ const currentBlock = blocks.find((block) => block.id === currentBlockId) || blocks[0];
878
+ const renderContentBlock = (block) => {
879
+ switch (block.type) {
880
+ case "text":
881
+ return `<div class="prose prose-sm max-w-none" ${block.styles ? `style="${Object.entries(block.styles).map(([k, v]) => `${k}: ${v}`).join("; ")}"` : ""}>${block.content}</div>`;
882
+ case "image":
883
+ return `<img src="${block.content || "/placeholder.svg"}" alt="Dynamic content" class="max-w-full h-auto rounded-lg" ${block.styles ? `style="${Object.entries(block.styles).map(([k, v]) => `${k}: ${v}`).join("; ")}"` : ""} />`;
884
+ case "video":
885
+ return `<video src="${block.content}" controls class="max-w-full h-auto rounded-lg" ${block.styles ? `style="${Object.entries(block.styles).map(([k, v]) => `${k}: ${v}`).join("; ")}"` : ""}></video>`;
886
+ case "html":
887
+ return `<div class="w-full" ${block.styles ? `style="${Object.entries(block.styles).map(([k, v]) => `${k}: ${v}`).join("; ")}"` : ""}>${block.content}</div>`;
888
+ default:
889
+ return '<div class="text-gray-500">Unknown content type</div>';
890
+ }
891
+ };
892
+ const blocksHTML = blocks.map(
893
+ (block, index) => `
894
+ <button
895
+ class="block-selector ${(currentBlock == null ? void 0 : currentBlock.id) === block.id ? "bg-blue-100 border-blue-500" : "bg-gray-50 border-gray-200"} border-2 rounded-lg p-3 text-left transition-all hover:border-blue-400 mb-2"
896
+ onclick="window.showDynamicBlock('${payload.id}', '${block.id}')"
897
+ >
898
+ <div class="font-medium text-xs capitalize">${block.type}</div>
899
+ <div class="text-xs text-gray-500 truncate">
900
+ ${block.content.substring(0, 30)}...
901
+ </div>
902
+ </button>
903
+ `
904
+ ).join("");
905
+ return `
906
+ <div class="dynamic-block-container bg-white dark:bg-gray-800 border-2 border-dashed border-blue-300 dark:border-blue-600 bg-gradient-to-br from-white to-blue-50 dark:from-gray-800 dark:to-blue-900/20 rounded-lg my-6">
907
+ <div class="p-4 border-b border-gray-200 dark:border-gray-700">
908
+ <div class="flex items-center gap-2">
909
+ <svg class="w-5 h-5 text-blue-600" fill="none" stroke="currentColor" viewBox="0 0 24 24">
910
+ <path strokeLinecap="round" strokeLinejoin="round" strokeWidth="2" d="M13 10V3L4 14h7v7l9-11h-7z"></path>
911
+ </svg>
912
+ <h3 class="text-lg font-semibold text-gray-900 dark:text-gray-100">${title}</h3>
913
+ <span class="inline-flex items-center px-2.5 py-0.5 rounded-full text-xs font-medium bg-gray-100 text-gray-800 dark:bg-gray-700 dark:text-gray-200">
914
+ Dynamic Block
915
+ </span>
916
+ </div>
917
+ </div>
918
+
919
+ <div class="p-4 space-y-4">
920
+ Content Display Area
921
+ <div class="min-h-[200px] p-4 rounded-lg border bg-gray-50 dark:bg-gray-700 relative overflow-hidden" id="dynamic-content-${payload.id}">
922
+ ${currentBlock ? renderContentBlock(currentBlock) : `
923
+ <div class="flex items-center justify-center h-full text-gray-500 dark:text-gray-400">
924
+ <div class="text-center">
925
+ <svg class="w-12 h-12 mx-auto mb-2 opacity-50" fill="none" stroke="currentColor" viewBox="0 0 24 24">
926
+ <path strokeLinecap="round" strokeLinejoin="round" strokeWidth="2" d="M13 10V3L4 14h7v7l9-11h-7z"></path>
927
+ </svg>
928
+ <p>No content block selected</p>
929
+ </div>
930
+ </div>
931
+ `}
932
+ </div>
933
+
934
+ Block Selection
935
+ <div class="space-y-3">
936
+ <h4 class="font-medium text-sm text-gray-900 dark:text-gray-100">Content Blocks (${blocks.length})</h4>
937
+ <div class="grid grid-cols-2 md:grid-cols-3 gap-2">
938
+ ${blocksHTML}
939
+ </div>
940
+ </div>
941
+ </div>
942
+ </div>
943
+ `;
944
+ }
945
+
946
+ // src/components/editor/plugins/ToolbarPlugin/index.tsx
947
+ var BlockFormatDropDown = dynamic(
948
+ () => import("./block-format-YJCV2DIY.mjs")
949
+ );
950
+ var MobileToolbar = dynamic(() => import("./MobileToolbar-BOOZAMQE.mjs"), { ssr: false });
951
+ var FontDropDown = dynamic(
952
+ () => import("./font-FEZ3GKSF.mjs")
953
+ );
954
+ var FontSize = dynamic(
955
+ () => import("./font-size-EK775WRH.mjs")
956
+ );
957
+ var Color = dynamic(() => import("./color-BPKOPQKN.mjs"));
958
+ var BackgroundColor = dynamic(() => import("./background-color-XZTYLGO2.mjs"));
959
+ var TextFormat = dynamic(
960
+ () => import("./text-format-BG5WOOPZ.mjs")
961
+ );
962
+ var InsertNode = dynamic(
963
+ () => import("./insert-node-5P2CRJ7S.mjs")
964
+ );
965
+ var TextAlign = dynamic(
966
+ () => import("./text-align-VLECWO4H.mjs")
967
+ );
968
+ function ToolbarPlugin({
969
+ editor,
970
+ activeEditor,
971
+ setActiveEditor,
972
+ setIsLinkEditMode,
973
+ toolbarConfig,
974
+ className
975
+ }) {
976
+ const [isEditable, setIsEditable] = useState2(() => editor.isEditable());
977
+ const [isSpeechToText, setIsSpeechToText] = useState2(false);
978
+ const [selectedElementKey, setSelectedElementKey] = useState2(
979
+ null
980
+ );
981
+ const [isFocused, setIsFocused] = useState2(false);
982
+ const { toolbarState, updateToolbarState } = useToolbarState();
983
+ const $updateToolbar = useCallback(() => {
984
+ const currentEditor = activeEditor || editor;
985
+ if (!currentEditor) return;
986
+ currentEditor.read(() => {
987
+ var _a;
988
+ const selection = $getSelection();
989
+ if ($isRangeSelection(selection)) {
990
+ if (activeEditor !== editor && $isEditorIsNestedEditor(activeEditor)) {
991
+ const rootElement = activeEditor.getRootElement();
992
+ updateToolbarState(
993
+ "isImageCaption",
994
+ !!((_a = rootElement == null ? void 0 : rootElement.parentElement) == null ? void 0 : _a.classList.contains(
995
+ "image-caption-container"
996
+ ))
997
+ );
998
+ } else {
999
+ updateToolbarState("isImageCaption", false);
1000
+ }
1001
+ const anchorNode = selection.anchor.getNode();
1002
+ let element = anchorNode.getKey() === "root" ? anchorNode : $findMatchingParent(anchorNode, (e) => {
1003
+ const parent2 = e.getParent();
1004
+ return parent2 !== null && $isRootOrShadowRoot(parent2);
1005
+ });
1006
+ if (element === null) {
1007
+ element = anchorNode.getTopLevelElementOrThrow();
1008
+ }
1009
+ const elementKey = element.getKey();
1010
+ const elementDOM = currentEditor.getElementByKey(elementKey);
1011
+ const node = getSelectedNode(selection);
1012
+ const parent = node.getParent();
1013
+ const isLink = $isLinkNode(parent) || $isLineBreakNode(node);
1014
+ updateToolbarState("isLink", isLink);
1015
+ const tableNode = $findMatchingParent(node, $isTableNode);
1016
+ if ($isTableNode(tableNode)) {
1017
+ updateToolbarState("rootType", "table");
1018
+ } else {
1019
+ updateToolbarState("rootType", "root");
1020
+ }
1021
+ if (elementDOM !== null) {
1022
+ setSelectedElementKey(elementKey);
1023
+ if ($isListNode(element)) {
1024
+ const parentList = $getNearestNodeOfType(anchorNode, ListNode);
1025
+ const type = parentList ? parentList.getListType() : element.getListType();
1026
+ updateToolbarState("blockType", type);
1027
+ } else {
1028
+ const type = $isHeadingNode(element) ? element.getTag() : element.getType();
1029
+ if (type in blockTypeToBlockName) {
1030
+ updateToolbarState(
1031
+ "blockType",
1032
+ type
1033
+ );
1034
+ }
1035
+ if ($isCodeNode(element)) {
1036
+ const language = element.getLanguage();
1037
+ updateToolbarState(
1038
+ "codeLanguage",
1039
+ language ? CODE_LANGUAGE_MAP[language] || language : ""
1040
+ );
1041
+ return;
1042
+ }
1043
+ }
1044
+ }
1045
+ updateToolbarState(
1046
+ "fontColor",
1047
+ $getSelectionStyleValueForProperty(selection, "color", "#000")
1048
+ );
1049
+ updateToolbarState(
1050
+ "bgColor",
1051
+ $getSelectionStyleValueForProperty(
1052
+ selection,
1053
+ "background-color",
1054
+ "#fff"
1055
+ )
1056
+ );
1057
+ updateToolbarState(
1058
+ "fontFamily",
1059
+ $getSelectionStyleValueForProperty(selection, "font-family", "Arial")
1060
+ );
1061
+ let matchingParent;
1062
+ if ($isLinkNode(parent)) {
1063
+ matchingParent = $findMatchingParent(
1064
+ node,
1065
+ (parentNode) => $isElementNode(parentNode) && !parentNode.isInline()
1066
+ );
1067
+ }
1068
+ updateToolbarState(
1069
+ "elementFormat",
1070
+ $isElementNode(matchingParent) ? matchingParent.getFormatType() : $isElementNode(node) ? node.getFormatType() : (parent == null ? void 0 : parent.getFormatType()) || "left"
1071
+ );
1072
+ }
1073
+ if ($isRangeSelection(selection) || $isTableSelection(selection)) {
1074
+ updateToolbarState("isBold", selection.hasFormat("bold"));
1075
+ updateToolbarState("isItalic", selection.hasFormat("italic"));
1076
+ updateToolbarState("isUnderline", selection.hasFormat("underline"));
1077
+ updateToolbarState("isStrikethrough", selection.hasFormat("strikethrough"));
1078
+ updateToolbarState("isSubscript", selection.hasFormat("subscript"));
1079
+ updateToolbarState("isSuperscript", selection.hasFormat("superscript"));
1080
+ updateToolbarState("isCode", selection.hasFormat("code"));
1081
+ updateToolbarState(
1082
+ "fontSize",
1083
+ $getSelectionStyleValueForProperty(selection, "font-size", "15px")
1084
+ );
1085
+ updateToolbarState("isLowercase", selection.hasFormat("lowercase"));
1086
+ updateToolbarState("isUppercase", selection.hasFormat("uppercase"));
1087
+ updateToolbarState("isCapitalize", selection.hasFormat("capitalize"));
1088
+ }
1089
+ });
1090
+ }, [activeEditor, editor, updateToolbarState]);
1091
+ useEffect(() => {
1092
+ return editor.registerCommand(
1093
+ SELECTION_CHANGE_COMMAND,
1094
+ (_payload, newEditor) => {
1095
+ setActiveEditor(newEditor);
1096
+ $updateToolbar();
1097
+ return false;
1098
+ },
1099
+ COMMAND_PRIORITY_CRITICAL
1100
+ );
1101
+ }, [editor, $updateToolbar, setActiveEditor]);
1102
+ useEffect(() => {
1103
+ activeEditor.getEditorState().read(() => {
1104
+ $updateToolbar();
1105
+ });
1106
+ }, [activeEditor, $updateToolbar]);
1107
+ useEffect(() => {
1108
+ return mergeRegister(
1109
+ editor.registerCommand(
1110
+ FOCUS_COMMAND,
1111
+ () => {
1112
+ setIsFocused(true);
1113
+ return false;
1114
+ },
1115
+ COMMAND_PRIORITY_CRITICAL
1116
+ ),
1117
+ editor.registerCommand(
1118
+ BLUR_COMMAND,
1119
+ () => {
1120
+ setIsFocused(false);
1121
+ return false;
1122
+ },
1123
+ COMMAND_PRIORITY_CRITICAL
1124
+ ),
1125
+ editor.registerEditableListener((editable) => {
1126
+ setIsEditable(editable);
1127
+ }),
1128
+ activeEditor.registerUpdateListener(({ editorState }) => {
1129
+ editorState.read(() => {
1130
+ $updateToolbar();
1131
+ });
1132
+ }),
1133
+ activeEditor.registerCommand(
1134
+ CAN_UNDO_COMMAND,
1135
+ (payload) => {
1136
+ updateToolbarState("canUndo", payload);
1137
+ return false;
1138
+ },
1139
+ COMMAND_PRIORITY_CRITICAL
1140
+ ),
1141
+ activeEditor.registerCommand(
1142
+ CAN_REDO_COMMAND,
1143
+ (payload) => {
1144
+ updateToolbarState("canRedo", payload);
1145
+ return false;
1146
+ },
1147
+ COMMAND_PRIORITY_CRITICAL
1148
+ )
1149
+ );
1150
+ }, [$updateToolbar, activeEditor, editor, updateToolbarState]);
1151
+ const insertLink = useCallback(() => {
1152
+ if (!toolbarState.isLink) {
1153
+ setIsLinkEditMode(true);
1154
+ activeEditor.dispatchCommand(
1155
+ TOGGLE_LINK_COMMAND,
1156
+ sanitizeUrl("https://")
1157
+ );
1158
+ } else {
1159
+ setIsLinkEditMode(false);
1160
+ activeEditor.dispatchCommand(TOGGLE_LINK_COMMAND, null);
1161
+ }
1162
+ }, [activeEditor, setIsLinkEditMode, toolbarState.isLink]);
1163
+ const onCodeLanguageSelect = useCallback(
1164
+ (value) => {
1165
+ activeEditor.update(() => {
1166
+ if (selectedElementKey !== null) {
1167
+ const node = $getNodeByKey(selectedElementKey);
1168
+ if ($isCodeNode(node)) {
1169
+ node.setLanguage(value);
1170
+ }
1171
+ }
1172
+ });
1173
+ },
1174
+ [activeEditor, selectedElementKey]
1175
+ );
1176
+ const handleDownloadHTML = useCallback(() => {
1177
+ try {
1178
+ const htmlContent = exportEditorToHTML(activeEditor);
1179
+ const timestamp = (/* @__PURE__ */ new Date()).toISOString().slice(0, 19).replace(/:/g, "-");
1180
+ downloadHTML(htmlContent, `document-${timestamp}.html`);
1181
+ } catch (error) {
1182
+ console.error("Failed to export HTML:", error);
1183
+ }
1184
+ }, [activeEditor]);
1185
+ const DEFAULT_TOOLBAR_ITEMS = [
1186
+ "undo",
1187
+ "redo",
1188
+ "separator",
1189
+ "block-format",
1190
+ "separator",
1191
+ "font-family",
1192
+ "separator",
1193
+ "font-size",
1194
+ "separator",
1195
+ "bold",
1196
+ "italic",
1197
+ "underline",
1198
+ "code",
1199
+ "link",
1200
+ "separator",
1201
+ "color",
1202
+ "bg-color",
1203
+ "separator",
1204
+ "text-format",
1205
+ "separator",
1206
+ "insert",
1207
+ "separator",
1208
+ "align",
1209
+ "separator",
1210
+ "speech",
1211
+ "template",
1212
+ "download",
1213
+ "separator",
1214
+ "export-md",
1215
+ "export-pdf"
1216
+ ];
1217
+ const itemsToRender = (toolbarConfig == null ? void 0 : toolbarConfig.items) || DEFAULT_TOOLBAR_ITEMS;
1218
+ const customClassName = (toolbarConfig == null ? void 0 : toolbarConfig.className) || className;
1219
+ const itemClassName = toolbarConfig == null ? void 0 : toolbarConfig.itemClassName;
1220
+ const activeItemClassName = toolbarConfig == null ? void 0 : toolbarConfig.activeItemClassName;
1221
+ const renderItem = (item, index) => {
1222
+ switch (item) {
1223
+ case "undo":
1224
+ return /* @__PURE__ */ React2.createElement(
1225
+ Button,
1226
+ {
1227
+ key: `undo-${index}`,
1228
+ size: "Toolbar",
1229
+ variant: "outline",
1230
+ disabled: !toolbarState.canUndo || !isEditable,
1231
+ onClick: () => {
1232
+ activeEditor.dispatchCommand(UNDO_COMMAND, void 0);
1233
+ },
1234
+ tip: false ? "Undo (\u2318Z)" : "Undo (Ctrl+Z)",
1235
+ type: "button",
1236
+ "aria-label": "Undo",
1237
+ className: cn("border-none", itemClassName)
1238
+ },
1239
+ /* @__PURE__ */ React2.createElement(Undo2Icon, { className: " size-4" })
1240
+ );
1241
+ case "redo":
1242
+ return /* @__PURE__ */ React2.createElement(
1243
+ Button,
1244
+ {
1245
+ key: `redo-${index}`,
1246
+ variant: "outline",
1247
+ size: "Toolbar",
1248
+ disabled: !toolbarState.canRedo || !isEditable,
1249
+ onClick: () => {
1250
+ activeEditor.dispatchCommand(REDO_COMMAND, void 0);
1251
+ },
1252
+ tip: false ? "Redo (\u21E7\u2318Z)" : "Redo (Ctrl+Y)",
1253
+ type: "button",
1254
+ className: cn("toolbar-item border-none", itemClassName),
1255
+ "aria-label": "Redo"
1256
+ },
1257
+ /* @__PURE__ */ React2.createElement(Redo2Icon, { className: " size-4" })
1258
+ );
1259
+ case "separator":
1260
+ return /* @__PURE__ */ React2.createElement(Separator, { key: `sep-${index}`, className: "h-6 mx-2", orientation: "vertical" });
1261
+ case "block-format":
1262
+ return toolbarState.blockType in blockTypeToBlockName && activeEditor === editor ? /* @__PURE__ */ React2.createElement("div", { key: `block-${index}`, className: "flex flex-row gap-x-[5px] items-center" }, /* @__PURE__ */ React2.createElement(
1263
+ BlockFormatDropDown,
1264
+ {
1265
+ disabled: !isEditable,
1266
+ blockType: toolbarState.blockType,
1267
+ editor: activeEditor
1268
+ }
1269
+ )) : null;
1270
+ case "font-family":
1271
+ return /* @__PURE__ */ React2.createElement(
1272
+ FontDropDown,
1273
+ {
1274
+ key: `font-${index}`,
1275
+ disabled: !isEditable,
1276
+ style: { fontFamily: toolbarState.fontFamily },
1277
+ value: toolbarState.fontFamily,
1278
+ editor: activeEditor
1279
+ }
1280
+ );
1281
+ case "font-size":
1282
+ return /* @__PURE__ */ React2.createElement(
1283
+ FontSize,
1284
+ {
1285
+ key: `size-${index}`,
1286
+ selectionFontSize: toolbarState.fontSize.slice(0, -2),
1287
+ editor: activeEditor,
1288
+ disabled: !isEditable
1289
+ }
1290
+ );
1291
+ case "bold":
1292
+ return /* @__PURE__ */ React2.createElement(
1293
+ Toggle,
1294
+ {
1295
+ key: `bold-${index}`,
1296
+ disabled: !isEditable,
1297
+ variant: "outline",
1298
+ size: "Toolbar",
1299
+ pressed: toolbarState.isBold,
1300
+ onPressedChange: () => {
1301
+ activeEditor.dispatchCommand(FORMAT_TEXT_COMMAND, "bold");
1302
+ },
1303
+ tip: `Bold ${SHORTCUTS.BOLD}`,
1304
+ "aria-label": `Format text as bold. Shortcut: ${SHORTCUTS.BOLD}`,
1305
+ className: cn(itemClassName, toolbarState.isBold && activeItemClassName)
1306
+ },
1307
+ /* @__PURE__ */ React2.createElement(Bold, { size: 16 })
1308
+ );
1309
+ case "italic":
1310
+ return /* @__PURE__ */ React2.createElement(
1311
+ Toggle,
1312
+ {
1313
+ key: `italic-${index}`,
1314
+ variant: "outline",
1315
+ size: "Toolbar",
1316
+ disabled: !isEditable,
1317
+ pressed: toolbarState.isItalic,
1318
+ onPressedChange: () => {
1319
+ activeEditor.dispatchCommand(FORMAT_TEXT_COMMAND, "italic");
1320
+ },
1321
+ tip: `Italic (${SHORTCUTS.ITALIC})`,
1322
+ type: "button",
1323
+ "aria-label": `Format text as italics. Shortcut: ${SHORTCUTS.ITALIC}`,
1324
+ className: cn(itemClassName, toolbarState.isItalic && activeItemClassName)
1325
+ },
1326
+ /* @__PURE__ */ React2.createElement(Italic, { size: 16 })
1327
+ );
1328
+ case "underline":
1329
+ return /* @__PURE__ */ React2.createElement(
1330
+ Toggle,
1331
+ {
1332
+ key: `underline-${index}`,
1333
+ disabled: !isEditable,
1334
+ variant: "outline",
1335
+ size: "Toolbar",
1336
+ pressed: toolbarState.isUnderline,
1337
+ onPressedChange: () => {
1338
+ activeEditor.dispatchCommand(FORMAT_TEXT_COMMAND, "underline");
1339
+ },
1340
+ tip: `Underline (${SHORTCUTS.UNDERLINE})`,
1341
+ type: "button",
1342
+ "aria-label": `Format text to underlined. Shortcut: ${SHORTCUTS.UNDERLINE}`,
1343
+ className: cn(itemClassName, toolbarState.isUnderline && activeItemClassName)
1344
+ },
1345
+ /* @__PURE__ */ React2.createElement(Underline, { size: 16 })
1346
+ );
1347
+ case "code":
1348
+ return /* @__PURE__ */ React2.createElement(
1349
+ Toggle,
1350
+ {
1351
+ key: `code-${index}`,
1352
+ disabled: !isEditable,
1353
+ variant: "outline",
1354
+ size: "Toolbar",
1355
+ pressed: toolbarState.isCode,
1356
+ onPressedChange: () => {
1357
+ activeEditor.dispatchCommand(FORMAT_TEXT_COMMAND, "code");
1358
+ },
1359
+ tip: `Insert code block (${SHORTCUTS.INSERT_CODE_BLOCK})`,
1360
+ type: "button",
1361
+ "aria-label": "Insert code block",
1362
+ className: cn(itemClassName, toolbarState.isCode && activeItemClassName)
1363
+ },
1364
+ /* @__PURE__ */ React2.createElement(Code, { size: 16 })
1365
+ );
1366
+ case "link":
1367
+ return /* @__PURE__ */ React2.createElement(
1368
+ Toggle,
1369
+ {
1370
+ key: `link-${index}`,
1371
+ variant: "outline",
1372
+ size: "Toolbar",
1373
+ disabled: !isEditable,
1374
+ onPressedChange: insertLink,
1375
+ pressed: toolbarState.isLink,
1376
+ "aria-label": "Insert link",
1377
+ tip: `Insert link (${SHORTCUTS.INSERT_LINK})`,
1378
+ type: "button",
1379
+ className: cn(itemClassName, toolbarState.isLink && activeItemClassName)
1380
+ },
1381
+ /* @__PURE__ */ React2.createElement(Link, { size: 16 })
1382
+ );
1383
+ case "color":
1384
+ return /* @__PURE__ */ React2.createElement(
1385
+ Color,
1386
+ {
1387
+ key: `color-${index}`,
1388
+ disabled: !isEditable,
1389
+ color: toolbarState.fontColor,
1390
+ bgColor: toolbarState.bgColor,
1391
+ editor
1392
+ }
1393
+ );
1394
+ case "bg-color":
1395
+ return /* @__PURE__ */ React2.createElement(
1396
+ BackgroundColor,
1397
+ {
1398
+ key: `bg-${index}`,
1399
+ disabled: !isEditable,
1400
+ color: toolbarState.fontColor,
1401
+ bgColor: toolbarState.bgColor,
1402
+ editor
1403
+ }
1404
+ );
1405
+ case "text-format":
1406
+ return /* @__PURE__ */ React2.createElement(
1407
+ TextFormat,
1408
+ {
1409
+ key: `format-${index}`,
1410
+ disabled: !isEditable,
1411
+ editor,
1412
+ toolbarState
1413
+ }
1414
+ );
1415
+ case "insert":
1416
+ return /* @__PURE__ */ React2.createElement(InsertNode, { key: `insert-${index}`, disabled: !isEditable, editor });
1417
+ case "align":
1418
+ return /* @__PURE__ */ React2.createElement(
1419
+ TextAlign,
1420
+ {
1421
+ key: `align-${index}`,
1422
+ disabled: !isEditable,
1423
+ value: toolbarState.elementFormat,
1424
+ editor: activeEditor,
1425
+ isRTL: toolbarState.isRTL
1426
+ }
1427
+ );
1428
+ case "speech":
1429
+ return SUPPORT_SPEECH_RECOGNITION ? /* @__PURE__ */ React2.createElement(
1430
+ Button,
1431
+ {
1432
+ key: `speech-${index}`,
1433
+ variant: "outline",
1434
+ size: "Toolbar",
1435
+ type: "button",
1436
+ onClick: () => {
1437
+ editor.dispatchCommand(SPEECH_TO_TEXT_COMMAND, !isSpeechToText);
1438
+ setIsSpeechToText(!isSpeechToText);
1439
+ },
1440
+ className: cn(
1441
+ "relative inline-flex items-center justify-center p-3 rounded-lg border-none font-medium transition-all duration-300 ease-in-out active:scale-95",
1442
+ isSpeechToText ? "animate-pulse bg-gray-800" : "bg-transparent hover:bg-gray-900 cursor-pointer shadow-sm hover:shadow-md",
1443
+ itemClassName
1444
+ ),
1445
+ title: "Speech To Text",
1446
+ "aria-label": `${isSpeechToText ? "Disable" : "Enable"} speech to text`
1447
+ },
1448
+ /* @__PURE__ */ React2.createElement(Mic, { className: cn("w-4 h-4 transition-all duration-300", isSpeechToText && "animate-bounce") })
1449
+ ) : null;
1450
+ case "template":
1451
+ return /* @__PURE__ */ React2.createElement(TemplateDialog, { key: `template-${index}` });
1452
+ case "download":
1453
+ return /* @__PURE__ */ React2.createElement(
1454
+ Button,
1455
+ {
1456
+ key: `download-${index}`,
1457
+ variant: "outline",
1458
+ size: "Toolbar",
1459
+ type: "button",
1460
+ onClick: handleDownloadHTML,
1461
+ tip: "Download as HTML",
1462
+ "aria-label": "Download document as HTML file",
1463
+ className: cn("border-none", itemClassName)
1464
+ },
1465
+ /* @__PURE__ */ React2.createElement(DownloadIcon, { className: "size-4" })
1466
+ );
1467
+ case "export-md":
1468
+ return /* @__PURE__ */ React2.createElement(
1469
+ Button,
1470
+ {
1471
+ key: `md-${index}`,
1472
+ variant: "outline",
1473
+ size: "Toolbar",
1474
+ type: "button",
1475
+ onClick: () => {
1476
+ editor.dispatchCommand(EXPORT_MARKDOWN_COMMAND, void 0);
1477
+ },
1478
+ tip: "Export to Markdown",
1479
+ "aria-label": "Export document to Markdown",
1480
+ className: cn("border-none", itemClassName)
1481
+ },
1482
+ /* @__PURE__ */ React2.createElement(FileJson, { className: "size-4" })
1483
+ );
1484
+ case "export-pdf":
1485
+ return /* @__PURE__ */ React2.createElement(
1486
+ Button,
1487
+ {
1488
+ key: `pdf-${index}`,
1489
+ variant: "outline",
1490
+ size: "Toolbar",
1491
+ type: "button",
1492
+ onClick: () => {
1493
+ editor.dispatchCommand(EXPORT_PDF_COMMAND, void 0);
1494
+ },
1495
+ tip: "Export to PDF",
1496
+ "aria-label": "Export document to PDF",
1497
+ className: cn("border-none", itemClassName)
1498
+ },
1499
+ /* @__PURE__ */ React2.createElement(FileText, { className: "size-4" })
1500
+ );
1501
+ default:
1502
+ return null;
1503
+ }
1504
+ };
1505
+ return /* @__PURE__ */ React2.createElement(React2.Fragment, null, /* @__PURE__ */ React2.createElement(
1506
+ "nav",
1507
+ {
1508
+ className: cn(
1509
+ "z-40 left-0 w-full hidden md:block"
1510
+ // Hide on mobile, show on desktop
1511
+ )
1512
+ },
1513
+ /* @__PURE__ */ React2.createElement("div", { className: "flex justify-center pt-4" }, /* @__PURE__ */ React2.createElement(
1514
+ "div",
1515
+ {
1516
+ className: cn(
1517
+ "group flex flex-row items-center bg-background/70 gap-x-2 dark:border dark:border-gray-500/20",
1518
+ "md:rounded-2xl rounded-md h-14 px-4 py-2 shadow-md",
1519
+ "overflow-x-auto whitespace-nowrap max-w-[90%] scrollbar-none",
1520
+ "[&::-webkit-scrollbar]:hidden [-ms-overflow-style:none] [scrollbar-width:none]",
1521
+ customClassName
1522
+ )
1523
+ },
1524
+ toolbarState.blockType === "code" ? /* @__PURE__ */ React2.createElement(
1525
+ CodeList,
1526
+ {
1527
+ onCodeLanguageSelect,
1528
+ codeLanguage: toolbarState.codeLanguage,
1529
+ disabled: !isEditable
1530
+ }
1531
+ ) : itemsToRender.map((item, index) => renderItem(item, index))
1532
+ ))
1533
+ ), /* @__PURE__ */ React2.createElement(
1534
+ MobileToolbar,
1535
+ {
1536
+ editor,
1537
+ activeEditor,
1538
+ toolbarState,
1539
+ setIsLinkEditMode,
1540
+ isVisible: isFocused,
1541
+ toolbarConfig
1542
+ }
1543
+ ));
1544
+ }
1545
+ export {
1546
+ ToolbarPlugin as default
1547
+ };