@cyberyozh/text-editor 0.1.1

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 (209) hide show
  1. package/README.md +102 -0
  2. package/dist/editor.css +2069 -0
  3. package/dist/editor.css.map +1 -0
  4. package/dist/editor.d.mts +45 -0
  5. package/dist/editor.d.ts +45 -0
  6. package/dist/editor.js +6155 -0
  7. package/dist/editor.js.map +1 -0
  8. package/dist/editor.mjs +6118 -0
  9. package/dist/editor.mjs.map +1 -0
  10. package/dist/render/client.d.mts +24 -0
  11. package/dist/render/client.d.ts +24 -0
  12. package/dist/render/client.js +98 -0
  13. package/dist/render/client.js.map +1 -0
  14. package/dist/render/client.mjs +74 -0
  15. package/dist/render/client.mjs.map +1 -0
  16. package/dist/render.d.mts +58 -0
  17. package/dist/render.d.ts +58 -0
  18. package/dist/render.js +2521 -0
  19. package/dist/render.js.map +1 -0
  20. package/dist/render.mjs +2484 -0
  21. package/dist/render.mjs.map +1 -0
  22. package/dist/styles/index.css +2068 -0
  23. package/package.json +92 -0
  24. package/src/editor/commands/items.ts +374 -0
  25. package/src/editor/commands/suggestion.tsx +146 -0
  26. package/src/editor/components/button/button.css +56 -0
  27. package/src/editor/components/button/button.tsx +35 -0
  28. package/src/editor/components/button/index.ts +1 -0
  29. package/src/editor/components/common-modal/common-modal.css +85 -0
  30. package/src/editor/components/common-modal/common-modal.tsx +58 -0
  31. package/src/editor/components/common-modal/index.ts +1 -0
  32. package/src/editor/components/index.ts +3 -0
  33. package/src/editor/components/input/index.ts +1 -0
  34. package/src/editor/components/input/input.css +43 -0
  35. package/src/editor/components/input/input.tsx +22 -0
  36. package/src/editor/context/dialog-command.tsx +47 -0
  37. package/src/editor/context/index.ts +2 -0
  38. package/src/editor/context/translations-context.tsx +28 -0
  39. package/src/editor/controls/bubble-menu-content.tsx +394 -0
  40. package/src/editor/controls/callout-menu.tsx +169 -0
  41. package/src/editor/controls/character-count.tsx +36 -0
  42. package/src/editor/controls/commands-list.tsx +117 -0
  43. package/src/editor/controls/drag-handle.tsx +98 -0
  44. package/src/editor/controls/emoji-picker.tsx +62 -0
  45. package/src/editor/controls/index.ts +5 -0
  46. package/src/editor/controls/table-menu.tsx +322 -0
  47. package/src/editor/dialogs/add-katex-dialog/add-katex-dialog.css +115 -0
  48. package/src/editor/dialogs/add-katex-dialog/add-katex-dialog.tsx +116 -0
  49. package/src/editor/dialogs/add-katex-dialog/index.ts +1 -0
  50. package/src/editor/dialogs/add-link-dialog/add-link-dialog.css +105 -0
  51. package/src/editor/dialogs/add-link-dialog/add-link-dialog.tsx +177 -0
  52. package/src/editor/dialogs/add-link-dialog/index.ts +1 -0
  53. package/src/editor/dialogs/add-video-dialog/add-video-dialog.css +146 -0
  54. package/src/editor/dialogs/add-video-dialog/add-video-dialog.tsx +157 -0
  55. package/src/editor/dialogs/add-video-dialog/index.ts +1 -0
  56. package/src/editor/dialogs/image-dialog/image-dialog.css +101 -0
  57. package/src/editor/dialogs/image-dialog/image-dialog.tsx +276 -0
  58. package/src/editor/dialogs/image-dialog/index.ts +1 -0
  59. package/src/editor/dialogs/index.ts +4 -0
  60. package/src/editor/editor.tsx +247 -0
  61. package/src/editor/handlers/create-image-upload-handler.ts +24 -0
  62. package/src/editor/handlers/dialog-handlers.ts +143 -0
  63. package/src/editor/handlers/index.ts +8 -0
  64. package/src/editor/index.ts +3 -0
  65. package/src/extensions/base/callout.ts +138 -0
  66. package/src/extensions/base/code-block.ts +24 -0
  67. package/src/extensions/base/compatibility.ts +493 -0
  68. package/src/extensions/base/copyable-text.ts +56 -0
  69. package/src/extensions/base/custom-quote.ts +174 -0
  70. package/src/extensions/base/figure.ts +141 -0
  71. package/src/extensions/base/index.ts +19 -0
  72. package/src/extensions/base/link.ts +18 -0
  73. package/src/extensions/base/myth-reality.ts +45 -0
  74. package/src/extensions/base/prompt.ts +109 -0
  75. package/src/extensions/base/video.ts +29 -0
  76. package/src/extensions/editor/callout.ts +43 -0
  77. package/src/extensions/editor/code-block.ts +9 -0
  78. package/src/extensions/editor/commands.ts +43 -0
  79. package/src/extensions/editor/copyable-text.ts +16 -0
  80. package/src/extensions/editor/custom-quote.ts +54 -0
  81. package/src/extensions/editor/figure.ts +20 -0
  82. package/src/extensions/editor/get-editor-extensions.ts +113 -0
  83. package/src/extensions/editor/index.ts +25 -0
  84. package/src/extensions/editor/prompt.ts +43 -0
  85. package/src/extensions/editor/video.ts +23 -0
  86. package/src/extensions/render/get-render-extensions.ts +74 -0
  87. package/src/extensions/render/index.ts +6 -0
  88. package/src/extensions/views/components/callout.tsx +70 -0
  89. package/src/extensions/views/components/code-block.tsx +73 -0
  90. package/src/extensions/views/components/copy-button.tsx +52 -0
  91. package/src/extensions/views/components/copyable-text.tsx +11 -0
  92. package/src/extensions/views/components/custom-quote.tsx +64 -0
  93. package/src/extensions/views/components/figure.tsx +63 -0
  94. package/src/extensions/views/components/index.ts +7 -0
  95. package/src/extensions/views/components/prompt.tsx +43 -0
  96. package/src/extensions/views/components/video.tsx +40 -0
  97. package/src/extensions/views/node-views/callout.tsx +51 -0
  98. package/src/extensions/views/node-views/code-block.tsx +30 -0
  99. package/src/extensions/views/node-views/copyable-text.tsx +10 -0
  100. package/src/extensions/views/node-views/custom-quote.tsx +66 -0
  101. package/src/extensions/views/node-views/figure.tsx +38 -0
  102. package/src/extensions/views/node-views/index.ts +7 -0
  103. package/src/extensions/views/node-views/prompt.tsx +35 -0
  104. package/src/extensions/views/node-views/video.tsx +19 -0
  105. package/src/icons/Check.tsx +12 -0
  106. package/src/icons/Copy.tsx +15 -0
  107. package/src/icons/DragIcon.tsx +10 -0
  108. package/src/icons/Edit.tsx +12 -0
  109. package/src/icons/Quote.tsx +10 -0
  110. package/src/icons/X.tsx +13 -0
  111. package/src/icons/color/TiptapCalloutError.tsx +25 -0
  112. package/src/icons/color/TiptapCalloutInfo.tsx +18 -0
  113. package/src/icons/color/TiptapCalloutSuccess.tsx +49 -0
  114. package/src/icons/color/TiptapCalloutWarning.tsx +28 -0
  115. package/src/icons/color/index.ts +4 -0
  116. package/src/icons/index.ts +60 -0
  117. package/src/icons/menu/AddImage.tsx +10 -0
  118. package/src/icons/menu/AlignCenter.tsx +10 -0
  119. package/src/icons/menu/AlignLeft.tsx +10 -0
  120. package/src/icons/menu/AlignRight.tsx +10 -0
  121. package/src/icons/menu/ArrowDown.tsx +13 -0
  122. package/src/icons/menu/ArrowLeft.tsx +13 -0
  123. package/src/icons/menu/ArrowRight.tsx +13 -0
  124. package/src/icons/menu/ArrowUp.tsx +13 -0
  125. package/src/icons/menu/Blockquote.tsx +7 -0
  126. package/src/icons/menu/Bold.tsx +10 -0
  127. package/src/icons/menu/BulletList.tsx +10 -0
  128. package/src/icons/menu/CalloutError.tsx +10 -0
  129. package/src/icons/menu/CalloutInfo.tsx +12 -0
  130. package/src/icons/menu/CalloutSuccess.tsx +10 -0
  131. package/src/icons/menu/CalloutWarning.tsx +12 -0
  132. package/src/icons/menu/ClearFormatting.tsx +10 -0
  133. package/src/icons/menu/Code.tsx +10 -0
  134. package/src/icons/menu/CodeBlock.tsx +10 -0
  135. package/src/icons/menu/Copyable.tsx +10 -0
  136. package/src/icons/menu/CustomQuote.tsx +17 -0
  137. package/src/icons/menu/DeleteColumn.tsx +17 -0
  138. package/src/icons/menu/DeleteRow.tsx +17 -0
  139. package/src/icons/menu/Details.tsx +10 -0
  140. package/src/icons/menu/H2.tsx +10 -0
  141. package/src/icons/menu/H3.tsx +10 -0
  142. package/src/icons/menu/H4.tsx +10 -0
  143. package/src/icons/menu/H5.tsx +10 -0
  144. package/src/icons/menu/H6.tsx +10 -0
  145. package/src/icons/menu/Highlight.tsx +13 -0
  146. package/src/icons/menu/HorizontalRule.tsx +7 -0
  147. package/src/icons/menu/Italic.tsx +10 -0
  148. package/src/icons/menu/Link.tsx +10 -0
  149. package/src/icons/menu/LinkOff.tsx +10 -0
  150. package/src/icons/menu/Math.tsx +10 -0
  151. package/src/icons/menu/MergeCells.tsx +10 -0
  152. package/src/icons/menu/MythReality.tsx +10 -0
  153. package/src/icons/menu/OrderedList.tsx +10 -0
  154. package/src/icons/menu/Prompt.tsx +18 -0
  155. package/src/icons/menu/Redo.tsx +14 -0
  156. package/src/icons/menu/SplitCells.tsx +7 -0
  157. package/src/icons/menu/Strikethrough.tsx +10 -0
  158. package/src/icons/menu/Subscript.tsx +10 -0
  159. package/src/icons/menu/Superscript.tsx +10 -0
  160. package/src/icons/menu/Table.tsx +14 -0
  161. package/src/icons/menu/TableColumnHeading.tsx +7 -0
  162. package/src/icons/menu/TableRowHeading.tsx +10 -0
  163. package/src/icons/menu/TextColor.tsx +13 -0
  164. package/src/icons/menu/Underline.tsx +10 -0
  165. package/src/icons/menu/Undo.tsx +14 -0
  166. package/src/icons/menu/Video.tsx +14 -0
  167. package/src/icons/menu/index.ts +49 -0
  168. package/src/render/index.ts +22 -0
  169. package/src/render/static-renderer-config.tsx +206 -0
  170. package/src/render/tiptap-interactivity-provider.tsx +78 -0
  171. package/src/render/tiptap-render.tsx +102 -0
  172. package/src/styles/components.css +10 -0
  173. package/src/styles/editor/base.css +39 -0
  174. package/src/styles/editor/callout-menu.css +81 -0
  175. package/src/styles/editor/controls.css +57 -0
  176. package/src/styles/editor/emoji-picker.css +113 -0
  177. package/src/styles/editor/index.css +9 -0
  178. package/src/styles/editor/menus.css +16 -0
  179. package/src/styles/editor/states.css +43 -0
  180. package/src/styles/editor/typography.css +165 -0
  181. package/src/styles/editor/utilities.css +71 -0
  182. package/src/styles/editor/variables.css +70 -0
  183. package/src/styles/extensions/callout.css +155 -0
  184. package/src/styles/extensions/code-block.css +109 -0
  185. package/src/styles/extensions/commands-list.css +83 -0
  186. package/src/styles/extensions/custom-quote.css +103 -0
  187. package/src/styles/extensions/details.css +87 -0
  188. package/src/styles/extensions/figure.css +66 -0
  189. package/src/styles/extensions/index.css +11 -0
  190. package/src/styles/extensions/math.css +32 -0
  191. package/src/styles/extensions/myth-reality.css +59 -0
  192. package/src/styles/extensions/prompt.css +75 -0
  193. package/src/styles/extensions/table.css +253 -0
  194. package/src/styles/extensions/video.css +53 -0
  195. package/src/styles/styles.css +3 -0
  196. package/src/translations/en.json +158 -0
  197. package/src/translations/ru.json +158 -0
  198. package/src/types/image-handler.ts +33 -0
  199. package/src/types/index.ts +1 -0
  200. package/src/utils/copy-to-clipboard.ts +23 -0
  201. package/src/utils/custom-emoji.ts +174 -0
  202. package/src/utils/detect-video-hosting.ts +106 -0
  203. package/src/utils/get-shared-extensions.ts +45 -0
  204. package/src/utils/get-translations.ts +25 -0
  205. package/src/utils/handle-exit-node.ts +61 -0
  206. package/src/utils/image-src-resolver.ts +74 -0
  207. package/src/utils/index.ts +2 -0
  208. package/src/utils/migrate-legacy-callouts.ts +59 -0
  209. package/src/utils/pluralize.ts +38 -0
@@ -0,0 +1,24 @@
1
+ /**
2
+ * Client component that initializes Tiptap interactivity
3
+ * Use this in your layout to enable interactive features for server-rendered content
4
+ *
5
+ * @example
6
+ * ```tsx
7
+ * // app/layout.tsx (Server Component)
8
+ * import { CalloutInteractivityProvider } from '@cyberyozh/tiptap/render';
9
+ *
10
+ * export default function Layout({ children }) {
11
+ * return (
12
+ * <html>
13
+ * <body>
14
+ * <CalloutInteractivityProvider />
15
+ * {children}
16
+ * </body>
17
+ * </html>
18
+ * );
19
+ * }
20
+ * ```
21
+ */
22
+ declare function TiptapInteractivityProvider(): null;
23
+
24
+ export { TiptapInteractivityProvider };
@@ -0,0 +1,24 @@
1
+ /**
2
+ * Client component that initializes Tiptap interactivity
3
+ * Use this in your layout to enable interactive features for server-rendered content
4
+ *
5
+ * @example
6
+ * ```tsx
7
+ * // app/layout.tsx (Server Component)
8
+ * import { CalloutInteractivityProvider } from '@cyberyozh/tiptap/render';
9
+ *
10
+ * export default function Layout({ children }) {
11
+ * return (
12
+ * <html>
13
+ * <body>
14
+ * <CalloutInteractivityProvider />
15
+ * {children}
16
+ * </body>
17
+ * </html>
18
+ * );
19
+ * }
20
+ * ```
21
+ */
22
+ declare function TiptapInteractivityProvider(): null;
23
+
24
+ export { TiptapInteractivityProvider };
@@ -0,0 +1,98 @@
1
+ "use client";
2
+ "use strict";
3
+ "use client";
4
+ var __defProp = Object.defineProperty;
5
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
6
+ var __getOwnPropNames = Object.getOwnPropertyNames;
7
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __export = (target, all) => {
9
+ for (var name in all)
10
+ __defProp(target, name, { get: all[name], enumerable: true });
11
+ };
12
+ var __copyProps = (to, from, except, desc) => {
13
+ if (from && typeof from === "object" || typeof from === "function") {
14
+ for (let key of __getOwnPropNames(from))
15
+ if (!__hasOwnProp.call(to, key) && key !== except)
16
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
17
+ }
18
+ return to;
19
+ };
20
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
21
+
22
+ // src/render/tiptap-interactivity-provider.tsx
23
+ var tiptap_interactivity_provider_exports = {};
24
+ __export(tiptap_interactivity_provider_exports, {
25
+ TiptapInteractivityProvider: () => TiptapInteractivityProvider
26
+ });
27
+ module.exports = __toCommonJS(tiptap_interactivity_provider_exports);
28
+ var import_react = require("react");
29
+
30
+ // src/utils/copy-to-clipboard.ts
31
+ var copyToClipboard = (text) => {
32
+ if (navigator.clipboard && window.isSecureContext) {
33
+ return navigator.clipboard.writeText(text);
34
+ }
35
+ return new Promise((resolve, reject) => {
36
+ const textarea = document.createElement("textarea");
37
+ textarea.value = text;
38
+ textarea.style.position = "fixed";
39
+ textarea.style.opacity = "0";
40
+ document.body.appendChild(textarea);
41
+ try {
42
+ textarea.select();
43
+ document.execCommand("copy");
44
+ resolve();
45
+ } catch (error) {
46
+ reject(error);
47
+ } finally {
48
+ document.body.removeChild(textarea);
49
+ }
50
+ });
51
+ };
52
+
53
+ // src/render/tiptap-interactivity-provider.tsx
54
+ function TiptapInteractivityProvider() {
55
+ (0, import_react.useEffect)(() => {
56
+ function findCopyContent(button) {
57
+ const parent = button.closest(":has([data-copy-content])");
58
+ return parent?.querySelector("[data-copy-content]") || null;
59
+ }
60
+ function showSuccessIcon(button) {
61
+ const defaultIcon = button.querySelector('[data-copy-icon="default"]');
62
+ const successIcon = button.querySelector('[data-copy-icon="success"]');
63
+ if (defaultIcon && successIcon) {
64
+ defaultIcon.style.display = "none";
65
+ successIcon.style.display = "flex";
66
+ setTimeout(() => {
67
+ defaultIcon.style.display = "flex";
68
+ successIcon.style.display = "none";
69
+ }, 1500);
70
+ }
71
+ }
72
+ function handleCopy(e) {
73
+ const target = e.target;
74
+ const button = target.closest('[data-copy-action="copy"]');
75
+ if (button) {
76
+ const contentElement = findCopyContent(button);
77
+ if (contentElement) {
78
+ const textContent = contentElement.textContent?.trim() || "";
79
+ copyToClipboard(textContent).then(() => {
80
+ showSuccessIcon(button);
81
+ }).catch((error) => {
82
+ console.error("\u274C Failed to copy:", error);
83
+ });
84
+ }
85
+ }
86
+ }
87
+ document.addEventListener("click", handleCopy);
88
+ return () => {
89
+ document.removeEventListener("click", handleCopy);
90
+ };
91
+ }, []);
92
+ return null;
93
+ }
94
+ // Annotate the CommonJS export names for ESM import in node:
95
+ 0 && (module.exports = {
96
+ TiptapInteractivityProvider
97
+ });
98
+ //# sourceMappingURL=client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/render/tiptap-interactivity-provider.tsx","../../src/utils/copy-to-clipboard.ts"],"sourcesContent":["\"use client\";\n\nimport { useEffect } from \"react\";\nimport { copyToClipboard } from \"../utils/copy-to-clipboard\";\n\n/**\n * Client component that initializes Tiptap interactivity\n * Use this in your layout to enable interactive features for server-rendered content\n *\n * @example\n * ```tsx\n * // app/layout.tsx (Server Component)\n * import { CalloutInteractivityProvider } from '@cyberyozh/tiptap/render';\n *\n * export default function Layout({ children }) {\n * return (\n * <html>\n * <body>\n * <CalloutInteractivityProvider />\n * {children}\n * </body>\n * </html>\n * );\n * }\n * ```\n */\nexport function TiptapInteractivityProvider() {\n useEffect(() => {\n function findCopyContent(button: HTMLElement): Element | null {\n const parent = button.closest(\":has([data-copy-content])\");\n return parent?.querySelector(\"[data-copy-content]\") || null;\n }\n\n function showSuccessIcon(button: HTMLElement) {\n const defaultIcon = button.querySelector('[data-copy-icon=\"default\"]') as HTMLElement;\n const successIcon = button.querySelector('[data-copy-icon=\"success\"]') as HTMLElement;\n\n if (defaultIcon && successIcon) {\n defaultIcon.style.display = \"none\";\n successIcon.style.display = \"flex\";\n\n setTimeout(() => {\n defaultIcon.style.display = \"flex\";\n successIcon.style.display = \"none\";\n }, 1500);\n }\n }\n\n function handleCopy(e: MouseEvent) {\n const target = e.target as HTMLElement;\n const button = target.closest('[data-copy-action=\"copy\"]') as HTMLElement;\n\n if (button) {\n const contentElement = findCopyContent(button);\n\n if (contentElement) {\n const textContent = contentElement.textContent?.trim() || \"\";\n\n copyToClipboard(textContent)\n .then(() => {\n showSuccessIcon(button);\n })\n .catch((error) => {\n console.error(\"❌ Failed to copy:\", error);\n });\n }\n }\n }\n\n document.addEventListener(\"click\", handleCopy);\n\n return () => {\n document.removeEventListener(\"click\", handleCopy);\n };\n }, []);\n\n return null;\n}\n","export const copyToClipboard = (text: string): Promise<void> => {\n if (navigator.clipboard && window.isSecureContext) {\n return navigator.clipboard.writeText(text);\n }\n\n return new Promise((resolve, reject) => {\n const textarea = document.createElement(\"textarea\");\n textarea.value = text;\n textarea.style.position = \"fixed\";\n textarea.style.opacity = \"0\";\n document.body.appendChild(textarea);\n\n try {\n textarea.select();\n document.execCommand(\"copy\");\n resolve();\n } catch (error) {\n reject(error);\n } finally {\n document.body.removeChild(textarea);\n }\n });\n};\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAEA,mBAA0B;;;ACFnB,IAAM,kBAAkB,CAAC,SAAgC;AAC9D,MAAI,UAAU,aAAa,OAAO,iBAAiB;AACjD,WAAO,UAAU,UAAU,UAAU,IAAI;AAAA,EAC3C;AAEA,SAAO,IAAI,QAAQ,CAAC,SAAS,WAAW;AACtC,UAAM,WAAW,SAAS,cAAc,UAAU;AAClD,aAAS,QAAQ;AACjB,aAAS,MAAM,WAAW;AAC1B,aAAS,MAAM,UAAU;AACzB,aAAS,KAAK,YAAY,QAAQ;AAElC,QAAI;AACF,eAAS,OAAO;AAChB,eAAS,YAAY,MAAM;AAC3B,cAAQ;AAAA,IACV,SAAS,OAAO;AACd,aAAO,KAAK;AAAA,IACd,UAAE;AACA,eAAS,KAAK,YAAY,QAAQ;AAAA,IACpC;AAAA,EACF,CAAC;AACH;;;ADIO,SAAS,8BAA8B;AAC5C,8BAAU,MAAM;AACd,aAAS,gBAAgB,QAAqC;AAC5D,YAAM,SAAS,OAAO,QAAQ,2BAA2B;AACzD,aAAO,QAAQ,cAAc,qBAAqB,KAAK;AAAA,IACzD;AAEA,aAAS,gBAAgB,QAAqB;AAC5C,YAAM,cAAc,OAAO,cAAc,4BAA4B;AACrE,YAAM,cAAc,OAAO,cAAc,4BAA4B;AAErE,UAAI,eAAe,aAAa;AAC9B,oBAAY,MAAM,UAAU;AAC5B,oBAAY,MAAM,UAAU;AAE5B,mBAAW,MAAM;AACf,sBAAY,MAAM,UAAU;AAC5B,sBAAY,MAAM,UAAU;AAAA,QAC9B,GAAG,IAAI;AAAA,MACT;AAAA,IACF;AAEA,aAAS,WAAW,GAAe;AACjC,YAAM,SAAS,EAAE;AACjB,YAAM,SAAS,OAAO,QAAQ,2BAA2B;AAEzD,UAAI,QAAQ;AACV,cAAM,iBAAiB,gBAAgB,MAAM;AAE7C,YAAI,gBAAgB;AAClB,gBAAM,cAAc,eAAe,aAAa,KAAK,KAAK;AAE1D,0BAAgB,WAAW,EACxB,KAAK,MAAM;AACV,4BAAgB,MAAM;AAAA,UACxB,CAAC,EACA,MAAM,CAAC,UAAU;AAChB,oBAAQ,MAAM,0BAAqB,KAAK;AAAA,UAC1C,CAAC;AAAA,QACL;AAAA,MACF;AAAA,IACF;AAEA,aAAS,iBAAiB,SAAS,UAAU;AAE7C,WAAO,MAAM;AACX,eAAS,oBAAoB,SAAS,UAAU;AAAA,IAClD;AAAA,EACF,GAAG,CAAC,CAAC;AAEL,SAAO;AACT;","names":[]}
@@ -0,0 +1,74 @@
1
+ "use client";
2
+ "use client";
3
+
4
+ // src/render/tiptap-interactivity-provider.tsx
5
+ import { useEffect } from "react";
6
+
7
+ // src/utils/copy-to-clipboard.ts
8
+ var copyToClipboard = (text) => {
9
+ if (navigator.clipboard && window.isSecureContext) {
10
+ return navigator.clipboard.writeText(text);
11
+ }
12
+ return new Promise((resolve, reject) => {
13
+ const textarea = document.createElement("textarea");
14
+ textarea.value = text;
15
+ textarea.style.position = "fixed";
16
+ textarea.style.opacity = "0";
17
+ document.body.appendChild(textarea);
18
+ try {
19
+ textarea.select();
20
+ document.execCommand("copy");
21
+ resolve();
22
+ } catch (error) {
23
+ reject(error);
24
+ } finally {
25
+ document.body.removeChild(textarea);
26
+ }
27
+ });
28
+ };
29
+
30
+ // src/render/tiptap-interactivity-provider.tsx
31
+ function TiptapInteractivityProvider() {
32
+ useEffect(() => {
33
+ function findCopyContent(button) {
34
+ const parent = button.closest(":has([data-copy-content])");
35
+ return parent?.querySelector("[data-copy-content]") || null;
36
+ }
37
+ function showSuccessIcon(button) {
38
+ const defaultIcon = button.querySelector('[data-copy-icon="default"]');
39
+ const successIcon = button.querySelector('[data-copy-icon="success"]');
40
+ if (defaultIcon && successIcon) {
41
+ defaultIcon.style.display = "none";
42
+ successIcon.style.display = "flex";
43
+ setTimeout(() => {
44
+ defaultIcon.style.display = "flex";
45
+ successIcon.style.display = "none";
46
+ }, 1500);
47
+ }
48
+ }
49
+ function handleCopy(e) {
50
+ const target = e.target;
51
+ const button = target.closest('[data-copy-action="copy"]');
52
+ if (button) {
53
+ const contentElement = findCopyContent(button);
54
+ if (contentElement) {
55
+ const textContent = contentElement.textContent?.trim() || "";
56
+ copyToClipboard(textContent).then(() => {
57
+ showSuccessIcon(button);
58
+ }).catch((error) => {
59
+ console.error("\u274C Failed to copy:", error);
60
+ });
61
+ }
62
+ }
63
+ }
64
+ document.addEventListener("click", handleCopy);
65
+ return () => {
66
+ document.removeEventListener("click", handleCopy);
67
+ };
68
+ }, []);
69
+ return null;
70
+ }
71
+ export {
72
+ TiptapInteractivityProvider
73
+ };
74
+ //# sourceMappingURL=client.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/render/tiptap-interactivity-provider.tsx","../../src/utils/copy-to-clipboard.ts"],"sourcesContent":["\"use client\";\n\nimport { useEffect } from \"react\";\nimport { copyToClipboard } from \"../utils/copy-to-clipboard\";\n\n/**\n * Client component that initializes Tiptap interactivity\n * Use this in your layout to enable interactive features for server-rendered content\n *\n * @example\n * ```tsx\n * // app/layout.tsx (Server Component)\n * import { CalloutInteractivityProvider } from '@cyberyozh/tiptap/render';\n *\n * export default function Layout({ children }) {\n * return (\n * <html>\n * <body>\n * <CalloutInteractivityProvider />\n * {children}\n * </body>\n * </html>\n * );\n * }\n * ```\n */\nexport function TiptapInteractivityProvider() {\n useEffect(() => {\n function findCopyContent(button: HTMLElement): Element | null {\n const parent = button.closest(\":has([data-copy-content])\");\n return parent?.querySelector(\"[data-copy-content]\") || null;\n }\n\n function showSuccessIcon(button: HTMLElement) {\n const defaultIcon = button.querySelector('[data-copy-icon=\"default\"]') as HTMLElement;\n const successIcon = button.querySelector('[data-copy-icon=\"success\"]') as HTMLElement;\n\n if (defaultIcon && successIcon) {\n defaultIcon.style.display = \"none\";\n successIcon.style.display = \"flex\";\n\n setTimeout(() => {\n defaultIcon.style.display = \"flex\";\n successIcon.style.display = \"none\";\n }, 1500);\n }\n }\n\n function handleCopy(e: MouseEvent) {\n const target = e.target as HTMLElement;\n const button = target.closest('[data-copy-action=\"copy\"]') as HTMLElement;\n\n if (button) {\n const contentElement = findCopyContent(button);\n\n if (contentElement) {\n const textContent = contentElement.textContent?.trim() || \"\";\n\n copyToClipboard(textContent)\n .then(() => {\n showSuccessIcon(button);\n })\n .catch((error) => {\n console.error(\"❌ Failed to copy:\", error);\n });\n }\n }\n }\n\n document.addEventListener(\"click\", handleCopy);\n\n return () => {\n document.removeEventListener(\"click\", handleCopy);\n };\n }, []);\n\n return null;\n}\n","export const copyToClipboard = (text: string): Promise<void> => {\n if (navigator.clipboard && window.isSecureContext) {\n return navigator.clipboard.writeText(text);\n }\n\n return new Promise((resolve, reject) => {\n const textarea = document.createElement(\"textarea\");\n textarea.value = text;\n textarea.style.position = \"fixed\";\n textarea.style.opacity = \"0\";\n document.body.appendChild(textarea);\n\n try {\n textarea.select();\n document.execCommand(\"copy\");\n resolve();\n } catch (error) {\n reject(error);\n } finally {\n document.body.removeChild(textarea);\n }\n });\n};\n"],"mappings":";;;;AAEA,SAAS,iBAAiB;;;ACFnB,IAAM,kBAAkB,CAAC,SAAgC;AAC9D,MAAI,UAAU,aAAa,OAAO,iBAAiB;AACjD,WAAO,UAAU,UAAU,UAAU,IAAI;AAAA,EAC3C;AAEA,SAAO,IAAI,QAAQ,CAAC,SAAS,WAAW;AACtC,UAAM,WAAW,SAAS,cAAc,UAAU;AAClD,aAAS,QAAQ;AACjB,aAAS,MAAM,WAAW;AAC1B,aAAS,MAAM,UAAU;AACzB,aAAS,KAAK,YAAY,QAAQ;AAElC,QAAI;AACF,eAAS,OAAO;AAChB,eAAS,YAAY,MAAM;AAC3B,cAAQ;AAAA,IACV,SAAS,OAAO;AACd,aAAO,KAAK;AAAA,IACd,UAAE;AACA,eAAS,KAAK,YAAY,QAAQ;AAAA,IACpC;AAAA,EACF,CAAC;AACH;;;ADIO,SAAS,8BAA8B;AAC5C,YAAU,MAAM;AACd,aAAS,gBAAgB,QAAqC;AAC5D,YAAM,SAAS,OAAO,QAAQ,2BAA2B;AACzD,aAAO,QAAQ,cAAc,qBAAqB,KAAK;AAAA,IACzD;AAEA,aAAS,gBAAgB,QAAqB;AAC5C,YAAM,cAAc,OAAO,cAAc,4BAA4B;AACrE,YAAM,cAAc,OAAO,cAAc,4BAA4B;AAErE,UAAI,eAAe,aAAa;AAC9B,oBAAY,MAAM,UAAU;AAC5B,oBAAY,MAAM,UAAU;AAE5B,mBAAW,MAAM;AACf,sBAAY,MAAM,UAAU;AAC5B,sBAAY,MAAM,UAAU;AAAA,QAC9B,GAAG,IAAI;AAAA,MACT;AAAA,IACF;AAEA,aAAS,WAAW,GAAe;AACjC,YAAM,SAAS,EAAE;AACjB,YAAM,SAAS,OAAO,QAAQ,2BAA2B;AAEzD,UAAI,QAAQ;AACV,cAAM,iBAAiB,gBAAgB,MAAM;AAE7C,YAAI,gBAAgB;AAClB,gBAAM,cAAc,eAAe,aAAa,KAAK,KAAK;AAE1D,0BAAgB,WAAW,EACxB,KAAK,MAAM;AACV,4BAAgB,MAAM;AAAA,UACxB,CAAC,EACA,MAAM,CAAC,UAAU;AAChB,oBAAQ,MAAM,0BAAqB,KAAK;AAAA,UAC1C,CAAC;AAAA,QACL;AAAA,MACF;AAAA,IACF;AAEA,aAAS,iBAAiB,SAAS,UAAU;AAE7C,WAAO,MAAM;AACX,eAAS,oBAAoB,SAAS,UAAU;AAAA,IAClD;AAAA,EACF,GAAG,CAAC,CAAC;AAEL,SAAO;AACT;","names":[]}
@@ -0,0 +1,58 @@
1
+ import { ReactNode } from 'react';
2
+
3
+ type JSONContent = Record<string, any>;
4
+ interface TiptapRenderProps {
5
+ /**
6
+ * Tiptap JSON content (parsed object or JSON string)
7
+ */
8
+ content: JSONContent | string;
9
+ /**
10
+ * Function to resolve image URLs from file IDs
11
+ * Used for static rendering of figure nodes with file references
12
+ */
13
+ getImageById?: (fileId: string) => string | null;
14
+ }
15
+ /**
16
+ * Server component that renders Tiptap JSON content as React
17
+ *
18
+ * Designed for Next.js Server Components. Converts Tiptap JSON to rendered React elements
19
+ * without any client-side dependencies.
20
+ *
21
+ * @example
22
+ * ```tsx
23
+ * // app/blog/[slug]/page.tsx (Server Component)
24
+ * import { TiptapRender } from '@cyberyozh/tiptap/server';
25
+ *
26
+ * export default function BlogPost({ article }) {
27
+ * return (
28
+ * <article>
29
+ * <h1>{article.title}</h1>
30
+ * <TiptapRender content={article.content} lang="en" />
31
+ * </article>
32
+ * );
33
+ * }
34
+ * ```
35
+ *
36
+ * @example
37
+ * ```tsx
38
+ * // With custom image resolver
39
+ * import { TiptapRender } from '@cyberyozh/tiptap/server';
40
+ *
41
+ * const getImageById = (fileId: string) => `/api/images/${fileId}`;
42
+ *
43
+ * export default function BlogPost({ article }) {
44
+ * return (
45
+ * <article>
46
+ * <TiptapRender
47
+ * content={article.content}
48
+ * lang="en"
49
+ * getImageById={getImageById}
50
+ * />
51
+ * </article>
52
+ * );
53
+ * }
54
+ * ```
55
+ */
56
+ declare function TiptapRender({ content, getImageById }: TiptapRenderProps): ReactNode;
57
+
58
+ export { TiptapRender };
@@ -0,0 +1,58 @@
1
+ import { ReactNode } from 'react';
2
+
3
+ type JSONContent = Record<string, any>;
4
+ interface TiptapRenderProps {
5
+ /**
6
+ * Tiptap JSON content (parsed object or JSON string)
7
+ */
8
+ content: JSONContent | string;
9
+ /**
10
+ * Function to resolve image URLs from file IDs
11
+ * Used for static rendering of figure nodes with file references
12
+ */
13
+ getImageById?: (fileId: string) => string | null;
14
+ }
15
+ /**
16
+ * Server component that renders Tiptap JSON content as React
17
+ *
18
+ * Designed for Next.js Server Components. Converts Tiptap JSON to rendered React elements
19
+ * without any client-side dependencies.
20
+ *
21
+ * @example
22
+ * ```tsx
23
+ * // app/blog/[slug]/page.tsx (Server Component)
24
+ * import { TiptapRender } from '@cyberyozh/tiptap/server';
25
+ *
26
+ * export default function BlogPost({ article }) {
27
+ * return (
28
+ * <article>
29
+ * <h1>{article.title}</h1>
30
+ * <TiptapRender content={article.content} lang="en" />
31
+ * </article>
32
+ * );
33
+ * }
34
+ * ```
35
+ *
36
+ * @example
37
+ * ```tsx
38
+ * // With custom image resolver
39
+ * import { TiptapRender } from '@cyberyozh/tiptap/server';
40
+ *
41
+ * const getImageById = (fileId: string) => `/api/images/${fileId}`;
42
+ *
43
+ * export default function BlogPost({ article }) {
44
+ * return (
45
+ * <article>
46
+ * <TiptapRender
47
+ * content={article.content}
48
+ * lang="en"
49
+ * getImageById={getImageById}
50
+ * />
51
+ * </article>
52
+ * );
53
+ * }
54
+ * ```
55
+ */
56
+ declare function TiptapRender({ content, getImageById }: TiptapRenderProps): ReactNode;
57
+
58
+ export { TiptapRender };