@eventuras/scribo 0.8.3 → 0.10.7

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 (164) hide show
  1. package/dist/App.d.ts +11 -0
  2. package/dist/App.d.ts.map +1 -0
  3. package/dist/MarkdownEditor.d.ts +18 -0
  4. package/dist/MarkdownEditor.d.ts.map +1 -0
  5. package/dist/MarkdownEditor2.js +111 -0
  6. package/dist/MarkdownEditor2.js.map +1 -0
  7. package/dist/MarkdownInput.d.ts +27 -0
  8. package/dist/MarkdownInput.d.ts.map +1 -0
  9. package/dist/MarkdownInput.js +57 -0
  10. package/dist/MarkdownInput.js.map +1 -0
  11. package/dist/callout.js +5 -0
  12. package/dist/context/SharedHistoryContext.d.ts +11 -0
  13. package/dist/context/SharedHistoryContext.d.ts.map +1 -0
  14. package/dist/context/SharedHistoryContext.js +12 -0
  15. package/dist/context/SharedHistoryContext.js.map +1 -0
  16. package/dist/index.d.ts +1 -0
  17. package/dist/index.d.ts.map +1 -0
  18. package/dist/main.d.ts +5 -0
  19. package/dist/main.d.ts.map +1 -0
  20. package/dist/main.js +4 -0
  21. package/dist/nodes/EditorNodes.d.ts +4 -0
  22. package/dist/nodes/EditorNodes.d.ts.map +1 -0
  23. package/dist/nodes/EditorNodes.js +39 -0
  24. package/dist/nodes/EditorNodes.js.map +1 -0
  25. package/dist/nodes/callout/CalloutComponent.d.ts +6 -0
  26. package/dist/nodes/callout/CalloutComponent.d.ts.map +1 -0
  27. package/dist/nodes/callout/CalloutComponent.js +53 -0
  28. package/dist/nodes/callout/CalloutComponent.js.map +1 -0
  29. package/dist/nodes/callout/CalloutNode.d.ts +27 -0
  30. package/dist/nodes/callout/CalloutNode.d.ts.map +1 -0
  31. package/dist/nodes/callout/CalloutNode.js +153 -0
  32. package/dist/nodes/callout/CalloutNode.js.map +1 -0
  33. package/dist/nodes/callout/CalloutTransformer.d.ts +3 -0
  34. package/dist/nodes/callout/CalloutTransformer.d.ts.map +1 -0
  35. package/dist/nodes/callout/CalloutTransformer.js +48 -0
  36. package/dist/nodes/callout/CalloutTransformer.js.map +1 -0
  37. package/dist/nodes/callout/calloutPlugin.d.ts +3 -0
  38. package/dist/nodes/callout/calloutPlugin.d.ts.map +1 -0
  39. package/dist/nodes/callout/calloutPlugin.js +34 -0
  40. package/dist/nodes/callout/calloutPlugin.js.map +1 -0
  41. package/dist/nodes/callout/index.d.ts +6 -0
  42. package/dist/nodes/callout/index.d.ts.map +1 -0
  43. package/dist/nodes/schedule/ScheduleItemComponent.d.ts +9 -0
  44. package/dist/nodes/schedule/ScheduleItemComponent.d.ts.map +1 -0
  45. package/dist/nodes/schedule/ScheduleItemComponent.js +167 -0
  46. package/dist/nodes/schedule/ScheduleItemComponent.js.map +1 -0
  47. package/dist/nodes/schedule/ScheduleItemNode.d.ts +31 -0
  48. package/dist/nodes/schedule/ScheduleItemNode.d.ts.map +1 -0
  49. package/dist/nodes/schedule/ScheduleItemNode.js +94 -0
  50. package/dist/nodes/schedule/ScheduleItemNode.js.map +1 -0
  51. package/dist/nodes/schedule/ScheduleTransformer.d.ts +22 -0
  52. package/dist/nodes/schedule/ScheduleTransformer.d.ts.map +1 -0
  53. package/dist/nodes/schedule/ScheduleTransformer.js +60 -0
  54. package/dist/nodes/schedule/ScheduleTransformer.js.map +1 -0
  55. package/dist/nodes/schedule/index.d.ts +5 -0
  56. package/dist/nodes/schedule/index.d.ts.map +1 -0
  57. package/dist/nodes/schedule/schedulePlugin.d.ts +3 -0
  58. package/dist/nodes/schedule/schedulePlugin.d.ts.map +1 -0
  59. package/dist/nodes/schedule/schedulePlugin.js +33 -0
  60. package/dist/nodes/schedule/schedulePlugin.js.map +1 -0
  61. package/dist/plugins/AutoLinkPlugin.d.ts +3 -0
  62. package/dist/plugins/AutoLinkPlugin.d.ts.map +1 -0
  63. package/dist/plugins/AutoLinkPlugin.js +22 -0
  64. package/dist/plugins/AutoLinkPlugin.js.map +1 -0
  65. package/dist/plugins/FloatingLinkEditorPlugin.d.ts +7 -0
  66. package/dist/plugins/FloatingLinkEditorPlugin.d.ts.map +1 -0
  67. package/dist/plugins/FloatingLinkEditorPlugin2.js +302 -0
  68. package/dist/plugins/FloatingLinkEditorPlugin2.js.map +1 -0
  69. package/dist/plugins/HistoryPlugin.d.ts +26 -0
  70. package/dist/plugins/HistoryPlugin.d.ts.map +1 -0
  71. package/dist/plugins/LinkPlugin.d.ts +3 -0
  72. package/dist/plugins/LinkPlugin.d.ts.map +1 -0
  73. package/dist/plugins/LinkPlugin.js +18 -0
  74. package/dist/plugins/LinkPlugin.js.map +1 -0
  75. package/dist/plugins/ToolbarPlugin.d.ts +7 -0
  76. package/dist/plugins/ToolbarPlugin.d.ts.map +1 -0
  77. package/dist/plugins/ToolbarPlugin.js +372 -0
  78. package/dist/plugins/ToolbarPlugin.js.map +1 -0
  79. package/dist/schedule.js +4 -0
  80. package/dist/scribo.css +1977 -0
  81. package/dist/themes/EditorTheme.d.ts +4 -0
  82. package/dist/themes/EditorTheme.d.ts.map +1 -0
  83. package/dist/themes/EditorTheme2.js +107 -0
  84. package/dist/themes/EditorTheme2.js.map +1 -0
  85. package/dist/types.d.ts +26 -0
  86. package/dist/types.d.ts.map +1 -0
  87. package/dist/ui/ContentEditable.d.ts +6 -0
  88. package/dist/ui/ContentEditable.d.ts.map +1 -0
  89. package/dist/ui/ContentEditable2.js +14 -0
  90. package/dist/ui/ContentEditable2.js.map +1 -0
  91. package/dist/ui/DropDown.d.ts +18 -0
  92. package/dist/ui/DropDown.d.ts.map +1 -0
  93. package/dist/ui/DropDown.js +162 -0
  94. package/dist/ui/DropDown.js.map +1 -0
  95. package/dist/ui/Placeholder.d.ts +6 -0
  96. package/dist/ui/Placeholder.d.ts.map +1 -0
  97. package/dist/ui/Placeholder2.js +13 -0
  98. package/dist/ui/Placeholder2.js.map +1 -0
  99. package/dist/utils/environment.d.ts +24 -0
  100. package/dist/utils/environment.d.ts.map +1 -0
  101. package/dist/utils/environment.js +20 -0
  102. package/dist/utils/environment.js.map +1 -0
  103. package/dist/utils/getSelectedNode.d.ts +3 -0
  104. package/dist/utils/getSelectedNode.d.ts.map +1 -0
  105. package/dist/utils/getSelectedNode.js +23 -0
  106. package/dist/utils/getSelectedNode.js.map +1 -0
  107. package/dist/utils/setFloatingElemPosition.d.ts +2 -0
  108. package/dist/utils/setFloatingElemPosition.d.ts.map +1 -0
  109. package/dist/utils/setFloatingElemPositionForLinkEditor.d.ts +2 -0
  110. package/dist/utils/setFloatingElemPositionForLinkEditor.d.ts.map +1 -0
  111. package/dist/utils/setFloatingElemPositionForLinkEditor.js +33 -0
  112. package/dist/utils/setFloatingElemPositionForLinkEditor.js.map +1 -0
  113. package/dist/utils/url.d.ts +11 -0
  114. package/dist/utils/url.d.ts.map +1 -0
  115. package/dist/utils/url.js +33 -0
  116. package/dist/utils/url.js.map +1 -0
  117. package/dist/vite.svg +1 -0
  118. package/package.json +55 -38
  119. package/src/MarkdownEditor.css +61 -47
  120. package/src/MarkdownEditor.tsx +76 -29
  121. package/src/MarkdownInput.tsx +9 -10
  122. package/src/context/SharedHistoryContext.tsx +8 -16
  123. package/src/main.tsx +3 -3
  124. package/src/nodes/EditorNodes.ts +10 -10
  125. package/src/nodes/callout/Callout.css +94 -0
  126. package/src/nodes/callout/CalloutComponent.tsx +61 -0
  127. package/src/nodes/callout/CalloutNode.ts +197 -0
  128. package/src/nodes/callout/CalloutTransformer.ts +87 -0
  129. package/src/nodes/callout/calloutPlugin.ts +37 -0
  130. package/src/nodes/callout/index.ts +5 -0
  131. package/src/nodes/schedule/ScheduleItem.css +140 -0
  132. package/src/nodes/schedule/ScheduleItemComponent.tsx +195 -0
  133. package/src/nodes/schedule/ScheduleItemNode.ts +135 -0
  134. package/src/nodes/schedule/ScheduleTransformer.ts +80 -0
  135. package/src/nodes/schedule/index.ts +4 -0
  136. package/src/nodes/schedule/schedulePlugin.ts +33 -0
  137. package/src/plugins/AutoLinkPlugin.tsx +5 -10
  138. package/src/plugins/FloatingLinkEditorPlugin.tsx +42 -66
  139. package/src/plugins/HistoryPlugin.tsx +20 -30
  140. package/src/plugins/LinkPlugin.tsx +2 -3
  141. package/src/plugins/ToolbarPlugin.tsx +129 -141
  142. package/src/themes/EditorTheme.css +9 -5
  143. package/src/themes/EditorTheme.ts +89 -90
  144. package/src/types.ts +27 -0
  145. package/src/ui/ContentEditable.tsx +5 -5
  146. package/src/ui/DropDown.tsx +23 -41
  147. package/src/ui/Placeholder.tsx +21 -21
  148. package/src/utils/environment.ts +6 -12
  149. package/src/utils/getSelectedNode.ts +3 -5
  150. package/src/utils/setFloatingElemPosition.ts +2 -5
  151. package/src/utils/setFloatingElemPositionForLinkEditor.ts +1 -1
  152. package/src/utils/url.ts +4 -10
  153. package/tsconfig.json +8 -0
  154. package/CHANGELOG.md +0 -65
  155. package/README.md +0 -126
  156. package/RELEASE.md +0 -102
  157. package/eslint.config.js +0 -4
  158. package/src/App.css +0 -35
  159. package/src/App.tsx +0 -42
  160. package/src/index.tsx +0 -13
  161. package/tsconfig.node.json +0 -11
  162. package/vite.config.site.ts +0 -19
  163. package/vite.config.ts +0 -33
  164. /package/{src → dist}/vite-env.d.ts +0 -0
@@ -0,0 +1,22 @@
1
+ import { ElementTransformer } from '@lexical/markdown';
2
+ import { ScheduleItemData } from './ScheduleItemNode';
3
+ export declare function normalizeScheduleItemData(data: {
4
+ time: string;
5
+ title: string;
6
+ speaker?: string;
7
+ description?: string;
8
+ }): {
9
+ time: string;
10
+ title: string;
11
+ speaker: string | undefined;
12
+ description: string | undefined;
13
+ };
14
+ export declare function parseScheduleItemMarkdown(markdown: string): {
15
+ time: string;
16
+ title: string;
17
+ speaker: string | undefined;
18
+ description: string | undefined;
19
+ } | null;
20
+ export declare function formatScheduleItemMarkdown(data: ScheduleItemData): string;
21
+ export declare const SCHEDULE_ITEM_TRANSFORMER: ElementTransformer;
22
+ //# sourceMappingURL=ScheduleTransformer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ScheduleTransformer.d.ts","sourceRoot":"","sources":["../../../src/nodes/schedule/ScheduleTransformer.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AAE5D,OAAO,EAGL,KAAK,gBAAgB,EAEtB,MAAM,oBAAoB,CAAC;AAY5B,wBAAgB,yBAAyB,CAAC,IAAI,EAAE;IAC9C,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;;;;;EAOA;AAED,wBAAgB,yBAAyB,CAAC,QAAQ,EAAE,MAAM;;;;;SAczD;AAED,wBAAgB,0BAA0B,CAAC,IAAI,EAAE,gBAAgB,GAAG,MAAM,CAIzE;AAED,eAAO,MAAM,yBAAyB,EAAE,kBAwBvC,CAAC"}
@@ -0,0 +1,60 @@
1
+ import { $createScheduleItemNode, $isScheduleItemNode, ScheduleItemNode } from "./ScheduleItemNode.js";
2
+ //#region src/nodes/schedule/ScheduleTransformer.ts
3
+ /**
4
+ * Markdown format: `- **09:00–10:00** Title | Speaker | Description`
5
+ *
6
+ * This matches the format expected by the remarkSchedule plugin in
7
+ * markdown-plugin-happening, so the same markdown renders correctly
8
+ * both in the editor and on the frontend.
9
+ */
10
+ var SCHEDULE_ITEM_REGEX = /^-\s+\*\*(\d{1,2}[.:]\d{2}(?:\s*[–-]\s*\d{1,2}[.:]\d{2})?)\s*\*\*\s+(.+)$/;
11
+ function normalizeScheduleItemData(data) {
12
+ return {
13
+ time: data.time.trim(),
14
+ title: data.title.trim(),
15
+ speaker: data.speaker?.trim() || void 0,
16
+ description: data.description?.trim() || void 0
17
+ };
18
+ }
19
+ function parseScheduleItemMarkdown(markdown) {
20
+ const match = markdown.match(SCHEDULE_ITEM_REGEX);
21
+ if (!match) return null;
22
+ const time = (match[1] ?? "").replaceAll(".", ":").trim();
23
+ const parts = (match[2] ?? "").trim().split("|").map((s) => s.trim());
24
+ return normalizeScheduleItemData({
25
+ time,
26
+ title: parts[0] ?? "",
27
+ speaker: parts[1] || void 0,
28
+ description: parts[2] || void 0
29
+ });
30
+ }
31
+ function formatScheduleItemMarkdown(data) {
32
+ const normalized = normalizeScheduleItemData(data);
33
+ const parts = [
34
+ normalized.title,
35
+ normalized.speaker,
36
+ normalized.description
37
+ ].filter(Boolean);
38
+ return `- **${normalized.time}** ${parts.join(" | ")}`;
39
+ }
40
+ var SCHEDULE_ITEM_TRANSFORMER = {
41
+ type: "element",
42
+ dependencies: [ScheduleItemNode],
43
+ regExp: SCHEDULE_ITEM_REGEX,
44
+ export: (node) => {
45
+ if (!$isScheduleItemNode(node)) return null;
46
+ return formatScheduleItemMarkdown(node.getData());
47
+ },
48
+ replace: (parentNode, _children, match) => {
49
+ const parsed = parseScheduleItemMarkdown(match[0] ?? "");
50
+ const node = $createScheduleItemNode(parsed ?? {
51
+ time: ((match[1] ?? "").replaceAll(".", ":").trim() || "").trim(),
52
+ title: ""
53
+ });
54
+ parentNode.replace(node);
55
+ }
56
+ };
57
+ //#endregion
58
+ export { SCHEDULE_ITEM_TRANSFORMER, formatScheduleItemMarkdown, normalizeScheduleItemData, parseScheduleItemMarkdown };
59
+
60
+ //# sourceMappingURL=ScheduleTransformer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ScheduleTransformer.js","names":[],"sources":["../../../src/nodes/schedule/ScheduleTransformer.ts"],"sourcesContent":["import type { ElementTransformer } from '@lexical/markdown';\n\nimport {\n $createScheduleItemNode,\n $isScheduleItemNode,\n type ScheduleItemData,\n ScheduleItemNode,\n} from './ScheduleItemNode';\n\n/**\n * Markdown format: `- **09:00–10:00** Title | Speaker | Description`\n *\n * This matches the format expected by the remarkSchedule plugin in\n * markdown-plugin-happening, so the same markdown renders correctly\n * both in the editor and on the frontend.\n */\nconst SCHEDULE_ITEM_REGEX =\n /^-\\s+\\*\\*(\\d{1,2}[.:]\\d{2}(?:\\s*[–-]\\s*\\d{1,2}[.:]\\d{2})?)\\s*\\*\\*\\s+(.+)$/;\n\nexport function normalizeScheduleItemData(data: {\n time: string;\n title: string;\n speaker?: string;\n description?: string;\n}) {\n return {\n time: data.time.trim(),\n title: data.title.trim(),\n speaker: data.speaker?.trim() || undefined,\n description: data.description?.trim() || undefined,\n };\n}\n\nexport function parseScheduleItemMarkdown(markdown: string) {\n const match = markdown.match(SCHEDULE_ITEM_REGEX);\n if (!match) return null;\n\n const time = (match[1] ?? '').replaceAll('.', ':').trim();\n const rest = (match[2] ?? '').trim();\n const parts = rest.split('|').map((s) => s.trim());\n\n return normalizeScheduleItemData({\n time,\n title: parts[0] ?? '',\n speaker: parts[1] || undefined,\n description: parts[2] || undefined,\n });\n}\n\nexport function formatScheduleItemMarkdown(data: ScheduleItemData): string {\n const normalized = normalizeScheduleItemData(data);\n const parts = [normalized.title, normalized.speaker, normalized.description].filter(Boolean);\n return `- **${normalized.time}** ${parts.join(' | ')}`;\n}\n\nexport const SCHEDULE_ITEM_TRANSFORMER: ElementTransformer = {\n type: 'element',\n dependencies: [ScheduleItemNode],\n\n regExp: SCHEDULE_ITEM_REGEX,\n\n export: (node) => {\n if (!$isScheduleItemNode(node)) return null;\n\n return formatScheduleItemMarkdown(node.getData());\n },\n\n replace: (parentNode, _children, match) => {\n const parsed = parseScheduleItemMarkdown(match[0] ?? '');\n\n const node = $createScheduleItemNode(\n parsed ?? {\n time: ((match[1] ?? '').replaceAll('.', ':').trim() || '').trim(),\n title: '',\n }\n );\n\n parentNode.replace(node);\n },\n};\n"],"mappings":";;;;;;;;;AAgBA,IAAM,sBACJ;AAEF,SAAgB,0BAA0B,MAKvC;CACD,OAAO;EACL,MAAM,KAAK,KAAK,KAAK;EACrB,OAAO,KAAK,MAAM,KAAK;EACvB,SAAS,KAAK,SAAS,KAAK,KAAK,KAAA;EACjC,aAAa,KAAK,aAAa,KAAK,KAAK,KAAA;CAC3C;AACF;AAEA,SAAgB,0BAA0B,UAAkB;CAC1D,MAAM,QAAQ,SAAS,MAAM,mBAAmB;CAChD,IAAI,CAAC,OAAO,OAAO;CAEnB,MAAM,QAAQ,MAAM,MAAM,GAAA,CAAI,WAAW,KAAK,GAAG,CAAC,CAAC,KAAK;CAExD,MAAM,SADQ,MAAM,MAAM,GAAA,CAAI,KAChB,CAAA,CAAK,MAAM,GAAG,CAAC,CAAC,KAAK,MAAM,EAAE,KAAK,CAAC;CAEjD,OAAO,0BAA0B;EAC/B;EACA,OAAO,MAAM,MAAM;EACnB,SAAS,MAAM,MAAM,KAAA;EACrB,aAAa,MAAM,MAAM,KAAA;CAC3B,CAAC;AACH;AAEA,SAAgB,2BAA2B,MAAgC;CACzE,MAAM,aAAa,0BAA0B,IAAI;CACjD,MAAM,QAAQ;EAAC,WAAW;EAAO,WAAW;EAAS,WAAW;CAAW,CAAC,CAAC,OAAO,OAAO;CAC3F,OAAO,OAAO,WAAW,KAAK,KAAK,MAAM,KAAK,KAAK;AACrD;AAEA,IAAa,4BAAgD;CAC3D,MAAM;CACN,cAAc,CAAC,gBAAgB;CAE/B,QAAQ;CAER,SAAS,SAAS;EAChB,IAAI,CAAC,oBAAoB,IAAI,GAAG,OAAO;EAEvC,OAAO,2BAA2B,KAAK,QAAQ,CAAC;CAClD;CAEA,UAAU,YAAY,WAAW,UAAU;EACzC,MAAM,SAAS,0BAA0B,MAAM,MAAM,EAAE;EAEvD,MAAM,OAAO,wBACX,UAAU;GACR,QAAQ,MAAM,MAAM,GAAA,CAAI,WAAW,KAAK,GAAG,CAAC,CAAC,KAAK,KAAK,GAAA,CAAI,KAAK;GAChE,OAAO;EACT,CACF;EAEA,WAAW,QAAQ,IAAI;CACzB;AACF"}
@@ -0,0 +1,5 @@
1
+ export type { ScheduleItemData, SerializedScheduleItemNode } from './ScheduleItemNode';
2
+ export { $createScheduleItemNode, $isScheduleItemNode, ScheduleItemNode } from './ScheduleItemNode';
3
+ export { SCHEDULE_ITEM_TRANSFORMER } from './ScheduleTransformer';
4
+ export { schedulePlugin } from './schedulePlugin';
5
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/nodes/schedule/index.ts"],"names":[],"mappings":"AAAA,YAAY,EAAE,gBAAgB,EAAE,0BAA0B,EAAE,MAAM,oBAAoB,CAAC;AACvF,OAAO,EAAE,uBAAuB,EAAE,mBAAmB,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AACpG,OAAO,EAAE,yBAAyB,EAAE,MAAM,uBAAuB,CAAC;AAClE,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC"}
@@ -0,0 +1,3 @@
1
+ import { ScriboPlugin } from '../../types';
2
+ export declare const schedulePlugin: ScriboPlugin;
3
+ //# sourceMappingURL=schedulePlugin.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schedulePlugin.d.ts","sourceRoot":"","sources":["../../../src/nodes/schedule/schedulePlugin.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAIhD,eAAO,MAAM,cAAc,EAAE,YAyB5B,CAAC"}
@@ -0,0 +1,33 @@
1
+ import { $createScheduleItemNode, ScheduleItemNode } from "./ScheduleItemNode.js";
2
+ import { SCHEDULE_ITEM_TRANSFORMER } from "./ScheduleTransformer.js";
3
+ import { $getSelection, $isRangeSelection } from "lexical";
4
+ import { $findMatchingParent } from "@lexical/utils";
5
+ //#region src/nodes/schedule/schedulePlugin.ts
6
+ var schedulePlugin = {
7
+ name: "schedule",
8
+ nodes: [ScheduleItemNode],
9
+ transformers: [SCHEDULE_ITEM_TRANSFORMER],
10
+ toolbarButtons: [{
11
+ key: "schedule-item",
12
+ label: "Schedule Item",
13
+ iconClass: "schedule",
14
+ onSelect: (editor) => {
15
+ editor.update(() => {
16
+ const selection = $getSelection();
17
+ if (!$isRangeSelection(selection)) return;
18
+ const anchor = selection.anchor.getNode();
19
+ const topLevel = $findMatchingParent(anchor, (n) => n.getParent()?.getType() === "root") ?? anchor;
20
+ const node = $createScheduleItemNode({
21
+ time: "",
22
+ title: ""
23
+ });
24
+ topLevel.insertAfter(node);
25
+ node.selectEnd();
26
+ });
27
+ }
28
+ }]
29
+ };
30
+ //#endregion
31
+ export { schedulePlugin };
32
+
33
+ //# sourceMappingURL=schedulePlugin.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schedulePlugin.js","names":[],"sources":["../../../src/nodes/schedule/schedulePlugin.ts"],"sourcesContent":["import { $findMatchingParent } from '@lexical/utils';\nimport { $getSelection, $isRangeSelection } from 'lexical';\n\nimport type { ScriboPlugin } from '../../types';\nimport { $createScheduleItemNode, ScheduleItemNode } from './ScheduleItemNode';\nimport { SCHEDULE_ITEM_TRANSFORMER } from './ScheduleTransformer';\n\nexport const schedulePlugin: ScriboPlugin = {\n name: 'schedule',\n nodes: [ScheduleItemNode],\n transformers: [SCHEDULE_ITEM_TRANSFORMER],\n toolbarButtons: [\n {\n key: 'schedule-item',\n label: 'Schedule Item',\n iconClass: 'schedule',\n onSelect: (editor) => {\n editor.update(() => {\n const selection = $getSelection();\n if (!$isRangeSelection(selection)) return;\n\n const anchor = selection.anchor.getNode();\n const topLevel =\n $findMatchingParent(anchor, (n) => n.getParent()?.getType() === 'root') ?? anchor;\n\n const node = $createScheduleItemNode({ time: '', title: '' });\n topLevel.insertAfter(node);\n node.selectEnd();\n });\n },\n },\n ],\n};\n"],"mappings":";;;;;AAOA,IAAa,iBAA+B;CAC1C,MAAM;CACN,OAAO,CAAC,gBAAgB;CACxB,cAAc,CAAC,yBAAyB;CACxC,gBAAgB,CACd;EACE,KAAK;EACL,OAAO;EACP,WAAW;EACX,WAAW,WAAW;GACpB,OAAO,aAAa;IAClB,MAAM,YAAY,cAAc;IAChC,IAAI,CAAC,kBAAkB,SAAS,GAAG;IAEnC,MAAM,SAAS,UAAU,OAAO,QAAQ;IACxC,MAAM,WACJ,oBAAoB,SAAS,MAAM,EAAE,UAAU,CAAC,EAAE,QAAQ,MAAM,MAAM,KAAK;IAE7E,MAAM,OAAO,wBAAwB;KAAE,MAAM;KAAI,OAAO;IAAG,CAAC;IAC5D,SAAS,YAAY,IAAI;IACzB,KAAK,UAAU;GACjB,CAAC;EACH;CACF,CACF;AACF"}
@@ -0,0 +1,3 @@
1
+ import { JSX } from 'react';
2
+ export default function LexicalAutoLinkPlugin(): JSX.Element;
3
+ //# sourceMappingURL=AutoLinkPlugin.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"AutoLinkPlugin.d.ts","sourceRoot":"","sources":["../../src/plugins/AutoLinkPlugin.tsx"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAGH,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,OAAO,CAAC;AAiBjC,MAAM,CAAC,OAAO,UAAU,qBAAqB,IAAI,GAAG,CAAC,OAAO,CAE3D"}
@@ -0,0 +1,22 @@
1
+ import { jsx } from "react/jsx-runtime";
2
+ import { AutoLinkPlugin, createLinkMatcherWithRegExp } from "@lexical/react/LexicalAutoLinkPlugin";
3
+ //#region src/plugins/AutoLinkPlugin.tsx
4
+ /**
5
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
6
+ *
7
+ * This source code is licensed under the MIT license found in the
8
+ * LICENSE file in the root directory of this source tree.
9
+ *
10
+ */
11
+ var MATCHERS = [createLinkMatcherWithRegExp(/((https?:\/\/(www\.)?)|(www\.))[-a-zA-Z0-9@:%._+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b([-a-zA-Z0-9()@:%_+.~#?&/=]*)(?<![-.+():%])/, (text) => {
12
+ return text.startsWith("http") ? text : `https://${text}`;
13
+ }), createLinkMatcherWithRegExp(/(([^<>()[\]\\.,;:\s@"]+(\.[^<>()[\]\\.,;:\s@"]+)*)|(".+"))@((\[\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\])|(([a-zA-Z\-\d]+\.)+[a-zA-Z]{2,}))/, (text) => {
14
+ return `mailto:${text}`;
15
+ })];
16
+ function LexicalAutoLinkPlugin() {
17
+ return /* @__PURE__ */ jsx(AutoLinkPlugin, { matchers: MATCHERS });
18
+ }
19
+ //#endregion
20
+ export { LexicalAutoLinkPlugin as default };
21
+
22
+ //# sourceMappingURL=AutoLinkPlugin.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"AutoLinkPlugin.js","names":[],"sources":["../../src/plugins/AutoLinkPlugin.tsx"],"sourcesContent":["/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n */\n\nimport { AutoLinkPlugin, createLinkMatcherWithRegExp } from '@lexical/react/LexicalAutoLinkPlugin';\nimport type { JSX } from 'react';\n\nconst URL_REGEX =\n /((https?:\\/\\/(www\\.)?)|(www\\.))[-a-zA-Z0-9@:%._+~#=]{1,256}\\.[a-zA-Z0-9()]{1,6}\\b([-a-zA-Z0-9()@:%_+.~#?&/=]*)(?<![-.+():%])/;\n\nconst EMAIL_REGEX =\n /(([^<>()[\\]\\\\.,;:\\s@\"]+(\\.[^<>()[\\]\\\\.,;:\\s@\"]+)*)|(\".+\"))@((\\[\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\])|(([a-zA-Z\\-\\d]+\\.)+[a-zA-Z]{2,}))/;\n\nconst MATCHERS = [\n createLinkMatcherWithRegExp(URL_REGEX, (text) => {\n return text.startsWith('http') ? text : `https://${text}`;\n }),\n createLinkMatcherWithRegExp(EMAIL_REGEX, (text) => {\n return `mailto:${text}`;\n }),\n];\n\nexport default function LexicalAutoLinkPlugin(): JSX.Element {\n return <AutoLinkPlugin matchers={MATCHERS} />;\n}\n"],"mappings":";;;;;;;;;;AAiBA,IAAM,WAAW,CACf,4BAA4B,iIAAY,SAAS;CAC/C,OAAO,KAAK,WAAW,MAAM,IAAI,OAAO,WAAW;AACrD,CAAC,GACD,4BAA4B,2IAAc,SAAS;CACjD,OAAO,UAAU;AACnB,CAAC,CACH;AAEA,SAAwB,wBAAqC;CAC3D,OAAO,oBAAC,gBAAD,EAAgB,UAAU,SAAW,CAAA;AAC9C"}
@@ -0,0 +1,7 @@
1
+ import { JSX, Dispatch } from 'react';
2
+ export default function FloatingLinkEditorPlugin({ anchorElem, isLinkEditMode, setIsLinkEditMode, }: {
3
+ anchorElem?: HTMLElement;
4
+ isLinkEditMode: boolean;
5
+ setIsLinkEditMode: Dispatch<boolean>;
6
+ }): JSX.Element | null;
7
+ //# sourceMappingURL=FloatingLinkEditorPlugin.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"FloatingLinkEditorPlugin.d.ts","sourceRoot":"","sources":["../../src/plugins/FloatingLinkEditorPlugin.tsx"],"names":[],"mappings":"AAEA;;;;;;GAMG;AACH,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,OAAO,CAAC;AAEjC,OAAO,gCAAgC,CAAC;AAqBxC,OAAO,EAAE,KAAK,QAAQ,EAA4C,MAAM,OAAO,CAAC;AA6YhF,MAAM,CAAC,OAAO,UAAU,wBAAwB,CAAC,EAC/C,UAAU,EACV,cAAc,EACd,iBAAiB,GAClB,EAAE;IACD,UAAU,CAAC,EAAE,WAAW,CAAC;IACzB,cAAc,EAAE,OAAO,CAAC;IACxB,iBAAiB,EAAE,QAAQ,CAAC,OAAO,CAAC,CAAC;CACtC,GAAG,GAAG,CAAC,OAAO,GAAG,IAAI,CAkBrB"}
@@ -0,0 +1,302 @@
1
+ /* empty css */
2
+ import { getSelectedNode } from "../utils/getSelectedNode.js";
3
+ import { setFloatingElemPositionForLinkEditor } from "../utils/setFloatingElemPositionForLinkEditor.js";
4
+ import { sanitizeUrl } from "../utils/url.js";
5
+ import { $getSelection, $isLineBreakNode, $isNodeSelection, $isRangeSelection, CLICK_COMMAND, COMMAND_PRIORITY_CRITICAL, COMMAND_PRIORITY_HIGH, COMMAND_PRIORITY_LOW, KEY_ESCAPE_COMMAND, SELECTION_CHANGE_COMMAND, getDOMSelection } from "lexical";
6
+ import { useCallback, useEffect, useRef, useState } from "react";
7
+ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
8
+ import { $createLinkNode, $isAutoLinkNode, $isLinkNode, TOGGLE_LINK_COMMAND } from "@lexical/link";
9
+ import { useLexicalComposerContext } from "@lexical/react/LexicalComposerContext";
10
+ import { $findMatchingParent, mergeRegister } from "@lexical/utils";
11
+ import { createPortal } from "react-dom";
12
+ //#region src/plugins/FloatingLinkEditorPlugin.tsx
13
+ function preventDefault(event) {
14
+ event.preventDefault();
15
+ }
16
+ function FloatingLinkEditor({ editor, isLink, setIsLink, anchorElem, isLinkEditMode, setIsLinkEditMode }) {
17
+ const editorRef = useRef(null);
18
+ const inputRef = useRef(null);
19
+ const [linkUrl, setLinkUrl] = useState("");
20
+ const [editedLinkUrl, setEditedLinkUrl] = useState("https://");
21
+ const [lastSelection, setLastSelection] = useState(null);
22
+ const $updateLinkEditor = useCallback(() => {
23
+ const selection = $getSelection();
24
+ if ($isRangeSelection(selection)) {
25
+ const node = getSelectedNode(selection);
26
+ const linkParent = $findMatchingParent(node, $isLinkNode);
27
+ if (linkParent) setLinkUrl(linkParent.getURL());
28
+ else if ($isLinkNode(node)) setLinkUrl(node.getURL());
29
+ else setLinkUrl("");
30
+ if (isLinkEditMode) setEditedLinkUrl(linkUrl);
31
+ } else if ($isNodeSelection(selection)) {
32
+ const nodes = selection.getNodes();
33
+ if (nodes.length > 0) {
34
+ const node = nodes[0];
35
+ const parent = node.getParent();
36
+ if ($isLinkNode(parent)) setLinkUrl(parent.getURL());
37
+ else if ($isLinkNode(node)) setLinkUrl(node.getURL());
38
+ else setLinkUrl("");
39
+ if (isLinkEditMode) setEditedLinkUrl(linkUrl);
40
+ }
41
+ }
42
+ const editorElem = editorRef.current;
43
+ const nativeSelection = getDOMSelection(editor._window);
44
+ const activeElement = document.activeElement;
45
+ if (editorElem === null) return;
46
+ const rootElement = editor.getRootElement();
47
+ if (selection !== null && rootElement !== null && editor.isEditable()) {
48
+ let domRect;
49
+ if ($isNodeSelection(selection)) {
50
+ const nodes = selection.getNodes();
51
+ if (nodes.length > 0) {
52
+ const element = editor.getElementByKey(nodes[0].getKey());
53
+ if (element) domRect = element.getBoundingClientRect();
54
+ }
55
+ } else if (nativeSelection !== null && rootElement.contains(nativeSelection.anchorNode)) domRect = nativeSelection.focusNode?.parentElement?.getBoundingClientRect();
56
+ if (domRect) {
57
+ domRect.y += 40;
58
+ setFloatingElemPositionForLinkEditor(domRect, editorElem, anchorElem);
59
+ }
60
+ setLastSelection(selection);
61
+ } else if (activeElement?.className !== "link-input") {
62
+ if (rootElement !== null) setFloatingElemPositionForLinkEditor(null, editorElem, anchorElem);
63
+ setLastSelection(null);
64
+ setIsLinkEditMode(false);
65
+ setLinkUrl("");
66
+ }
67
+ return true;
68
+ }, [
69
+ anchorElem,
70
+ editor,
71
+ setIsLinkEditMode,
72
+ isLinkEditMode,
73
+ linkUrl
74
+ ]);
75
+ useEffect(() => {
76
+ const scrollerElem = anchorElem.parentElement;
77
+ const update = () => {
78
+ editor.getEditorState().read(() => {
79
+ $updateLinkEditor();
80
+ });
81
+ };
82
+ window.addEventListener("resize", update);
83
+ if (scrollerElem) scrollerElem.addEventListener("scroll", update);
84
+ return () => {
85
+ window.removeEventListener("resize", update);
86
+ if (scrollerElem) scrollerElem.removeEventListener("scroll", update);
87
+ };
88
+ }, [
89
+ anchorElem.parentElement,
90
+ editor,
91
+ $updateLinkEditor
92
+ ]);
93
+ useEffect(() => {
94
+ return mergeRegister(editor.registerUpdateListener(({ editorState }) => {
95
+ editorState.read(() => {
96
+ $updateLinkEditor();
97
+ });
98
+ }), editor.registerCommand(SELECTION_CHANGE_COMMAND, () => {
99
+ $updateLinkEditor();
100
+ return true;
101
+ }, COMMAND_PRIORITY_LOW), editor.registerCommand(KEY_ESCAPE_COMMAND, () => {
102
+ if (isLink) {
103
+ setIsLink(false);
104
+ return true;
105
+ }
106
+ return false;
107
+ }, COMMAND_PRIORITY_HIGH));
108
+ }, [
109
+ editor,
110
+ $updateLinkEditor,
111
+ setIsLink,
112
+ isLink
113
+ ]);
114
+ useEffect(() => {
115
+ editor.getEditorState().read(() => {
116
+ $updateLinkEditor();
117
+ });
118
+ }, [editor, $updateLinkEditor]);
119
+ useEffect(() => {
120
+ if (isLinkEditMode && inputRef.current) inputRef.current.focus();
121
+ }, [isLinkEditMode, isLink]);
122
+ useEffect(() => {
123
+ const editorElement = editorRef.current;
124
+ if (editorElement === null) return;
125
+ const handleBlur = (event) => {
126
+ if (!editorElement.contains(event.relatedTarget) && isLink) {
127
+ setIsLink(false);
128
+ setIsLinkEditMode(false);
129
+ }
130
+ };
131
+ editorElement.addEventListener("focusout", handleBlur);
132
+ return () => {
133
+ editorElement.removeEventListener("focusout", handleBlur);
134
+ };
135
+ }, [
136
+ editorRef,
137
+ setIsLink,
138
+ setIsLinkEditMode,
139
+ isLink
140
+ ]);
141
+ const monitorInputInteraction = (event) => {
142
+ if (event.key === "Enter") handleLinkSubmission(event);
143
+ else if (event.key === "Escape") {
144
+ event.preventDefault();
145
+ setIsLinkEditMode(false);
146
+ }
147
+ };
148
+ const handleLinkSubmission = (event) => {
149
+ event.preventDefault();
150
+ if (lastSelection !== null) {
151
+ if (linkUrl !== "") editor.update(() => {
152
+ editor.dispatchCommand(TOGGLE_LINK_COMMAND, sanitizeUrl(editedLinkUrl));
153
+ const selection = $getSelection();
154
+ if ($isRangeSelection(selection)) {
155
+ const parent = getSelectedNode(selection).getParent();
156
+ if ($isAutoLinkNode(parent)) {
157
+ const linkNode = $createLinkNode(parent.getURL(), {
158
+ rel: parent.__rel,
159
+ target: parent.__target,
160
+ title: parent.__title
161
+ });
162
+ parent.replace(linkNode, true);
163
+ }
164
+ }
165
+ });
166
+ setEditedLinkUrl("https://");
167
+ setIsLinkEditMode(false);
168
+ }
169
+ };
170
+ return /* @__PURE__ */ jsxs("div", {
171
+ ref: editorRef,
172
+ className: "link-editor",
173
+ children: [isLink && isLinkEditMode && /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx("input", {
174
+ ref: inputRef,
175
+ className: "link-input",
176
+ value: editedLinkUrl,
177
+ onChange: (event) => {
178
+ setEditedLinkUrl(event.target.value);
179
+ },
180
+ onKeyDown: (event) => {
181
+ monitorInputInteraction(event);
182
+ }
183
+ }), /* @__PURE__ */ jsxs("div", { children: [/* @__PURE__ */ jsx("div", {
184
+ className: "link-cancel",
185
+ role: "button",
186
+ tabIndex: 0,
187
+ onMouseDown: preventDefault,
188
+ onClick: () => {
189
+ setIsLinkEditMode(false);
190
+ }
191
+ }), /* @__PURE__ */ jsx("div", {
192
+ className: "link-confirm",
193
+ role: "button",
194
+ tabIndex: 0,
195
+ onMouseDown: preventDefault,
196
+ onClick: handleLinkSubmission
197
+ })] })] }), isLink && !isLinkEditMode && /* @__PURE__ */ jsxs("div", {
198
+ className: "link-view",
199
+ children: [
200
+ /* @__PURE__ */ jsx("a", {
201
+ href: sanitizeUrl(linkUrl),
202
+ target: "_blank",
203
+ rel: "noopener noreferrer",
204
+ children: linkUrl
205
+ }),
206
+ /* @__PURE__ */ jsx("div", {
207
+ className: "link-edit",
208
+ role: "button",
209
+ tabIndex: 0,
210
+ onMouseDown: preventDefault,
211
+ onClick: (event) => {
212
+ event.preventDefault();
213
+ setEditedLinkUrl(linkUrl);
214
+ setIsLinkEditMode(true);
215
+ }
216
+ }),
217
+ /* @__PURE__ */ jsx("div", {
218
+ className: "link-trash",
219
+ role: "button",
220
+ tabIndex: 0,
221
+ onMouseDown: preventDefault,
222
+ onClick: () => {
223
+ editor.dispatchCommand(TOGGLE_LINK_COMMAND, null);
224
+ }
225
+ })
226
+ ]
227
+ })]
228
+ });
229
+ }
230
+ function useFloatingLinkEditorToolbar(editor, anchorElem, isLinkEditMode, setIsLinkEditMode) {
231
+ const [activeEditor, setActiveEditor] = useState(editor);
232
+ const [isLink, setIsLink] = useState(false);
233
+ useEffect(() => {
234
+ function $updateToolbar() {
235
+ const selection = $getSelection();
236
+ if ($isRangeSelection(selection)) {
237
+ const focusNode = getSelectedNode(selection);
238
+ const focusLinkNode = $findMatchingParent(focusNode, $isLinkNode);
239
+ const focusAutoLinkNode = $findMatchingParent(focusNode, $isAutoLinkNode);
240
+ if (!(focusLinkNode || focusAutoLinkNode)) {
241
+ setIsLink(false);
242
+ return;
243
+ }
244
+ if (!selection.getNodes().filter((node) => !$isLineBreakNode(node)).find((node) => {
245
+ const linkNode = $findMatchingParent(node, $isLinkNode);
246
+ const autoLinkNode = $findMatchingParent(node, $isAutoLinkNode);
247
+ return focusLinkNode && !focusLinkNode.is(linkNode) || linkNode && !linkNode.is(focusLinkNode) || focusAutoLinkNode && !focusAutoLinkNode.is(autoLinkNode) || autoLinkNode && (!autoLinkNode.is(focusAutoLinkNode) || autoLinkNode.getIsUnlinked());
248
+ })) setIsLink(true);
249
+ else setIsLink(false);
250
+ } else if ($isNodeSelection(selection)) {
251
+ const nodes = selection.getNodes();
252
+ if (nodes.length === 0) {
253
+ setIsLink(false);
254
+ return;
255
+ }
256
+ const node = nodes[0];
257
+ const parent = node.getParent();
258
+ if ($isLinkNode(parent) || $isLinkNode(node)) setIsLink(true);
259
+ else setIsLink(false);
260
+ }
261
+ }
262
+ return mergeRegister(editor.registerUpdateListener(({ editorState }) => {
263
+ editorState.read(() => {
264
+ $updateToolbar();
265
+ });
266
+ }), editor.registerCommand(SELECTION_CHANGE_COMMAND, (_payload, newEditor) => {
267
+ $updateToolbar();
268
+ setActiveEditor(newEditor);
269
+ return false;
270
+ }, COMMAND_PRIORITY_CRITICAL), editor.registerCommand(CLICK_COMMAND, (payload) => {
271
+ const selection = $getSelection();
272
+ if ($isRangeSelection(selection)) {
273
+ const node = getSelectedNode(selection);
274
+ const linkNode = $findMatchingParent(node, $isLinkNode);
275
+ if ($isLinkNode(linkNode) && (payload.metaKey || payload.ctrlKey)) {
276
+ window.open(linkNode.getURL(), "_blank");
277
+ return true;
278
+ }
279
+ }
280
+ return false;
281
+ }, COMMAND_PRIORITY_LOW));
282
+ }, [editor]);
283
+ return createPortal(/* @__PURE__ */ jsx(FloatingLinkEditor, {
284
+ editor: activeEditor,
285
+ isLink,
286
+ anchorElem,
287
+ setIsLink,
288
+ isLinkEditMode,
289
+ setIsLinkEditMode
290
+ }), anchorElem);
291
+ }
292
+ function FloatingLinkEditorPlugin({ anchorElem, isLinkEditMode, setIsLinkEditMode }) {
293
+ const [editor] = useLexicalComposerContext();
294
+ const defaultAnchorElem = typeof document !== "undefined" ? document.body : null;
295
+ const effectiveAnchorElem = anchorElem ?? defaultAnchorElem;
296
+ if (!effectiveAnchorElem) return null;
297
+ return useFloatingLinkEditorToolbar(editor, effectiveAnchorElem, isLinkEditMode, setIsLinkEditMode);
298
+ }
299
+ //#endregion
300
+ export { FloatingLinkEditorPlugin as default };
301
+
302
+ //# sourceMappingURL=FloatingLinkEditorPlugin2.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"FloatingLinkEditorPlugin2.js","names":[],"sources":["../../src/plugins/FloatingLinkEditorPlugin.tsx"],"sourcesContent":["// @ts-nocheck\n// https://github.com/facebook/lexical/blob/main/packages/lexical-playground/src/plugins/FloatingLinkEditorPlugin/index.tsx\n/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n */\nimport type { JSX } from 'react';\n\nimport './FloatingLinkEditorPlugin.css';\n\nimport { $createLinkNode, $isAutoLinkNode, $isLinkNode, TOGGLE_LINK_COMMAND } from '@lexical/link';\nimport { useLexicalComposerContext } from '@lexical/react/LexicalComposerContext';\nimport { $findMatchingParent, mergeRegister } from '@lexical/utils';\nimport {\n $getSelection,\n $isLineBreakNode,\n $isNodeSelection,\n $isRangeSelection,\n type BaseSelection,\n CLICK_COMMAND,\n COMMAND_PRIORITY_CRITICAL,\n COMMAND_PRIORITY_HIGH,\n COMMAND_PRIORITY_LOW,\n getDOMSelection,\n KEY_ESCAPE_COMMAND,\n type LexicalEditor,\n SELECTION_CHANGE_COMMAND,\n} from 'lexical';\nimport type * as React from 'react';\nimport { type Dispatch, useCallback, useEffect, useRef, useState } from 'react';\nimport { createPortal } from 'react-dom';\n\nimport { getSelectedNode } from '../utils/getSelectedNode';\nimport { setFloatingElemPositionForLinkEditor } from '../utils/setFloatingElemPositionForLinkEditor';\nimport { sanitizeUrl } from '../utils/url';\n\nfunction preventDefault(\n event: React.KeyboardEvent<HTMLInputElement> | React.MouseEvent<HTMLElement>\n): void {\n event.preventDefault();\n}\n\nfunction FloatingLinkEditor({\n editor,\n isLink,\n setIsLink,\n anchorElem,\n isLinkEditMode,\n setIsLinkEditMode,\n}: Readonly<{\n editor: LexicalEditor;\n isLink: boolean;\n setIsLink: Dispatch<boolean>;\n anchorElem: HTMLElement;\n isLinkEditMode: boolean;\n setIsLinkEditMode: Dispatch<boolean>;\n}>): JSX.Element {\n const editorRef = useRef<HTMLDivElement | null>(null);\n const inputRef = useRef<HTMLInputElement>(null);\n const [linkUrl, setLinkUrl] = useState('');\n const [editedLinkUrl, setEditedLinkUrl] = useState('https://');\n const [lastSelection, setLastSelection] = useState<BaseSelection | null>(null);\n\n const $updateLinkEditor = useCallback(() => {\n const selection = $getSelection();\n if ($isRangeSelection(selection)) {\n const node = getSelectedNode(selection);\n const linkParent = $findMatchingParent(node, $isLinkNode);\n\n if (linkParent) {\n setLinkUrl(linkParent.getURL());\n } else if ($isLinkNode(node)) {\n setLinkUrl(node.getURL());\n } else {\n setLinkUrl('');\n }\n if (isLinkEditMode) {\n setEditedLinkUrl(linkUrl);\n }\n } else if ($isNodeSelection(selection)) {\n const nodes = selection.getNodes();\n if (nodes.length > 0) {\n const node = nodes[0];\n const parent = node.getParent();\n if ($isLinkNode(parent)) {\n setLinkUrl(parent.getURL());\n } else if ($isLinkNode(node)) {\n setLinkUrl(node.getURL());\n } else {\n setLinkUrl('');\n }\n if (isLinkEditMode) {\n setEditedLinkUrl(linkUrl);\n }\n }\n }\n\n const editorElem = editorRef.current;\n const nativeSelection = getDOMSelection(editor._window);\n const activeElement = document.activeElement;\n\n if (editorElem === null) {\n return;\n }\n\n const rootElement = editor.getRootElement();\n\n if (selection !== null && rootElement !== null && editor.isEditable()) {\n let domRect: DOMRect | undefined;\n\n if ($isNodeSelection(selection)) {\n const nodes = selection.getNodes();\n if (nodes.length > 0) {\n const element = editor.getElementByKey(nodes[0].getKey());\n if (element) {\n domRect = element.getBoundingClientRect();\n }\n }\n } else if (nativeSelection !== null && rootElement.contains(nativeSelection.anchorNode)) {\n domRect = nativeSelection.focusNode?.parentElement?.getBoundingClientRect();\n }\n\n if (domRect) {\n domRect.y += 40;\n setFloatingElemPositionForLinkEditor(domRect, editorElem, anchorElem);\n }\n setLastSelection(selection);\n } else if (activeElement?.className !== 'link-input') {\n if (rootElement !== null) {\n setFloatingElemPositionForLinkEditor(null, editorElem, anchorElem);\n }\n setLastSelection(null);\n setIsLinkEditMode(false);\n setLinkUrl('');\n }\n\n return true;\n }, [anchorElem, editor, setIsLinkEditMode, isLinkEditMode, linkUrl]);\n\n useEffect(() => {\n const scrollerElem = anchorElem.parentElement;\n\n const update = () => {\n editor.getEditorState().read(() => {\n $updateLinkEditor();\n });\n };\n\n window.addEventListener('resize', update);\n\n if (scrollerElem) {\n scrollerElem.addEventListener('scroll', update);\n }\n\n return () => {\n window.removeEventListener('resize', update);\n\n if (scrollerElem) {\n scrollerElem.removeEventListener('scroll', update);\n }\n };\n }, [anchorElem.parentElement, editor, $updateLinkEditor]);\n\n useEffect(() => {\n return mergeRegister(\n editor.registerUpdateListener(({ editorState }) => {\n editorState.read(() => {\n $updateLinkEditor();\n });\n }),\n\n editor.registerCommand(\n SELECTION_CHANGE_COMMAND,\n () => {\n $updateLinkEditor();\n return true;\n },\n COMMAND_PRIORITY_LOW\n ),\n editor.registerCommand(\n KEY_ESCAPE_COMMAND,\n () => {\n if (isLink) {\n setIsLink(false);\n return true;\n }\n return false;\n },\n COMMAND_PRIORITY_HIGH\n )\n );\n }, [editor, $updateLinkEditor, setIsLink, isLink]);\n\n useEffect(() => {\n editor.getEditorState().read(() => {\n $updateLinkEditor();\n });\n }, [editor, $updateLinkEditor]);\n\n useEffect(() => {\n if (isLinkEditMode && inputRef.current) {\n inputRef.current.focus();\n }\n }, [isLinkEditMode, isLink]);\n\n useEffect(() => {\n const editorElement = editorRef.current;\n if (editorElement === null) {\n return;\n }\n const handleBlur = (event: FocusEvent) => {\n if (!editorElement.contains(event.relatedTarget as Element) && isLink) {\n setIsLink(false);\n setIsLinkEditMode(false);\n }\n };\n editorElement.addEventListener('focusout', handleBlur);\n return () => {\n editorElement.removeEventListener('focusout', handleBlur);\n };\n }, [editorRef, setIsLink, setIsLinkEditMode, isLink]);\n\n const monitorInputInteraction = (event: React.KeyboardEvent<HTMLInputElement>) => {\n if (event.key === 'Enter') {\n handleLinkSubmission(event);\n } else if (event.key === 'Escape') {\n event.preventDefault();\n setIsLinkEditMode(false);\n }\n };\n\n const handleLinkSubmission = (\n event: React.KeyboardEvent<HTMLInputElement> | React.MouseEvent<HTMLElement>\n ) => {\n event.preventDefault();\n if (lastSelection !== null) {\n if (linkUrl !== '') {\n editor.update(() => {\n editor.dispatchCommand(TOGGLE_LINK_COMMAND, sanitizeUrl(editedLinkUrl));\n const selection = $getSelection();\n if ($isRangeSelection(selection)) {\n const parent = getSelectedNode(selection).getParent();\n if ($isAutoLinkNode(parent)) {\n const linkNode = $createLinkNode(parent.getURL(), {\n rel: parent.__rel,\n target: parent.__target,\n title: parent.__title,\n });\n parent.replace(linkNode, true);\n }\n }\n });\n }\n setEditedLinkUrl('https://');\n setIsLinkEditMode(false);\n }\n };\n\n return (\n <div ref={editorRef} className=\"link-editor\">\n {isLink && isLinkEditMode && (\n <>\n <input\n ref={inputRef}\n className=\"link-input\"\n value={editedLinkUrl}\n onChange={(event) => {\n setEditedLinkUrl(event.target.value);\n }}\n onKeyDown={(event) => {\n monitorInputInteraction(event);\n }}\n />\n <div>\n <div\n className=\"link-cancel\"\n role=\"button\"\n tabIndex={0}\n onMouseDown={preventDefault}\n onClick={() => {\n setIsLinkEditMode(false);\n }}\n />\n\n <div\n className=\"link-confirm\"\n role=\"button\"\n tabIndex={0}\n onMouseDown={preventDefault}\n onClick={handleLinkSubmission}\n />\n </div>\n </>\n )}\n {isLink && !isLinkEditMode && (\n <div className=\"link-view\">\n <a href={sanitizeUrl(linkUrl)} target=\"_blank\" rel=\"noopener noreferrer\">\n {linkUrl}\n </a>\n <div\n className=\"link-edit\"\n role=\"button\"\n tabIndex={0}\n onMouseDown={preventDefault}\n onClick={(event) => {\n event.preventDefault();\n setEditedLinkUrl(linkUrl);\n setIsLinkEditMode(true);\n }}\n />\n <div\n className=\"link-trash\"\n role=\"button\"\n tabIndex={0}\n onMouseDown={preventDefault}\n onClick={() => {\n editor.dispatchCommand(TOGGLE_LINK_COMMAND, null);\n }}\n />\n </div>\n )}\n </div>\n );\n}\n\nfunction useFloatingLinkEditorToolbar(\n editor: LexicalEditor,\n anchorElem: HTMLElement,\n isLinkEditMode: boolean,\n setIsLinkEditMode: Dispatch<boolean>\n): JSX.Element | null {\n const [activeEditor, setActiveEditor] = useState(editor);\n const [isLink, setIsLink] = useState(false);\n\n useEffect(() => {\n function $updateToolbar() {\n const selection = $getSelection();\n if ($isRangeSelection(selection)) {\n const focusNode = getSelectedNode(selection);\n const focusLinkNode = $findMatchingParent(focusNode, $isLinkNode);\n const focusAutoLinkNode = $findMatchingParent(focusNode, $isAutoLinkNode);\n if (!(focusLinkNode || focusAutoLinkNode)) {\n setIsLink(false);\n return;\n }\n const badNode = selection\n .getNodes()\n .filter((node) => !$isLineBreakNode(node))\n .find((node) => {\n const linkNode = $findMatchingParent(node, $isLinkNode);\n const autoLinkNode = $findMatchingParent(node, $isAutoLinkNode);\n return (\n (focusLinkNode && !focusLinkNode.is(linkNode)) ||\n (linkNode && !linkNode.is(focusLinkNode)) ||\n (focusAutoLinkNode && !focusAutoLinkNode.is(autoLinkNode)) ||\n (autoLinkNode &&\n (!autoLinkNode.is(focusAutoLinkNode) || autoLinkNode.getIsUnlinked()))\n );\n });\n if (!badNode) {\n setIsLink(true);\n } else {\n setIsLink(false);\n }\n } else if ($isNodeSelection(selection)) {\n const nodes = selection.getNodes();\n if (nodes.length === 0) {\n setIsLink(false);\n return;\n }\n const node = nodes[0];\n const parent = node.getParent();\n if ($isLinkNode(parent) || $isLinkNode(node)) {\n setIsLink(true);\n } else {\n setIsLink(false);\n }\n }\n }\n return mergeRegister(\n editor.registerUpdateListener(({ editorState }) => {\n editorState.read(() => {\n $updateToolbar();\n });\n }),\n editor.registerCommand(\n SELECTION_CHANGE_COMMAND,\n (_payload, newEditor) => {\n $updateToolbar();\n setActiveEditor(newEditor);\n return false;\n },\n COMMAND_PRIORITY_CRITICAL\n ),\n editor.registerCommand(\n CLICK_COMMAND,\n (payload) => {\n const selection = $getSelection();\n if ($isRangeSelection(selection)) {\n const node = getSelectedNode(selection);\n const linkNode = $findMatchingParent(node, $isLinkNode);\n if ($isLinkNode(linkNode) && (payload.metaKey || payload.ctrlKey)) {\n window.open(linkNode.getURL(), '_blank');\n return true;\n }\n }\n return false;\n },\n COMMAND_PRIORITY_LOW\n )\n );\n }, [editor]);\n\n return createPortal(\n <FloatingLinkEditor\n editor={activeEditor}\n isLink={isLink}\n anchorElem={anchorElem}\n setIsLink={setIsLink}\n isLinkEditMode={isLinkEditMode}\n setIsLinkEditMode={setIsLinkEditMode}\n />,\n anchorElem\n );\n}\n\nexport default function FloatingLinkEditorPlugin({\n anchorElem,\n isLinkEditMode,\n setIsLinkEditMode,\n}: {\n anchorElem?: HTMLElement;\n isLinkEditMode: boolean;\n setIsLinkEditMode: Dispatch<boolean>;\n}): JSX.Element | null {\n const [editor] = useLexicalComposerContext();\n\n // Use document.body as default, but only in browser environment\n const defaultAnchorElem = typeof document !== 'undefined' ? document.body : null;\n const effectiveAnchorElem = anchorElem ?? defaultAnchorElem;\n\n // Don't render if we don't have a valid anchor element\n if (!effectiveAnchorElem) {\n return null;\n }\n\n return useFloatingLinkEditorToolbar(\n editor,\n effectiveAnchorElem,\n isLinkEditMode,\n setIsLinkEditMode\n );\n}\n"],"mappings":"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"}
@@ -0,0 +1,26 @@
1
+ import { EditorState, LexicalEditor } from 'lexical';
2
+ export type HistoryStateEntry = {
3
+ editor: LexicalEditor;
4
+ editorState: EditorState;
5
+ };
6
+ export type HistoryState = {
7
+ current: null | HistoryStateEntry;
8
+ redoStack: Array<HistoryStateEntry>;
9
+ undoStack: Array<HistoryStateEntry>;
10
+ };
11
+ /**
12
+ * Registers necessary listeners to manage undo/redo history stack and related editor commands.
13
+ * It returns `unregister` callback that cleans up all listeners and should be called on editor unmount.
14
+ * @param editor - The lexical editor.
15
+ * @param historyState - The history state, containing the current state and the undo/redo stack.
16
+ * @param delay - The time (in milliseconds) the editor should delay generating a new history stack,
17
+ * instead of merging the current changes with the current stack.
18
+ * @returns The listeners cleanup callback function.
19
+ */
20
+ export declare function registerHistory(editor: LexicalEditor, historyState: HistoryState, delay: number): () => void;
21
+ /**
22
+ * Creates an empty history state.
23
+ * @returns - The empty history state, as an object.
24
+ */
25
+ export declare function createEmptyHistoryState(): HistoryState;
26
+ //# sourceMappingURL=HistoryPlugin.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"HistoryPlugin.d.ts","sourceRoot":"","sources":["../../src/plugins/HistoryPlugin.tsx"],"names":[],"mappings":"AAAA,+BAA+B;AAC/B;;;;;;GAMG;AAGH,OAAO,KAAK,EAAE,WAAW,EAAE,aAAa,EAAwB,MAAM,SAAS,CAAC;AA0BhF,MAAM,MAAM,iBAAiB,GAAG;IAC9B,MAAM,EAAE,aAAa,CAAC;IACtB,WAAW,EAAE,WAAW,CAAC;CAC1B,CAAC;AACF,MAAM,MAAM,YAAY,GAAG;IACzB,OAAO,EAAE,IAAI,GAAG,iBAAiB,CAAC;IAClC,SAAS,EAAE,KAAK,CAAC,iBAAiB,CAAC,CAAC;IACpC,SAAS,EAAE,KAAK,CAAC,iBAAiB,CAAC,CAAC;CACrC,CAAC;AA0UF;;;;;;;;GAQG;AACH,wBAAgB,eAAe,CAC7B,MAAM,EAAE,aAAa,EACrB,YAAY,EAAE,YAAY,EAC1B,KAAK,EAAE,MAAM,GACZ,MAAM,IAAI,CAqGZ;AAED;;;GAGG;AACH,wBAAgB,uBAAuB,IAAI,YAAY,CAMtD"}
@@ -0,0 +1,3 @@
1
+ import { JSX } from 'react';
2
+ export default function LinkPlugin(): JSX.Element;
3
+ //# sourceMappingURL=LinkPlugin.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"LinkPlugin.d.ts","sourceRoot":"","sources":["../../src/plugins/LinkPlugin.tsx"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAGH,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,OAAO,CAAC;AAIjC,MAAM,CAAC,OAAO,UAAU,UAAU,IAAI,GAAG,CAAC,OAAO,CAEhD"}
@@ -0,0 +1,18 @@
1
+ import { validateUrl } from "../utils/url.js";
2
+ import { jsx } from "react/jsx-runtime";
3
+ import { LinkPlugin } from "@lexical/react/LexicalLinkPlugin";
4
+ //#region src/plugins/LinkPlugin.tsx
5
+ /**
6
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
7
+ *
8
+ * This source code is licensed under the MIT license found in the
9
+ * LICENSE file in the root directory of this source tree.
10
+ *
11
+ */
12
+ function LinkPlugin$1() {
13
+ return /* @__PURE__ */ jsx(LinkPlugin, { validateUrl });
14
+ }
15
+ //#endregion
16
+ export { LinkPlugin$1 as default };
17
+
18
+ //# sourceMappingURL=LinkPlugin.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"LinkPlugin.js","names":[],"sources":["../../src/plugins/LinkPlugin.tsx"],"sourcesContent":["/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n */\n\nimport { LinkPlugin as LexicalLinkPlugin } from '@lexical/react/LexicalLinkPlugin';\nimport type { JSX } from 'react';\n\nimport { validateUrl } from '../utils/url';\n\nexport default function LinkPlugin(): JSX.Element {\n return <LexicalLinkPlugin validateUrl={validateUrl} />;\n}\n"],"mappings":";;;;;;;;;;;AAaA,SAAwB,eAA0B;CAChD,OAAO,oBAAC,YAAD,EAAgC,YAAc,CAAA;AACvD"}
@@ -0,0 +1,7 @@
1
+ import { JSX, Dispatch } from 'react';
2
+ import { ScriboToolbarButton } from '../types';
3
+ export default function ToolbarPlugin({ setIsLinkEditMode, toolbarButtons, }: Readonly<{
4
+ setIsLinkEditMode: Dispatch<boolean>;
5
+ toolbarButtons?: ScriboToolbarButton[];
6
+ }>): JSX.Element;
7
+ //# sourceMappingURL=ToolbarPlugin.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ToolbarPlugin.d.ts","sourceRoot":"","sources":["../../src/plugins/ToolbarPlugin.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AA4CH,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,OAAO,CAAC;AACjC,OAAO,EAAE,KAAK,QAAQ,EAAoC,MAAM,OAAO,CAAC;AACxE,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,UAAU,CAAC;AAiMpD,MAAM,CAAC,OAAO,UAAU,aAAa,CAAC,EACpC,iBAAiB,EACjB,cAAmB,GACpB,EAAE,QAAQ,CAAC;IACV,iBAAiB,EAAE,QAAQ,CAAC,OAAO,CAAC,CAAC;IACrC,cAAc,CAAC,EAAE,mBAAmB,EAAE,CAAC;CACxC,CAAC,GAAG,GAAG,CAAC,OAAO,CAqQf"}