@crystallize/design-system 1.21.0 → 1.21.2

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.
@@ -0,0 +1,3227 @@
1
+ import {
2
+ ActionMenu,
3
+ Button,
4
+ Dialog,
5
+ DropdownMenu,
6
+ Icon,
7
+ IconButton,
8
+ InputWithLabel
9
+ } from "./chunk-PB47BT3T.mjs";
10
+ import "./chunk-NIH5ZMPE.mjs";
11
+
12
+ // src/rich-text-editor/rich-text-editor.tsx
13
+ import { useEffect as useEffect11, useRef as useRef5, useState as useState10 } from "react";
14
+ import { AutoFocusPlugin } from "@lexical/react/LexicalAutoFocusPlugin";
15
+ import { ClearEditorPlugin } from "@lexical/react/LexicalClearEditorPlugin";
16
+ import { LexicalComposer } from "@lexical/react/LexicalComposer";
17
+ import LexicalErrorBoundary from "@lexical/react/LexicalErrorBoundary";
18
+ import { HistoryPlugin } from "@lexical/react/LexicalHistoryPlugin";
19
+ import { HorizontalRulePlugin } from "@lexical/react/LexicalHorizontalRulePlugin";
20
+ import { ListPlugin } from "@lexical/react/LexicalListPlugin";
21
+ import { OnChangePlugin } from "@lexical/react/LexicalOnChangePlugin";
22
+ import { RichTextPlugin } from "@lexical/react/LexicalRichTextPlugin";
23
+ import { TabIndentationPlugin } from "@lexical/react/LexicalTabIndentationPlugin";
24
+ import { TablePlugin } from "@lexical/react/LexicalTablePlugin";
25
+ import { useLexicalComposerContext as useLexicalComposerContext12 } from "@lexical/react/LexicalComposerContext";
26
+ import { ContentEditable } from "@lexical/react/LexicalContentEditable";
27
+
28
+ // src/rich-text-editor/context/SharedHistoryContext.tsx
29
+ import { createContext, useContext, useMemo } from "react";
30
+ import { createEmptyHistoryState } from "@lexical/react/LexicalHistoryPlugin";
31
+ import { jsx } from "react/jsx-runtime";
32
+ var Context = createContext({});
33
+ var SharedHistoryContext = ({ children }) => {
34
+ const historyContext = useMemo(() => ({ historyState: createEmptyHistoryState() }), []);
35
+ return /* @__PURE__ */ jsx(Context.Provider, {
36
+ value: historyContext,
37
+ children
38
+ });
39
+ };
40
+ var useSharedHistoryContext = () => {
41
+ return useContext(Context);
42
+ };
43
+
44
+ // src/rich-text-editor/i18n/index.tsx
45
+ import { createContext as createContext2, useContext as useContext2 } from "react";
46
+
47
+ // src/rich-text-editor/i18n/translations/en.ts
48
+ var translations = {
49
+ actionClearTextFormatting: "Clear text formatting",
50
+ actionTextFormattingOptions: "Formatting options for additional text styles",
51
+ actionFormatAsStrongLabel: "Format text as bold",
52
+ actionFormatAsStrongTitle: "Bold (Ctrl+B)",
53
+ actionFormatAsStrongTitleApple: "Bold (\u2318B)",
54
+ actionFormatAsEmphasizedLabel: "Format text as italics",
55
+ actionFormatAsEmphasizedTitle: "Italic (Ctrl+I)",
56
+ actionFormatAsEmphasizedTitleApple: "Italic (\u2318I)",
57
+ actionFormatAsUnderlinedLabel: "Underline text",
58
+ actionFormatAsUnderlinedTitle: "Underlined (Ctrl+U)",
59
+ actionFormatAsUnderlinedTitleApple: "Underlined (\u2318U)",
60
+ actionFormatWithStrikethroughLabel: "Format text with a strikethrough",
61
+ actionFormatWithStrikethroughTitle: "Strikethrough",
62
+ actionFormatWithSubscriptLabel: "Format text as subscript",
63
+ actionFormatWithSubscriptTitle: "Subscript",
64
+ actionFormatWithSuperscriptLabel: "Format text as superscript",
65
+ actionFormatWithSuperscriptTitle: "Superscript",
66
+ actionFormatClear: "Clear formatting",
67
+ actionInsertCodeBlock: "Insert code block",
68
+ actionInsertlink: "Insert link",
69
+ actionCopyJSON: "Copy JSON",
70
+ actionCopyCode: "Copy code",
71
+ actionClear: "Clear editor",
72
+ actionFormatCode: "Format code with Prettier",
73
+ actionTableInsertRowsAbove: "Insert row above",
74
+ actionTableInsertRowsAbove_plural: "Insert {{rows}} rows above",
75
+ actionTableInsertRowsBelow: "Insert row below",
76
+ actionTableInsertRowsBelow_plural: "Insert {{rows}} rows below",
77
+ actionTableInsertColumnsBefore: "Insert column left",
78
+ actionTableInsertColumnsBefore_plural: "Insert {{columns}} columns left",
79
+ actionTableInsertColumnsAfter: "Insert column right",
80
+ actionTableInsertColumnsAfter_plural: "Insert {{columns}} columns right",
81
+ actionTableAddRowHeader: "Add row header",
82
+ actionTableRemoveRowHeader: "Remove row header",
83
+ actionTableAddColumnHeader: "Add column header",
84
+ actionTableRemoveColumnHeader: "Remove column header",
85
+ actionTableDeleteColumn: "Delete column",
86
+ actionTableDeleteRow: "Delete row",
87
+ actionTableDeleteTable: "Delete table",
88
+ actionTableOpenOptions: "Open table options",
89
+ actionUndoLabel: "Undo",
90
+ actionUndoTitle: "Undo (Ctrl+Z)",
91
+ actionUndoTitleApple: "Undo (\u2318Z)",
92
+ actionRedoLabel: "Undo",
93
+ actionRedoTitle: "Undo (Ctrl+Y)",
94
+ actionRedoTitleApple: "Redo (\u2318Y)",
95
+ codeSelectLanguage: "Select language",
96
+ linkEditorLink: "Link",
97
+ linkEditorRel: "Rel",
98
+ linkEditorTarget: "Target",
99
+ linkEditorCommit: "Done",
100
+ linkEditorEdit: "Edit",
101
+ linkPreviewReplaceTextWithTitle: "Replace link text with its title",
102
+ horizontalRule: "Horizontal rule",
103
+ table: "Table",
104
+ insertTableTitle: "Insert table",
105
+ insertTableDescription: "Define your starting point of a table, you can add and remove columns and rows after creation.",
106
+ insertTableRows: "Rows",
107
+ insertTableColumns: "Columns",
108
+ insertTableCommit: "Insert table"
109
+ };
110
+ var en_default = translations;
111
+
112
+ // src/rich-text-editor/i18n/index.tsx
113
+ import { jsx as jsx2 } from "react/jsx-runtime";
114
+ var I18nContext = createContext2(null);
115
+ function I18nProvider({
116
+ labelTranslations,
117
+ children
118
+ }) {
119
+ const translations2 = labelTranslations || en_default;
120
+ return /* @__PURE__ */ jsx2(I18nContext.Provider, {
121
+ value: translations2,
122
+ children
123
+ });
124
+ }
125
+ function replaceI18nVariablesInString(str, replaceWith) {
126
+ return str.replace(/({{[^}]+}})/g, replaceWith);
127
+ }
128
+ function useTr() {
129
+ const context = useContext2(I18nContext);
130
+ return (key, units) => {
131
+ const thereAreUnits = typeof units === "number";
132
+ const keyToUse = thereAreUnits && units > 1 ? `${key}_plural` : key;
133
+ if (context && keyToUse in context) {
134
+ const tr = context[keyToUse];
135
+ if (thereAreUnits) {
136
+ return replaceI18nVariablesInString(tr, units.toString());
137
+ }
138
+ return tr;
139
+ }
140
+ return "";
141
+ };
142
+ }
143
+
144
+ // src/rich-text-editor/model/crystallize-to-lexical.ts
145
+ import {
146
+ $createLineBreakNode,
147
+ $createParagraphNode,
148
+ $createTextNode,
149
+ $getRoot,
150
+ $isTextNode
151
+ } from "lexical";
152
+ import { $createCodeHighlightNode, $createCodeNode } from "@lexical/code";
153
+ import { $createLinkNode } from "@lexical/link";
154
+ import { $createListItemNode, $createListNode } from "@lexical/list";
155
+ import { $createHorizontalRuleNode } from "@lexical/react/LexicalHorizontalRuleNode";
156
+ import { $createHeadingNode, $createQuoteNode } from "@lexical/rich-text";
157
+ import { $createTableCellNode, $createTableNode, $createTableRowNode } from "@lexical/table";
158
+
159
+ // src/rich-text-editor/model/parse-initial-state.ts
160
+ function parseInitialState({ richText }) {
161
+ let richTextArray = Array.isArray(richText) ? richText : [richText];
162
+ richTextArray = richTextArray.map((rootNode) => {
163
+ if (!rootNode.kind || rootNode.kind === "inline") {
164
+ return {
165
+ type: "paragraph",
166
+ kind: "block",
167
+ children: [rootNode]
168
+ };
169
+ }
170
+ return rootNode;
171
+ });
172
+ return richTextArray;
173
+ }
174
+
175
+ // src/rich-text-editor/model/crystallize-to-lexical.ts
176
+ function composeInitialState({ richText }) {
177
+ return function setLexicalState() {
178
+ const root = $getRoot();
179
+ function handleNode({
180
+ crystallizeContentNode,
181
+ lexicalParent
182
+ }) {
183
+ const { textContent, kind, type, children, metadata } = crystallizeContentNode;
184
+ let lexicalNode = null;
185
+ let insertedTextContent = false;
186
+ const customTextFormat = getLexicalTextFormat(crystallizeContentNode);
187
+ if (customTextFormat) {
188
+ lexicalNode = $createTextNode(textContent).toggleFormat(customTextFormat);
189
+ insertedTextContent = true;
190
+ } else {
191
+ switch (type) {
192
+ case "heading1": {
193
+ lexicalNode = $createHeadingNode("h1");
194
+ break;
195
+ }
196
+ case "heading2": {
197
+ lexicalNode = $createHeadingNode("h2");
198
+ break;
199
+ }
200
+ case "heading3": {
201
+ lexicalNode = $createHeadingNode("h3");
202
+ break;
203
+ }
204
+ case "heading4": {
205
+ lexicalNode = $createHeadingNode("h4");
206
+ break;
207
+ }
208
+ case "heading5": {
209
+ lexicalNode = $createHeadingNode("h5");
210
+ break;
211
+ }
212
+ case "heading6": {
213
+ lexicalNode = $createHeadingNode("h6");
214
+ break;
215
+ }
216
+ case "paragraph": {
217
+ lexicalNode = $createParagraphNode();
218
+ break;
219
+ }
220
+ case "horizontal-line": {
221
+ lexicalNode = $createHorizontalRuleNode();
222
+ break;
223
+ }
224
+ case "code": {
225
+ const language = metadata && typeof metadata.language === "string" ? metadata.language : null;
226
+ lexicalNode = $createCodeNode(language);
227
+ lexicalNode.append($createCodeHighlightNode(textContent ?? ""));
228
+ insertedTextContent = true;
229
+ break;
230
+ }
231
+ case "ordered-list": {
232
+ lexicalNode = $createListNode("number");
233
+ break;
234
+ }
235
+ case "unordered-list": {
236
+ lexicalNode = $createListNode("bullet");
237
+ break;
238
+ }
239
+ case "list-item": {
240
+ lexicalNode = $createListItemNode();
241
+ break;
242
+ }
243
+ case "line-break": {
244
+ lexicalNode = $createLineBreakNode();
245
+ break;
246
+ }
247
+ case "link": {
248
+ const href = metadata && typeof metadata.href === "string" ? metadata.href : "";
249
+ const target = metadata && typeof metadata.target === "string" ? metadata.target : null;
250
+ const rel = metadata && typeof metadata.rel === "string" ? metadata.rel : null;
251
+ lexicalNode = $createLinkNode(href, {
252
+ target,
253
+ rel
254
+ });
255
+ break;
256
+ }
257
+ case "quote": {
258
+ lexicalNode = $createQuoteNode();
259
+ break;
260
+ }
261
+ case "table": {
262
+ lexicalNode = $createTableNode();
263
+ break;
264
+ }
265
+ case "table-row": {
266
+ lexicalNode = $createTableRowNode();
267
+ break;
268
+ }
269
+ case "table-cell":
270
+ case "table-head-cell": {
271
+ const colSpan = void 0;
272
+ lexicalNode = $createTableCellNode(
273
+ 0,
274
+ colSpan
275
+ );
276
+ break;
277
+ }
278
+ case "preformatted": {
279
+ lexicalNode = lexicalParent;
280
+ if (children) {
281
+ children.forEach((n) => handleNode({ crystallizeContentNode: n, lexicalParent }));
282
+ }
283
+ return;
284
+ }
285
+ }
286
+ if (!insertedTextContent && typeof textContent === "string") {
287
+ const textNode = $createTextNode(textContent);
288
+ if (!lexicalNode && kind === "inline") {
289
+ lexicalNode = textNode;
290
+ } else if (lexicalNode) {
291
+ lexicalNode.append(textNode);
292
+ }
293
+ }
294
+ }
295
+ if (lexicalNode) {
296
+ if (Array.isArray(children)) {
297
+ if ($isTextNode(lexicalNode)) {
298
+ const handleInlineTextChild = (child) => {
299
+ if ($isTextNode(lexicalNode)) {
300
+ const textFormat = getLexicalTextFormat(child);
301
+ if (textFormat && !lexicalNode.hasFormat(textFormat)) {
302
+ lexicalNode.toggleFormat(textFormat);
303
+ }
304
+ if (child.textContent) {
305
+ lexicalNode.setTextContent(child.textContent);
306
+ }
307
+ }
308
+ if ("children" in child) {
309
+ child.children?.forEach(handleInlineTextChild);
310
+ }
311
+ };
312
+ children.forEach(handleInlineTextChild);
313
+ } else {
314
+ children.forEach((n) => handleNode({ crystallizeContentNode: n, lexicalParent: lexicalNode }));
315
+ }
316
+ }
317
+ lexicalParent.append(lexicalNode);
318
+ }
319
+ }
320
+ parseInitialState({ richText }).forEach(
321
+ (crystallizeContentNode) => handleNode({ crystallizeContentNode, lexicalParent: root })
322
+ );
323
+ };
324
+ }
325
+ function getLexicalTextFormat(node) {
326
+ switch (node.type) {
327
+ case "strong":
328
+ return "bold";
329
+ case "emphasized":
330
+ return "italic";
331
+ case "underlined":
332
+ return "underline";
333
+ case "subscripted":
334
+ return "subscript";
335
+ case "superscripted":
336
+ return "superscript";
337
+ case "deleted":
338
+ return "strikethrough";
339
+ case "code": {
340
+ if (node.kind === "inline") {
341
+ return "code";
342
+ }
343
+ break;
344
+ }
345
+ }
346
+ return null;
347
+ }
348
+
349
+ // src/rich-text-editor/model/lexical-to-crystallize.ts
350
+ import {
351
+ $getRoot as $getRoot2,
352
+ $isElementNode,
353
+ $isLineBreakNode,
354
+ $isParagraphNode,
355
+ $isTextNode as $isTextNode2
356
+ } from "lexical";
357
+ import { $isCodeNode } from "@lexical/code";
358
+ import { $isLinkNode } from "@lexical/link";
359
+ import { $isListItemNode, $isListNode } from "@lexical/list";
360
+ import { $isHorizontalRuleNode } from "@lexical/react/LexicalHorizontalRuleNode";
361
+ import { $isHeadingNode, $isQuoteNode } from "@lexical/rich-text";
362
+ import { $isTableCellNode, $isTableNode, $isTableRowNode } from "@lexical/table";
363
+ var headingMapper = {
364
+ h1: "heading1",
365
+ h2: "heading2",
366
+ h3: "heading3",
367
+ h4: "heading4",
368
+ h5: "heading5",
369
+ h6: "heading6"
370
+ };
371
+ function lexicalToCrystallizeRichText({
372
+ editorState
373
+ }) {
374
+ const crystallizeRichText = [];
375
+ editorState.read(() => {
376
+ handleNode($getRoot2(), crystallizeRichText);
377
+ function handleNode(lexicalNode, parentChildren) {
378
+ let crystallizeNode = null;
379
+ let innerContentsIsTakenCareOf = false;
380
+ if ($isParagraphNode(lexicalNode)) {
381
+ crystallizeNode = {
382
+ kind: "block",
383
+ type: "paragraph"
384
+ };
385
+ } else if ($isHeadingNode(lexicalNode)) {
386
+ const tag = lexicalNode.getTag();
387
+ crystallizeNode = {
388
+ kind: "block",
389
+ type: headingMapper[tag]
390
+ };
391
+ } else if ($isLinkNode(lexicalNode)) {
392
+ const href = lexicalNode.getURL();
393
+ const target = lexicalNode.getTarget();
394
+ const rel = lexicalNode.getRel();
395
+ crystallizeNode = {
396
+ kind: "inline",
397
+ type: "link",
398
+ metadata: {
399
+ href,
400
+ ...target && { target },
401
+ ...rel && { rel }
402
+ }
403
+ };
404
+ } else if ($isListNode(lexicalNode)) {
405
+ const listType = lexicalNode.getListType();
406
+ crystallizeNode = {
407
+ kind: "block",
408
+ type: listType === "number" ? "ordered-list" : "unordered-list"
409
+ };
410
+ } else if ($isListItemNode(lexicalNode)) {
411
+ crystallizeNode = {
412
+ kind: "block",
413
+ type: "list-item"
414
+ };
415
+ } else if ($isQuoteNode(lexicalNode)) {
416
+ crystallizeNode = {
417
+ kind: "block",
418
+ type: "quote"
419
+ };
420
+ } else if ($isLineBreakNode(lexicalNode)) {
421
+ crystallizeNode = {
422
+ kind: "inline",
423
+ type: "line-break"
424
+ };
425
+ } else if ($isCodeNode(lexicalNode)) {
426
+ crystallizeNode = {
427
+ kind: "block",
428
+ type: "preformatted",
429
+ children: [
430
+ {
431
+ type: "code",
432
+ kind: "block",
433
+ textContent: lexicalNode.getTextContent(),
434
+ metadata: {
435
+ language: lexicalNode.getLanguage()
436
+ }
437
+ }
438
+ ]
439
+ };
440
+ innerContentsIsTakenCareOf = true;
441
+ } else if ($isTableNode(lexicalNode)) {
442
+ crystallizeNode = {
443
+ kind: "block",
444
+ type: "table"
445
+ };
446
+ } else if ($isTableRowNode(lexicalNode)) {
447
+ crystallizeNode = {
448
+ kind: "block",
449
+ type: "table-row"
450
+ };
451
+ } else if ($isTableCellNode(lexicalNode)) {
452
+ crystallizeNode = {
453
+ kind: "inline",
454
+ type: lexicalNode.hasHeader() ? "table-head-cell" : "table-cell"
455
+ };
456
+ }
457
+ if (crystallizeNode) {
458
+ parentChildren.push(crystallizeNode);
459
+ }
460
+ if (!innerContentsIsTakenCareOf) {
461
+ let onlyChildIsPureTextContent = false;
462
+ const children = lexicalNode.getChildren();
463
+ if (children?.length > 0) {
464
+ let parentChildrenToUse = parentChildren;
465
+ if (crystallizeNode) {
466
+ if (children.length === 1 && parent) {
467
+ const [first] = children;
468
+ if ($isTextNode2(first)) {
469
+ const childTextNode = getTextChild(first);
470
+ if (!childTextNode.type) {
471
+ crystallizeNode.textContent = childTextNode.textContent;
472
+ onlyChildIsPureTextContent = true;
473
+ }
474
+ }
475
+ }
476
+ if (!onlyChildIsPureTextContent) {
477
+ crystallizeNode.children = [];
478
+ parentChildrenToUse = crystallizeNode.children;
479
+ }
480
+ }
481
+ if (!onlyChildIsPureTextContent) {
482
+ children.forEach((childNode) => {
483
+ if ($isElementNode(childNode)) {
484
+ handleNode(childNode, parentChildrenToUse);
485
+ } else if ($isHorizontalRuleNode(childNode)) {
486
+ parentChildrenToUse.push({ kind: "block", type: "horizontal-line" });
487
+ } else if ($isTextNode2(childNode)) {
488
+ parentChildrenToUse.push(getTextChild(childNode));
489
+ } else if ($isLineBreakNode(childNode)) {
490
+ parentChildrenToUse.push({ kind: "inline", type: "line-break" });
491
+ }
492
+ });
493
+ }
494
+ }
495
+ }
496
+ }
497
+ });
498
+ return crystallizeRichText;
499
+ }
500
+ var lexicalFormatToCrystallizeType = {
501
+ bold: "strong",
502
+ italic: "emphasized",
503
+ underline: "underlined",
504
+ strikethrough: "deleted",
505
+ subscript: "subscripted",
506
+ superscript: "superscripted",
507
+ highlight: "emphasized",
508
+ code: "code"
509
+ };
510
+ function getTextChild(n) {
511
+ let currentChild = {
512
+ kind: "inline"
513
+ };
514
+ let textChild = null;
515
+ function checkFormat(format) {
516
+ const type = lexicalFormatToCrystallizeType[format];
517
+ if (n.hasFormat(format) && type) {
518
+ if (!textChild) {
519
+ currentChild = textChild = {
520
+ kind: "inline",
521
+ type
522
+ };
523
+ } else {
524
+ currentChild.children = [
525
+ {
526
+ kind: "inline",
527
+ type
528
+ }
529
+ ];
530
+ currentChild = currentChild.children[0];
531
+ }
532
+ }
533
+ }
534
+ Object.keys(lexicalFormatToCrystallizeType).forEach(checkFormat);
535
+ if (!textChild) {
536
+ currentChild = textChild = {
537
+ kind: "inline"
538
+ };
539
+ }
540
+ currentChild.textContent = n.getTextContent();
541
+ return textChild;
542
+ }
543
+
544
+ // src/rich-text-editor/nodes/BaseNodes.ts
545
+ import { LineBreakNode } from "lexical";
546
+ import { CodeHighlightNode, CodeNode } from "@lexical/code";
547
+ import { AutoLinkNode, LinkNode } from "@lexical/link";
548
+ import { ListItemNode, ListNode } from "@lexical/list";
549
+ import { MarkNode } from "@lexical/mark";
550
+ import { OverflowNode } from "@lexical/overflow";
551
+ import { HorizontalRuleNode } from "@lexical/react/LexicalHorizontalRuleNode";
552
+ import { HeadingNode, QuoteNode } from "@lexical/rich-text";
553
+ import { TableCellNode, TableNode, TableRowNode } from "@lexical/table";
554
+ var BaseNodes = [
555
+ HeadingNode,
556
+ ListNode,
557
+ ListItemNode,
558
+ QuoteNode,
559
+ CodeNode,
560
+ TableNode,
561
+ TableCellNode,
562
+ TableRowNode,
563
+ CodeHighlightNode,
564
+ AutoLinkNode,
565
+ LinkNode,
566
+ OverflowNode,
567
+ HorizontalRuleNode,
568
+ MarkNode,
569
+ LineBreakNode
570
+ ];
571
+
572
+ // src/rich-text-editor/plugins/AutoLinkPlugin/index.tsx
573
+ import "react";
574
+ import { AutoLinkPlugin } from "@lexical/react/LexicalAutoLinkPlugin";
575
+ import { jsx as jsx3 } from "react/jsx-runtime";
576
+ var URL_MATCHER = /((https?:\/\/(www\.)?)|(www\.))[-a-zA-Z0-9@:%._+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b([-a-zA-Z0-9()@:%_+.~#?&//=]*)/;
577
+ var EMAIL_MATCHER = /(([^<>()[\]\\.,;:\s@"]+(\.[^<>()[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))/;
578
+ var MATCHERS = [
579
+ (text) => {
580
+ const match = URL_MATCHER.exec(text);
581
+ if (match === null) {
582
+ return null;
583
+ }
584
+ const fullMatch = match[0];
585
+ return {
586
+ index: match.index,
587
+ length: fullMatch.length,
588
+ text: fullMatch,
589
+ url: fullMatch.startsWith("http") ? fullMatch : `https://${fullMatch}`
590
+ };
591
+ },
592
+ (text) => {
593
+ const match = EMAIL_MATCHER.exec(text);
594
+ return match && {
595
+ index: match.index,
596
+ length: match[0].length,
597
+ text: match[0],
598
+ url: `mailto:${match[0]}`
599
+ };
600
+ }
601
+ ];
602
+ function LexicalAutoLinkPlugin() {
603
+ return /* @__PURE__ */ jsx3(AutoLinkPlugin, {
604
+ matchers: MATCHERS
605
+ });
606
+ }
607
+
608
+ // src/rich-text-editor/plugins/CodeActionMenuPlugin/index.tsx
609
+ import { useEffect, useRef, useState as useState3 } from "react";
610
+ import { $getNearestNodeFromDOMNode as $getNearestNodeFromDOMNode3 } from "lexical";
611
+ import { createPortal } from "react-dom";
612
+ import { useDebouncedCallback as useDebouncedCallback2 } from "use-debounce";
613
+ import { $isCodeNode as $isCodeNode4, CodeNode as CodeNode2, getLanguageFriendlyName, normalizeCodeLang } from "@lexical/code";
614
+ import { useLexicalComposerContext } from "@lexical/react/LexicalComposerContext";
615
+
616
+ // src/rich-text-editor/plugins/CodeActionMenuPlugin/components/CopyButton/index.tsx
617
+ import "react";
618
+ import { useState } from "react";
619
+ import { $getNearestNodeFromDOMNode, $getSelection, $setSelection } from "lexical";
620
+ import { useDebouncedCallback } from "use-debounce";
621
+ import { $isCodeNode as $isCodeNode2 } from "@lexical/code";
622
+ import { jsx as jsx4 } from "react/jsx-runtime";
623
+ function CopyButton({ editor, getCodeDOMNode }) {
624
+ const [isCopyCompleted, setCopyCompleted] = useState(false);
625
+ const tr = useTr();
626
+ const removeSuccessIcon = useDebouncedCallback(() => {
627
+ setCopyCompleted(false);
628
+ }, 1e3);
629
+ async function handleClick() {
630
+ const codeDOMNode = getCodeDOMNode();
631
+ if (!codeDOMNode) {
632
+ return;
633
+ }
634
+ let content = "";
635
+ editor.update(() => {
636
+ const codeNode = $getNearestNodeFromDOMNode(codeDOMNode);
637
+ if ($isCodeNode2(codeNode)) {
638
+ content = codeNode.getTextContent();
639
+ }
640
+ const selection = $getSelection();
641
+ $setSelection(selection);
642
+ });
643
+ try {
644
+ await navigator.clipboard.writeText(content);
645
+ setCopyCompleted(true);
646
+ removeSuccessIcon();
647
+ } catch (err) {
648
+ console.error("Failed to copy: ", err);
649
+ }
650
+ }
651
+ return /* @__PURE__ */ jsx4("button", {
652
+ className: "c-rte-code-button",
653
+ onClick: handleClick,
654
+ "aria-label": tr("actionCopyCode"),
655
+ children: isCopyCompleted ? /* @__PURE__ */ jsx4("i", {
656
+ className: "c-rte-code-button__icon c-rte-icon-success"
657
+ }) : /* @__PURE__ */ jsx4("i", {
658
+ className: "c-rte-code-button__icon c-rte-icon-copy"
659
+ })
660
+ });
661
+ }
662
+
663
+ // src/rich-text-editor/plugins/CodeActionMenuPlugin/components/PrettierButton/index.tsx
664
+ import "react";
665
+ import { useState as useState2 } from "react";
666
+ import { $getNearestNodeFromDOMNode as $getNearestNodeFromDOMNode2 } from "lexical";
667
+ import { $isCodeNode as $isCodeNode3 } from "@lexical/code";
668
+ import { jsx as jsx5, jsxs } from "react/jsx-runtime";
669
+ var PRETTIER_PARSER_MODULES = {
670
+ css: () => import("./parser-postcss-AN2EJ77H.mjs"),
671
+ html: () => import("./parser-html-URMUOK6U.mjs"),
672
+ js: () => import("./parser-babel-B7AMC4UT.mjs")
673
+ };
674
+ async function loadPrettierParserByLang(lang) {
675
+ const dynamicImport = PRETTIER_PARSER_MODULES[lang];
676
+ return await dynamicImport();
677
+ }
678
+ async function loadPrettierFormat() {
679
+ const { format } = await import("./standalone-AR2ENVE7.mjs");
680
+ return format;
681
+ }
682
+ var PRETTIER_OPTIONS_BY_LANG = {
683
+ css: {
684
+ parser: "css"
685
+ },
686
+ html: {
687
+ parser: "html"
688
+ },
689
+ js: {
690
+ parser: "babel"
691
+ },
692
+ markdown: {
693
+ parser: "markdown"
694
+ }
695
+ };
696
+ var LANG_CAN_BE_PRETTIER = Object.keys(PRETTIER_OPTIONS_BY_LANG);
697
+ function canBePrettier(lang) {
698
+ return LANG_CAN_BE_PRETTIER.includes(lang);
699
+ }
700
+ function getPrettierOptions(lang) {
701
+ const options = PRETTIER_OPTIONS_BY_LANG[lang];
702
+ if (!options) {
703
+ throw new Error(`CodeActionMenuPlugin: Prettier does not support this language: ${lang}`);
704
+ }
705
+ return options;
706
+ }
707
+ function PrettierButton({ lang, editor, getCodeDOMNode }) {
708
+ const [syntaxError, setSyntaxError] = useState2("");
709
+ const [tipsVisible, setTipsVisible] = useState2(false);
710
+ const tr = useTr();
711
+ async function handleClick() {
712
+ const codeDOMNode = getCodeDOMNode();
713
+ try {
714
+ const format = await loadPrettierFormat();
715
+ const options = getPrettierOptions(lang);
716
+ options.plugins = [await loadPrettierParserByLang(lang)];
717
+ if (!codeDOMNode) {
718
+ return;
719
+ }
720
+ editor.update(() => {
721
+ const codeNode = $getNearestNodeFromDOMNode2(codeDOMNode);
722
+ if ($isCodeNode3(codeNode)) {
723
+ const content = codeNode.getTextContent();
724
+ let parsed = "";
725
+ parsed = format(content, options);
726
+ parsed = parsed.replace(/[\r\n]+$/, "");
727
+ if (parsed !== "") {
728
+ const selection = codeNode.select(0);
729
+ selection.insertText(parsed);
730
+ setSyntaxError("");
731
+ setTipsVisible(false);
732
+ }
733
+ }
734
+ });
735
+ } catch (error) {
736
+ if (error instanceof Error) {
737
+ setSyntaxError(error.message);
738
+ setTipsVisible(true);
739
+ } else {
740
+ console.error("Unexpected error: ", error);
741
+ }
742
+ }
743
+ }
744
+ function handleMouseEnter() {
745
+ if (syntaxError !== "") {
746
+ setTipsVisible(true);
747
+ }
748
+ }
749
+ function handleMouseLeave() {
750
+ if (syntaxError !== "") {
751
+ setTipsVisible(false);
752
+ }
753
+ }
754
+ return /* @__PURE__ */ jsxs("div", {
755
+ className: "c-rte-prettier-wrapper",
756
+ children: [
757
+ /* @__PURE__ */ jsx5("button", {
758
+ className: "c-rte-code-button",
759
+ onClick: handleClick,
760
+ onMouseEnter: handleMouseEnter,
761
+ onMouseLeave: handleMouseLeave,
762
+ "aria-label": tr("actionFormatCode"),
763
+ children: syntaxError ? /* @__PURE__ */ jsx5("i", {
764
+ className: "c-rte-code-button__icon c-rte-icon-prettier-error"
765
+ }) : /* @__PURE__ */ jsx5("i", {
766
+ className: "c-rte-code-button__icon c-rte-icon-prettier"
767
+ })
768
+ }),
769
+ tipsVisible ? /* @__PURE__ */ jsx5("pre", {
770
+ className: "c-rte-code-error-tips",
771
+ children: syntaxError
772
+ }) : null
773
+ ]
774
+ });
775
+ }
776
+
777
+ // src/rich-text-editor/plugins/CodeActionMenuPlugin/index.tsx
778
+ import { Fragment, jsx as jsx6, jsxs as jsxs2 } from "react/jsx-runtime";
779
+ var CODE_PADDING = 0;
780
+ function CodeActionMenuContainer({ anchorElem }) {
781
+ const [editor] = useLexicalComposerContext();
782
+ const [lang, setLang] = useState3("");
783
+ const [isShown, setShown] = useState3(false);
784
+ const [shouldListenMouseMove, setShouldListenMouseMove] = useState3(true);
785
+ const [position, setPosition] = useState3({
786
+ right: "0",
787
+ top: "0"
788
+ });
789
+ const codeSetRef = useRef(/* @__PURE__ */ new Set());
790
+ const codeDOMNodeRef = useRef(null);
791
+ function getCodeDOMNode() {
792
+ return codeDOMNodeRef.current;
793
+ }
794
+ const debouncedOnMouseMove = useDebouncedCallback2((event) => {
795
+ const { codeDOMNode, isOutside } = getMouseInfo(event);
796
+ if (isOutside) {
797
+ setShown(false);
798
+ return;
799
+ }
800
+ if (!codeDOMNode) {
801
+ return;
802
+ }
803
+ codeDOMNodeRef.current = codeDOMNode;
804
+ let codeNode = null;
805
+ let _lang = "";
806
+ editor.update(() => {
807
+ const maybeCodeNode = $getNearestNodeFromDOMNode3(codeDOMNode);
808
+ if ($isCodeNode4(maybeCodeNode)) {
809
+ codeNode = maybeCodeNode;
810
+ _lang = codeNode.getLanguage() || "";
811
+ }
812
+ });
813
+ if (codeNode) {
814
+ const { y: editorElemY, right: editorElemRight } = anchorElem.getBoundingClientRect();
815
+ const { y, right } = codeDOMNode.getBoundingClientRect();
816
+ setLang(_lang);
817
+ setShown(true);
818
+ setPosition({
819
+ right: `${editorElemRight - right + CODE_PADDING}px`,
820
+ top: `${y - editorElemY}px`
821
+ });
822
+ }
823
+ }, 50);
824
+ useEffect(() => {
825
+ if (!shouldListenMouseMove) {
826
+ return;
827
+ }
828
+ document.addEventListener("mousemove", debouncedOnMouseMove);
829
+ return () => {
830
+ setShown(false);
831
+ debouncedOnMouseMove.cancel();
832
+ document.removeEventListener("mousemove", debouncedOnMouseMove);
833
+ };
834
+ }, [shouldListenMouseMove, debouncedOnMouseMove]);
835
+ editor.registerMutationListener(CodeNode2, (mutations) => {
836
+ editor.getEditorState().read(() => {
837
+ for (const [key, type] of mutations) {
838
+ switch (type) {
839
+ case "created":
840
+ codeSetRef.current.add(key);
841
+ setShouldListenMouseMove(codeSetRef.current.size > 0);
842
+ break;
843
+ case "destroyed":
844
+ codeSetRef.current.delete(key);
845
+ setShouldListenMouseMove(codeSetRef.current.size > 0);
846
+ break;
847
+ default:
848
+ break;
849
+ }
850
+ }
851
+ });
852
+ });
853
+ const normalizedLang = normalizeCodeLang(lang);
854
+ const codeFriendlyName = getLanguageFriendlyName(lang);
855
+ return /* @__PURE__ */ jsx6(Fragment, {
856
+ children: isShown ? /* @__PURE__ */ jsxs2("div", {
857
+ className: "c-rte-code-action-menu-container",
858
+ style: { ...position },
859
+ children: [
860
+ /* @__PURE__ */ jsx6("div", {
861
+ className: "c-rte-code-highlight-language",
862
+ children: codeFriendlyName
863
+ }),
864
+ /* @__PURE__ */ jsx6(CopyButton, {
865
+ editor,
866
+ getCodeDOMNode
867
+ }),
868
+ canBePrettier(normalizedLang) ? /* @__PURE__ */ jsx6(PrettierButton, {
869
+ editor,
870
+ getCodeDOMNode,
871
+ lang: normalizedLang
872
+ }) : null
873
+ ]
874
+ }) : null
875
+ });
876
+ }
877
+ function getMouseInfo(event) {
878
+ const target = event.target;
879
+ if (target && target instanceof HTMLElement) {
880
+ const codeDOMNode = target.closest("code.CrystallizeRTEditorTheme__code");
881
+ const isOutside = !(codeDOMNode || target.closest("div.c-rte-code-action-menu-container"));
882
+ return { codeDOMNode, isOutside };
883
+ } else {
884
+ return { codeDOMNode: null, isOutside: true };
885
+ }
886
+ }
887
+ function CodeActionMenuPlugin({
888
+ anchorElem = document.body
889
+ }) {
890
+ return createPortal(/* @__PURE__ */ jsx6(CodeActionMenuContainer, {
891
+ anchorElem
892
+ }), anchorElem);
893
+ }
894
+
895
+ // src/rich-text-editor/plugins/CodeHighlightPlugin/index.ts
896
+ import { useEffect as useEffect2 } from "react";
897
+ import { registerCodeHighlighting } from "@lexical/code";
898
+ import { useLexicalComposerContext as useLexicalComposerContext2 } from "@lexical/react/LexicalComposerContext";
899
+ function CodeHighlightPlugin() {
900
+ const [editor] = useLexicalComposerContext2();
901
+ useEffect2(() => {
902
+ return registerCodeHighlighting(editor);
903
+ }, [editor]);
904
+ return null;
905
+ }
906
+
907
+ // src/rich-text-editor/plugins/FloatingLinkEditorPlugin/index.tsx
908
+ import { useCallback, useEffect as useEffect4, useRef as useRef2, useState as useState5 } from "react";
909
+ import "react";
910
+ import {
911
+ $getSelection as $getSelection3,
912
+ $isRangeSelection,
913
+ COMMAND_PRIORITY_CRITICAL,
914
+ COMMAND_PRIORITY_HIGH,
915
+ COMMAND_PRIORITY_LOW,
916
+ KEY_ESCAPE_COMMAND,
917
+ SELECTION_CHANGE_COMMAND
918
+ } from "lexical";
919
+ import { createPortal as createPortal2 } from "react-dom";
920
+ import { $isAutoLinkNode, $isLinkNode as $isLinkNode2, TOGGLE_LINK_COMMAND } from "@lexical/link";
921
+ import { useLexicalComposerContext as useLexicalComposerContext4 } from "@lexical/react/LexicalComposerContext";
922
+ import { $findMatchingParent, mergeRegister } from "@lexical/utils";
923
+
924
+ // src/rich-text-editor/ui/LinkPreview.tsx
925
+ import { Suspense, useEffect as useEffect3, useState as useState4 } from "react";
926
+ import { $getSelection as $getSelection2, $isTextNode as $isTextNode3 } from "lexical";
927
+ import { useLexicalComposerContext as useLexicalComposerContext3 } from "@lexical/react/LexicalComposerContext";
928
+ import { Fragment as Fragment2, jsx as jsx7, jsxs as jsxs3 } from "react/jsx-runtime";
929
+ var PREVIEW_CACHE = {};
930
+ var URL_MATCHER2 = /((https?:\/\/(www\.)?)|(www\.))[-a-zA-Z0-9@:%._+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b([-a-zA-Z0-9()@:%_+.~#?&//=]*)/;
931
+ function useSuspenseRequest(url) {
932
+ let cached = PREVIEW_CACHE[url];
933
+ if (!url.match(URL_MATCHER2)) {
934
+ return { preview: null };
935
+ }
936
+ if (!cached) {
937
+ cached = PREVIEW_CACHE[url] = fetch(`https://service-metatags.crystallize.workers.dev/?url=${encodeURI(url)}`).then((response) => response.json()).then((preview) => {
938
+ PREVIEW_CACHE[url] = { preview };
939
+ return preview;
940
+ }).catch(() => {
941
+ PREVIEW_CACHE[url] = { preview: null };
942
+ });
943
+ }
944
+ if (cached instanceof Promise) {
945
+ throw cached;
946
+ }
947
+ return cached;
948
+ }
949
+ function LinkPreviewContent({
950
+ url
951
+ }) {
952
+ const [textContent, setTextContent] = useState4("");
953
+ const { preview } = useSuspenseRequest(url);
954
+ const [editor] = useLexicalComposerContext3();
955
+ const tr = useTr();
956
+ const hasPreview = preview !== null && preview.google?.title;
957
+ useEffect3(() => {
958
+ editor.update(() => {
959
+ const sel = $getSelection2();
960
+ const nodes = sel?.getNodes();
961
+ if (hasPreview && nodes?.length === 1) {
962
+ const [firstNode] = nodes;
963
+ if ($isTextNode3(firstNode)) {
964
+ setTextContent(firstNode.getTextContent());
965
+ }
966
+ }
967
+ });
968
+ }, [editor, preview]);
969
+ function useTitleForText() {
970
+ editor.update(() => {
971
+ const sel = $getSelection2();
972
+ const nodes = sel?.getNodes();
973
+ if (hasPreview && nodes?.length === 1) {
974
+ const [firstNode] = nodes;
975
+ if ($isTextNode3(firstNode)) {
976
+ firstNode.setTextContent(preview.google.title);
977
+ setTextContent(preview.google.title);
978
+ }
979
+ }
980
+ });
981
+ }
982
+ if (!hasPreview) {
983
+ return null;
984
+ }
985
+ return /* @__PURE__ */ jsxs3("div", {
986
+ className: "c-rte-link-preview",
987
+ children: [
988
+ preview.google.image && /* @__PURE__ */ jsx7("div", {
989
+ className: "c-rte-link-preview-image-wrapper",
990
+ children: /* @__PURE__ */ jsx7("img", {
991
+ src: preview.google.image,
992
+ alt: preview.google.title,
993
+ className: "c-rte-link-preview-image"
994
+ })
995
+ }),
996
+ preview.google.title && /* @__PURE__ */ jsx7("div", {
997
+ className: "c-rte-link-preview-title",
998
+ children: preview.google.title
999
+ }),
1000
+ preview.google.description && /* @__PURE__ */ jsx7("div", {
1001
+ className: "c-rte-link-preview-description",
1002
+ children: preview.google.description
1003
+ }),
1004
+ textContent && textContent !== preview.google.title ? /* @__PURE__ */ jsx7(Button, {
1005
+ className: "c-rte-link-preview__replace-text-btn",
1006
+ onClick: useTitleForText,
1007
+ children: tr("linkPreviewReplaceTextWithTitle")
1008
+ }) : null
1009
+ ]
1010
+ });
1011
+ }
1012
+ function Glimmer(props) {
1013
+ return /* @__PURE__ */ jsx7("div", {
1014
+ className: "c-rte-link-preview-glimmer",
1015
+ ...props,
1016
+ style: {
1017
+ animationDelay: String((props.index || 0) * 300),
1018
+ ...props.style || {}
1019
+ }
1020
+ });
1021
+ }
1022
+ function LinkPreview({
1023
+ url
1024
+ }) {
1025
+ return /* @__PURE__ */ jsx7(Suspense, {
1026
+ fallback: /* @__PURE__ */ jsxs3(Fragment2, {
1027
+ children: [
1028
+ /* @__PURE__ */ jsx7(Glimmer, {
1029
+ style: { height: "80px" },
1030
+ index: 0
1031
+ }),
1032
+ /* @__PURE__ */ jsx7(Glimmer, {
1033
+ style: { width: "60%" },
1034
+ index: 1
1035
+ }),
1036
+ /* @__PURE__ */ jsx7(Glimmer, {
1037
+ style: { width: "80%" },
1038
+ index: 2
1039
+ })
1040
+ ]
1041
+ }),
1042
+ children: /* @__PURE__ */ jsx7(LinkPreviewContent, {
1043
+ url
1044
+ })
1045
+ });
1046
+ }
1047
+
1048
+ // src/rich-text-editor/utils/getSelectedNode.ts
1049
+ import { $isAtNodeEnd } from "@lexical/selection";
1050
+ function getSelectedNode(selection) {
1051
+ const anchor = selection.anchor;
1052
+ const focus = selection.focus;
1053
+ const anchorNode = selection.anchor.getNode();
1054
+ const focusNode = selection.focus.getNode();
1055
+ if (anchorNode === focusNode) {
1056
+ return anchorNode;
1057
+ }
1058
+ const isBackward = selection.isBackward();
1059
+ if (isBackward) {
1060
+ return $isAtNodeEnd(focus) ? anchorNode : focusNode;
1061
+ } else {
1062
+ return $isAtNodeEnd(anchor) ? anchorNode : focusNode;
1063
+ }
1064
+ }
1065
+
1066
+ // src/rich-text-editor/utils/setFloatingElemPosition.ts
1067
+ var VERTICAL_GAP = 10;
1068
+ var HORIZONTAL_OFFSET = 5;
1069
+ function setFloatingElemPosition(targetRect, floatingElem, anchorElem, verticalGap = VERTICAL_GAP, horizontalOffset = HORIZONTAL_OFFSET) {
1070
+ const scrollerElem = anchorElem.parentElement;
1071
+ if (targetRect === null || !scrollerElem) {
1072
+ floatingElem.style.opacity = "0";
1073
+ floatingElem.style.transform = "translate(-10000px, -10000px)";
1074
+ return;
1075
+ }
1076
+ const floatingElemRect = floatingElem.getBoundingClientRect();
1077
+ const anchorElementRect = anchorElem.getBoundingClientRect();
1078
+ const editorScrollerRect = scrollerElem.getBoundingClientRect();
1079
+ let top = targetRect.top - floatingElemRect.height - verticalGap;
1080
+ let left = targetRect.left - horizontalOffset;
1081
+ if (top < editorScrollerRect.top) {
1082
+ top += floatingElemRect.height + targetRect.height + verticalGap * 2;
1083
+ }
1084
+ if (left + floatingElemRect.width > editorScrollerRect.right) {
1085
+ left = editorScrollerRect.right - floatingElemRect.width - horizontalOffset;
1086
+ }
1087
+ top -= anchorElementRect.top;
1088
+ left -= anchorElementRect.left;
1089
+ floatingElem.style.opacity = "1";
1090
+ floatingElem.style.transform = `translate(${left}px, ${top}px)`;
1091
+ }
1092
+
1093
+ // src/rich-text-editor/utils/url.ts
1094
+ function sanitizeUrl(url) {
1095
+ const SAFE_URL_PATTERN = /^(?:(?:https?|mailto|ftp|tel|file|sms):|[^&:/?#]*(?:[/?#]|$))/gi;
1096
+ const DATA_URL_PATTERN = /^data:(?:image\/(?:bmp|gif|jpeg|jpg|png|tiff|webp)|video\/(?:mpeg|mp4|ogg|webm)|audio\/(?:mp3|oga|ogg|opus));base64,[a-z0-9+/]+=*$/i;
1097
+ url = String(url).trim();
1098
+ if (url.match(SAFE_URL_PATTERN) || url.match(DATA_URL_PATTERN))
1099
+ return url;
1100
+ return "https://";
1101
+ }
1102
+ var urlRegExp = new RegExp(
1103
+ /((([A-Za-z]{3,9}:(?:\/\/)?)(?:[-;:&=+$,\w]+@)?[A-Za-z0-9.-]+|(?:www.|[-;:&=+$,\w]+@)[A-Za-z0-9.-]+)((?:\/[+~%/.\w-_]*)?\??(?:[-+=&;%@.\w_]*)#?(?:[\w]*))?)/
1104
+ );
1105
+ function validateUrl(url) {
1106
+ return url === "https://" || urlRegExp.test(url);
1107
+ }
1108
+
1109
+ // src/rich-text-editor/plugins/FloatingLinkEditorPlugin/index.tsx
1110
+ import { Fragment as Fragment3, jsx as jsx8, jsxs as jsxs4 } from "react/jsx-runtime";
1111
+ function FloatingLinkEditor({
1112
+ editor,
1113
+ isLink,
1114
+ setIsLink,
1115
+ anchorElem
1116
+ }) {
1117
+ const editorRef = useRef2(null);
1118
+ const inputRef = useRef2(null);
1119
+ const [linkUrl, setLinkUrl] = useState5("");
1120
+ const [rel, setRel] = useState5(null);
1121
+ const [target, setTarget] = useState5(null);
1122
+ const [isEditMode, setEditMode] = useState5(false);
1123
+ const [lastSelection, setLastSelection] = useState5(null);
1124
+ const tr = useTr();
1125
+ const updateLinkEditor = useCallback(() => {
1126
+ const selection = $getSelection3();
1127
+ if ($isRangeSelection(selection)) {
1128
+ const node = getSelectedNode(selection);
1129
+ const parent2 = node.getParent();
1130
+ if ($isLinkNode2(parent2)) {
1131
+ setLinkUrl(parent2.getURL());
1132
+ setRel(parent2.getRel());
1133
+ setTarget(parent2.getTarget());
1134
+ } else if ($isLinkNode2(node)) {
1135
+ setLinkUrl(node.getURL());
1136
+ setRel(node.getRel());
1137
+ setRel(node.getTarget());
1138
+ } else {
1139
+ setLinkUrl("");
1140
+ setRel(null);
1141
+ setTarget(null);
1142
+ }
1143
+ }
1144
+ const editorElem = editorRef.current;
1145
+ const nativeSelection = window.getSelection();
1146
+ const activeElement = document.activeElement;
1147
+ if (editorElem === null) {
1148
+ return;
1149
+ }
1150
+ const rootElement = editor.getRootElement();
1151
+ if (selection !== null && nativeSelection !== null && rootElement !== null && rootElement.contains(nativeSelection.anchorNode) && editor.isEditable()) {
1152
+ const domRange = nativeSelection.getRangeAt(0);
1153
+ let rect;
1154
+ if (nativeSelection.anchorNode === rootElement) {
1155
+ let inner = rootElement;
1156
+ while (inner.firstElementChild != null) {
1157
+ inner = inner.firstElementChild;
1158
+ }
1159
+ rect = inner.getBoundingClientRect();
1160
+ } else {
1161
+ rect = domRange.getBoundingClientRect();
1162
+ }
1163
+ setFloatingElemPosition(rect, editorElem, anchorElem);
1164
+ setLastSelection(selection);
1165
+ } else if (!activeElement || activeElement.className !== "link-input") {
1166
+ if (rootElement !== null) {
1167
+ setFloatingElemPosition(null, editorElem, anchorElem);
1168
+ }
1169
+ setLastSelection(null);
1170
+ setEditMode(false);
1171
+ setLinkUrl("");
1172
+ }
1173
+ return true;
1174
+ }, [anchorElem, editor]);
1175
+ useEffect4(() => {
1176
+ const scrollerElem = anchorElem.parentElement;
1177
+ const update = () => {
1178
+ editor.getEditorState().read(() => {
1179
+ updateLinkEditor();
1180
+ });
1181
+ };
1182
+ window.addEventListener("resize", update);
1183
+ if (scrollerElem) {
1184
+ scrollerElem.addEventListener("scroll", update);
1185
+ }
1186
+ return () => {
1187
+ window.removeEventListener("resize", update);
1188
+ if (scrollerElem) {
1189
+ scrollerElem.removeEventListener("scroll", update);
1190
+ }
1191
+ };
1192
+ }, [anchorElem.parentElement, editor, updateLinkEditor]);
1193
+ useEffect4(() => {
1194
+ return mergeRegister(
1195
+ editor.registerUpdateListener(({ editorState }) => {
1196
+ editorState.read(() => {
1197
+ updateLinkEditor();
1198
+ });
1199
+ }),
1200
+ editor.registerCommand(
1201
+ SELECTION_CHANGE_COMMAND,
1202
+ () => {
1203
+ updateLinkEditor();
1204
+ return true;
1205
+ },
1206
+ COMMAND_PRIORITY_LOW
1207
+ ),
1208
+ editor.registerCommand(
1209
+ KEY_ESCAPE_COMMAND,
1210
+ () => {
1211
+ if (isLink) {
1212
+ setIsLink(false);
1213
+ return true;
1214
+ }
1215
+ return false;
1216
+ },
1217
+ COMMAND_PRIORITY_HIGH
1218
+ )
1219
+ );
1220
+ }, [editor, updateLinkEditor, setIsLink, isLink]);
1221
+ useEffect4(() => {
1222
+ editor.getEditorState().read(() => {
1223
+ updateLinkEditor();
1224
+ });
1225
+ }, [editor, updateLinkEditor]);
1226
+ useEffect4(() => {
1227
+ if (isEditMode && inputRef.current) {
1228
+ inputRef.current.focus();
1229
+ }
1230
+ }, [isEditMode]);
1231
+ return /* @__PURE__ */ jsx8("div", {
1232
+ ref: editorRef,
1233
+ className: "c-rte-link-editor",
1234
+ "data-testid": "rich-text-link-editor",
1235
+ children: isEditMode ? /* @__PURE__ */ jsxs4("div", {
1236
+ children: [
1237
+ /* @__PURE__ */ jsx8("div", {
1238
+ className: "c-rte-link-editor-input-group",
1239
+ children: /* @__PURE__ */ jsx8(InputWithLabel, {
1240
+ label: tr("linkEditorLink"),
1241
+ type: "text",
1242
+ value: linkUrl,
1243
+ onChange: (e) => setLinkUrl(e.target.value)
1244
+ })
1245
+ }),
1246
+ /* @__PURE__ */ jsx8("div", {
1247
+ className: "c-rte-link-editor-input-group",
1248
+ children: /* @__PURE__ */ jsx8(InputWithLabel, {
1249
+ label: tr("linkEditorRel"),
1250
+ type: "text",
1251
+ value: rel ?? "",
1252
+ onChange: (e) => setRel(e.target.value)
1253
+ })
1254
+ }),
1255
+ /* @__PURE__ */ jsx8("div", {
1256
+ className: "c-rte-link-editor-input-group",
1257
+ children: /* @__PURE__ */ jsx8(InputWithLabel, {
1258
+ label: tr("linkEditorTarget"),
1259
+ type: "text",
1260
+ value: target ?? "",
1261
+ onChange: (e) => setTarget(e.target.value)
1262
+ })
1263
+ }),
1264
+ /* @__PURE__ */ jsx8("div", {
1265
+ className: "c-rte-link-editor-button-wrap",
1266
+ children: /* @__PURE__ */ jsx8(Button, {
1267
+ "data-testid": "link-editor-save-button",
1268
+ onClick: () => {
1269
+ if (lastSelection !== null) {
1270
+ if (linkUrl !== "") {
1271
+ editor.dispatchCommand(TOGGLE_LINK_COMMAND, {
1272
+ url: sanitizeUrl(linkUrl),
1273
+ rel,
1274
+ target
1275
+ });
1276
+ }
1277
+ setEditMode(false);
1278
+ }
1279
+ },
1280
+ children: tr("linkEditorCommit")
1281
+ })
1282
+ })
1283
+ ]
1284
+ }) : /* @__PURE__ */ jsxs4(Fragment3, {
1285
+ children: [
1286
+ /* @__PURE__ */ jsxs4("div", {
1287
+ className: "c-rte-link-editor-link-input",
1288
+ children: [
1289
+ /* @__PURE__ */ jsxs4("div", {
1290
+ className: "c-rte-link-editor-link-preview",
1291
+ children: [
1292
+ /* @__PURE__ */ jsx8("a", {
1293
+ href: linkUrl,
1294
+ target: "_blank",
1295
+ rel: "noopener noreferrer",
1296
+ children: linkUrl
1297
+ }),
1298
+ rel || target ? /* @__PURE__ */ jsxs4("div", {
1299
+ className: "c-rte-link-editor-preview-attrs",
1300
+ children: [
1301
+ rel && /* @__PURE__ */ jsx8("div", {
1302
+ className: "c-rte-link-editor-preview-attr",
1303
+ children: rel
1304
+ }),
1305
+ target && /* @__PURE__ */ jsx8("div", {
1306
+ className: "c-rte-link-editor-preview-attr",
1307
+ children: target
1308
+ })
1309
+ ]
1310
+ }) : null
1311
+ ]
1312
+ }),
1313
+ /* @__PURE__ */ jsx8("div", {
1314
+ children: /* @__PURE__ */ jsx8(IconButton, {
1315
+ size: "sm",
1316
+ tabIndex: 0,
1317
+ onMouseDown: (event) => event.preventDefault(),
1318
+ onClick: () => setEditMode(true),
1319
+ "aria-label": tr("linkEditorEdit"),
1320
+ "data-testid": "link-editor-edit",
1321
+ children: /* @__PURE__ */ jsx8(Icon.Edit, {})
1322
+ })
1323
+ })
1324
+ ]
1325
+ }),
1326
+ /* @__PURE__ */ jsx8("div", {
1327
+ children: /* @__PURE__ */ jsx8(LinkPreview, {
1328
+ url: linkUrl
1329
+ })
1330
+ })
1331
+ ]
1332
+ })
1333
+ });
1334
+ }
1335
+ function useFloatingLinkEditorToolbar(editor, anchorElem) {
1336
+ const [activeEditor, setActiveEditor] = useState5(editor);
1337
+ const [isLink, setIsLink] = useState5(false);
1338
+ const updateToolbar = useCallback(() => {
1339
+ const selection = $getSelection3();
1340
+ if ($isRangeSelection(selection)) {
1341
+ const node = getSelectedNode(selection);
1342
+ const linkParent = $findMatchingParent(node, $isLinkNode2);
1343
+ const autoLinkParent = $findMatchingParent(node, $isAutoLinkNode);
1344
+ if (linkParent != null && autoLinkParent == null) {
1345
+ setIsLink(true);
1346
+ } else {
1347
+ setIsLink(false);
1348
+ }
1349
+ }
1350
+ }, []);
1351
+ useEffect4(() => {
1352
+ return editor.registerCommand(
1353
+ SELECTION_CHANGE_COMMAND,
1354
+ (_payload, newEditor) => {
1355
+ updateToolbar();
1356
+ setActiveEditor(newEditor);
1357
+ return false;
1358
+ },
1359
+ COMMAND_PRIORITY_CRITICAL
1360
+ );
1361
+ }, [editor, updateToolbar]);
1362
+ return isLink ? createPortal2(
1363
+ /* @__PURE__ */ jsx8(FloatingLinkEditor, {
1364
+ editor: activeEditor,
1365
+ isLink,
1366
+ anchorElem,
1367
+ setIsLink
1368
+ }),
1369
+ anchorElem
1370
+ ) : null;
1371
+ }
1372
+ function FloatingLinkEditorPlugin({
1373
+ anchorElem = document.body
1374
+ }) {
1375
+ const [editor] = useLexicalComposerContext4();
1376
+ return useFloatingLinkEditorToolbar(editor, anchorElem);
1377
+ }
1378
+
1379
+ // src/rich-text-editor/plugins/FloatingTextFormatToolbarPlugin/index.tsx
1380
+ import { useCallback as useCallback2, useEffect as useEffect5, useRef as useRef3, useState as useState6 } from "react";
1381
+ import "react";
1382
+ import {
1383
+ $getSelection as $getSelection4,
1384
+ $isRangeSelection as $isRangeSelection2,
1385
+ $isTextNode as $isTextNode4,
1386
+ COMMAND_PRIORITY_LOW as COMMAND_PRIORITY_LOW2,
1387
+ FORMAT_TEXT_COMMAND,
1388
+ SELECTION_CHANGE_COMMAND as SELECTION_CHANGE_COMMAND2
1389
+ } from "lexical";
1390
+ import { createPortal as createPortal3 } from "react-dom";
1391
+ import { $isCodeHighlightNode } from "@lexical/code";
1392
+ import { $isLinkNode as $isLinkNode3, TOGGLE_LINK_COMMAND as TOGGLE_LINK_COMMAND2 } from "@lexical/link";
1393
+ import { useLexicalComposerContext as useLexicalComposerContext5 } from "@lexical/react/LexicalComposerContext";
1394
+ import { mergeRegister as mergeRegister2 } from "@lexical/utils";
1395
+
1396
+ // src/rich-text-editor/utils/environment.ts
1397
+ var IS_APPLE = typeof navigator !== "undefined" && /Mac|iPod|iPhone|iPad/.test(navigator.platform);
1398
+
1399
+ // src/rich-text-editor/utils/getDOMRangeRect.ts
1400
+ function getDOMRangeRect(nativeSelection, rootElement) {
1401
+ const domRange = nativeSelection.getRangeAt(0);
1402
+ let rect;
1403
+ if (nativeSelection.anchorNode === rootElement) {
1404
+ let inner = rootElement;
1405
+ while (inner.firstElementChild != null) {
1406
+ inner = inner.firstElementChild;
1407
+ }
1408
+ rect = inner.getBoundingClientRect();
1409
+ } else {
1410
+ if ("getBoundingClientRect" in domRange) {
1411
+ rect = domRange.getBoundingClientRect();
1412
+ } else {
1413
+ return {
1414
+ height: 0,
1415
+ width: 0,
1416
+ x: 0,
1417
+ y: 0,
1418
+ bottom: 0,
1419
+ left: 0,
1420
+ top: 0,
1421
+ right: 0
1422
+ };
1423
+ }
1424
+ }
1425
+ return rect;
1426
+ }
1427
+
1428
+ // src/rich-text-editor/plugins/FloatingTextFormatToolbarPlugin/index.tsx
1429
+ import { jsx as jsx9, jsxs as jsxs5 } from "react/jsx-runtime";
1430
+ function TextFormatFloatingToolbar({
1431
+ editor,
1432
+ anchorElem,
1433
+ isLink,
1434
+ isBold,
1435
+ isItalic,
1436
+ isUnderline,
1437
+ isCode,
1438
+ isStrikethrough,
1439
+ isSubscript,
1440
+ isSuperscript
1441
+ }) {
1442
+ const popupCharStylesEditorRef = useRef3(null);
1443
+ const tr = useTr();
1444
+ const insertLink = useCallback2(() => {
1445
+ if (!isLink) {
1446
+ editor.dispatchCommand(TOGGLE_LINK_COMMAND2, "https://");
1447
+ } else {
1448
+ editor.dispatchCommand(TOGGLE_LINK_COMMAND2, null);
1449
+ }
1450
+ }, [editor, isLink]);
1451
+ const updateTextFormatFloatingToolbar = useCallback2(() => {
1452
+ const selection = $getSelection4();
1453
+ const popupCharStylesEditorElem = popupCharStylesEditorRef.current;
1454
+ const nativeSelection = window.getSelection();
1455
+ if (popupCharStylesEditorElem === null) {
1456
+ return;
1457
+ }
1458
+ const rootElement = editor.getRootElement();
1459
+ if (selection !== null && nativeSelection !== null && !nativeSelection.isCollapsed && rootElement !== null && rootElement.contains(nativeSelection.anchorNode)) {
1460
+ const rangeRect = getDOMRangeRect(nativeSelection, rootElement);
1461
+ setFloatingElemPosition(rangeRect, popupCharStylesEditorElem, anchorElem);
1462
+ }
1463
+ }, [editor, anchorElem]);
1464
+ useEffect5(() => {
1465
+ const scrollerElem = anchorElem.parentElement;
1466
+ const update = () => {
1467
+ editor.getEditorState().read(() => {
1468
+ updateTextFormatFloatingToolbar();
1469
+ });
1470
+ };
1471
+ window.addEventListener("resize", update);
1472
+ if (scrollerElem) {
1473
+ scrollerElem.addEventListener("scroll", update);
1474
+ }
1475
+ return () => {
1476
+ window.removeEventListener("resize", update);
1477
+ if (scrollerElem) {
1478
+ scrollerElem.removeEventListener("scroll", update);
1479
+ }
1480
+ };
1481
+ }, [editor, updateTextFormatFloatingToolbar, anchorElem]);
1482
+ useEffect5(() => {
1483
+ editor.getEditorState().read(() => {
1484
+ updateTextFormatFloatingToolbar();
1485
+ });
1486
+ return mergeRegister2(
1487
+ editor.registerUpdateListener(({ editorState }) => {
1488
+ editorState.read(() => {
1489
+ updateTextFormatFloatingToolbar();
1490
+ });
1491
+ }),
1492
+ editor.registerCommand(
1493
+ SELECTION_CHANGE_COMMAND2,
1494
+ () => {
1495
+ updateTextFormatFloatingToolbar();
1496
+ return false;
1497
+ },
1498
+ COMMAND_PRIORITY_LOW2
1499
+ )
1500
+ );
1501
+ }, [editor, updateTextFormatFloatingToolbar]);
1502
+ if (!editor.isEditable()) {
1503
+ return /* @__PURE__ */ jsx9("span", {});
1504
+ }
1505
+ return /* @__PURE__ */ jsxs5("div", {
1506
+ ref: popupCharStylesEditorRef,
1507
+ className: "c-rte-floating-text-format-tb-plugin",
1508
+ children: [
1509
+ /* @__PURE__ */ jsx9(IconButton, {
1510
+ onClick: () => {
1511
+ editor.dispatchCommand(FORMAT_TEXT_COMMAND, "bold");
1512
+ },
1513
+ style: { padding: 0, overflow: "hidden" },
1514
+ title: tr(IS_APPLE ? "actionFormatAsStrongTitleApple" : "actionFormatAsStrongTitle"),
1515
+ "aria-label": tr("actionFormatAsStrongLabel"),
1516
+ children: /* @__PURE__ */ jsx9("i", {
1517
+ className: `c-rte-icon-bold c-rte-floating-text-format-tb-plugin__format-icon ${isBold ? "selected" : ""}`
1518
+ })
1519
+ }),
1520
+ /* @__PURE__ */ jsx9(IconButton, {
1521
+ style: { padding: 0, overflow: "hidden" },
1522
+ onClick: () => {
1523
+ editor.dispatchCommand(FORMAT_TEXT_COMMAND, "italic");
1524
+ },
1525
+ title: tr("actionFormatAsEmphasizedTitle"),
1526
+ "aria-label": tr("actionFormatAsEmphasizedLabel"),
1527
+ children: /* @__PURE__ */ jsx9("i", {
1528
+ className: `c-rte-icon-italic c-rte-floating-text-format-tb-plugin__format-icon ${isItalic ? "selected" : ""}`
1529
+ })
1530
+ }),
1531
+ /* @__PURE__ */ jsx9(IconButton, {
1532
+ style: { padding: 0, overflow: "hidden" },
1533
+ onClick: () => {
1534
+ editor.dispatchCommand(FORMAT_TEXT_COMMAND, "underline");
1535
+ },
1536
+ title: tr("actionFormatAsUnderlinedTitle"),
1537
+ "aria-label": tr("actionFormatAsUnderlinedLabel"),
1538
+ children: /* @__PURE__ */ jsx9("i", {
1539
+ className: `c-rte-icon-underline c-rte-floating-text-format-tb-plugin__format-icon ${isUnderline ? "selected" : ""}`
1540
+ })
1541
+ }),
1542
+ /* @__PURE__ */ jsx9(IconButton, {
1543
+ style: { padding: 0, overflow: "hidden" },
1544
+ onClick: () => {
1545
+ editor.dispatchCommand(FORMAT_TEXT_COMMAND, "code");
1546
+ },
1547
+ "aria-label": tr("actionInsertCodeBlock"),
1548
+ children: /* @__PURE__ */ jsx9("i", {
1549
+ className: `c-rte-icon-code c-rte-floating-text-format-tb-plugin__format-icon ${isCode ? "selected" : ""}`
1550
+ })
1551
+ }),
1552
+ /* @__PURE__ */ jsx9(IconButton, {
1553
+ style: { padding: 0, overflow: "hidden" },
1554
+ onClick: insertLink,
1555
+ "aria-label": tr("actionInsertlink"),
1556
+ children: /* @__PURE__ */ jsx9("i", {
1557
+ className: `c-rte-icon-link c-rte-floating-text-format-tb-plugin__format-icon ${isLink ? "selected" : ""}`
1558
+ })
1559
+ }),
1560
+ /* @__PURE__ */ jsx9(IconButton, {
1561
+ style: { padding: 0, overflow: "hidden" },
1562
+ onClick: () => {
1563
+ editor.dispatchCommand(FORMAT_TEXT_COMMAND, "strikethrough");
1564
+ },
1565
+ title: tr("actionFormatWithStrikethroughTitle"),
1566
+ "aria-label": tr("actionFormatWithStrikethroughLabel"),
1567
+ children: /* @__PURE__ */ jsx9("i", {
1568
+ className: `c-rte-icon-strikethrough c-rte-floating-text-format-tb-plugin__format-icon ${isStrikethrough ? "selected" : ""}`
1569
+ })
1570
+ }),
1571
+ /* @__PURE__ */ jsx9(IconButton, {
1572
+ style: { padding: 0, overflow: "hidden" },
1573
+ onClick: () => {
1574
+ editor.dispatchCommand(FORMAT_TEXT_COMMAND, "subscript");
1575
+ },
1576
+ title: tr("actionFormatWithSubscriptTitle"),
1577
+ "aria-label": tr("actionFormatWithSubscriptLabel"),
1578
+ children: /* @__PURE__ */ jsx9("i", {
1579
+ className: `c-rte-icon-subscript c-rte-floating-text-format-tb-plugin__format-icon ${isSubscript ? "selected" : ""}`
1580
+ })
1581
+ }),
1582
+ /* @__PURE__ */ jsx9(IconButton, {
1583
+ style: { padding: 0, overflow: "hidden" },
1584
+ onClick: () => {
1585
+ editor.dispatchCommand(FORMAT_TEXT_COMMAND, "superscript");
1586
+ },
1587
+ title: tr("actionFormatWithSuperscriptTitle"),
1588
+ "aria-label": tr("actionFormatWithSuperscriptLabel"),
1589
+ children: /* @__PURE__ */ jsx9("i", {
1590
+ className: `c-rte-icon-superscript c-rte-floating-text-format-tb-plugin__format-icon ${isSuperscript ? "selected" : ""}`
1591
+ })
1592
+ })
1593
+ ]
1594
+ });
1595
+ }
1596
+ function useFloatingTextFormatToolbar(editor, anchorElem) {
1597
+ const [isText, setIsText] = useState6(false);
1598
+ const [isLink, setIsLink] = useState6(false);
1599
+ const [isBold, setIsBold] = useState6(false);
1600
+ const [isItalic, setIsItalic] = useState6(false);
1601
+ const [isUnderline, setIsUnderline] = useState6(false);
1602
+ const [isStrikethrough, setIsStrikethrough] = useState6(false);
1603
+ const [isSubscript, setIsSubscript] = useState6(false);
1604
+ const [isSuperscript, setIsSuperscript] = useState6(false);
1605
+ const [isCode, setIsCode] = useState6(false);
1606
+ const updatePopup = useCallback2(() => {
1607
+ editor.getEditorState().read(() => {
1608
+ if (editor.isComposing()) {
1609
+ return;
1610
+ }
1611
+ const selection = $getSelection4();
1612
+ const nativeSelection = window.getSelection();
1613
+ const rootElement = editor.getRootElement();
1614
+ if (nativeSelection !== null && (!$isRangeSelection2(selection) || rootElement === null || !rootElement.contains(nativeSelection.anchorNode))) {
1615
+ setIsText(false);
1616
+ return;
1617
+ }
1618
+ if (!$isRangeSelection2(selection)) {
1619
+ return;
1620
+ }
1621
+ const node = getSelectedNode(selection);
1622
+ setIsBold(selection.hasFormat("bold"));
1623
+ setIsItalic(selection.hasFormat("italic"));
1624
+ setIsUnderline(selection.hasFormat("underline"));
1625
+ setIsStrikethrough(selection.hasFormat("strikethrough"));
1626
+ setIsSubscript(selection.hasFormat("subscript"));
1627
+ setIsSuperscript(selection.hasFormat("superscript"));
1628
+ setIsCode(selection.hasFormat("code"));
1629
+ const parent2 = node.getParent();
1630
+ if ($isLinkNode3(parent2) || $isLinkNode3(node)) {
1631
+ setIsLink(true);
1632
+ } else {
1633
+ setIsLink(false);
1634
+ }
1635
+ if (!$isCodeHighlightNode(selection.anchor.getNode()) && selection.getTextContent() !== "") {
1636
+ setIsText($isTextNode4(node));
1637
+ } else {
1638
+ setIsText(false);
1639
+ }
1640
+ });
1641
+ }, [editor]);
1642
+ useEffect5(() => {
1643
+ document.addEventListener("selectionchange", updatePopup);
1644
+ return () => {
1645
+ document.removeEventListener("selectionchange", updatePopup);
1646
+ };
1647
+ }, [updatePopup]);
1648
+ useEffect5(() => {
1649
+ return mergeRegister2(
1650
+ editor.registerUpdateListener(() => {
1651
+ updatePopup();
1652
+ }),
1653
+ editor.registerRootListener(() => {
1654
+ if (editor.getRootElement() === null) {
1655
+ setIsText(false);
1656
+ }
1657
+ })
1658
+ );
1659
+ }, [editor, updatePopup]);
1660
+ if (!isText || isLink) {
1661
+ return null;
1662
+ }
1663
+ return createPortal3(
1664
+ /* @__PURE__ */ jsx9(TextFormatFloatingToolbar, {
1665
+ editor,
1666
+ anchorElem,
1667
+ isLink,
1668
+ isBold,
1669
+ isItalic,
1670
+ isStrikethrough,
1671
+ isSubscript,
1672
+ isSuperscript,
1673
+ isUnderline,
1674
+ isCode
1675
+ }),
1676
+ anchorElem
1677
+ );
1678
+ }
1679
+ function FloatingTextFormatToolbarPlugin({
1680
+ anchorElem = document.body
1681
+ }) {
1682
+ const [editor] = useLexicalComposerContext5();
1683
+ return useFloatingTextFormatToolbar(editor, anchorElem);
1684
+ }
1685
+
1686
+ // src/rich-text-editor/plugins/LinkPlugin/index.tsx
1687
+ import "react";
1688
+ import { LinkPlugin as LexicalLinkPlugin } from "@lexical/react/LexicalLinkPlugin";
1689
+ import { jsx as jsx10 } from "react/jsx-runtime";
1690
+ function LinkPlugin() {
1691
+ return /* @__PURE__ */ jsx10(LexicalLinkPlugin, {
1692
+ validateUrl
1693
+ });
1694
+ }
1695
+
1696
+ // src/rich-text-editor/plugins/ListMaxIndentLevelPlugin/index.ts
1697
+ import { useEffect as useEffect6 } from "react";
1698
+ import {
1699
+ $getSelection as $getSelection5,
1700
+ $isElementNode as $isElementNode2,
1701
+ $isRangeSelection as $isRangeSelection3,
1702
+ COMMAND_PRIORITY_CRITICAL as COMMAND_PRIORITY_CRITICAL2,
1703
+ INDENT_CONTENT_COMMAND
1704
+ } from "lexical";
1705
+ import { $getListDepth, $isListItemNode as $isListItemNode2, $isListNode as $isListNode2 } from "@lexical/list";
1706
+ import { useLexicalComposerContext as useLexicalComposerContext6 } from "@lexical/react/LexicalComposerContext";
1707
+ function getElementNodesInSelection(selection) {
1708
+ const nodesInSelection = selection.getNodes();
1709
+ if (nodesInSelection.length === 0) {
1710
+ return /* @__PURE__ */ new Set([selection.anchor.getNode().getParentOrThrow(), selection.focus.getNode().getParentOrThrow()]);
1711
+ }
1712
+ return new Set(nodesInSelection.map((n) => $isElementNode2(n) ? n : n.getParentOrThrow()));
1713
+ }
1714
+ function isIndentPermitted(maxDepth) {
1715
+ const selection = $getSelection5();
1716
+ if (!$isRangeSelection3(selection)) {
1717
+ return false;
1718
+ }
1719
+ const elementNodesInSelection = getElementNodesInSelection(selection);
1720
+ let totalDepth = 0;
1721
+ for (const elementNode of elementNodesInSelection) {
1722
+ if ($isListNode2(elementNode)) {
1723
+ totalDepth = Math.max($getListDepth(elementNode) + 1, totalDepth);
1724
+ } else if ($isListItemNode2(elementNode)) {
1725
+ const parent2 = elementNode.getParent();
1726
+ if (!$isListNode2(parent2)) {
1727
+ throw new Error("ListMaxIndentLevelPlugin: A ListItemNode must have a ListNode for a parent.");
1728
+ }
1729
+ totalDepth = Math.max($getListDepth(parent2) + 1, totalDepth);
1730
+ }
1731
+ }
1732
+ return totalDepth <= maxDepth;
1733
+ }
1734
+ function ListMaxIndentLevelPlugin({ maxDepth }) {
1735
+ const [editor] = useLexicalComposerContext6();
1736
+ useEffect6(() => {
1737
+ return editor.registerCommand(
1738
+ INDENT_CONTENT_COMMAND,
1739
+ () => !isIndentPermitted(maxDepth ?? 7),
1740
+ COMMAND_PRIORITY_CRITICAL2
1741
+ );
1742
+ }, [editor, maxDepth]);
1743
+ return null;
1744
+ }
1745
+
1746
+ // src/rich-text-editor/plugins/MaxLengthPlugin/index.tsx
1747
+ import { useEffect as useEffect7 } from "react";
1748
+ import { $getSelection as $getSelection6, $isRangeSelection as $isRangeSelection4 } from "lexical";
1749
+ import { useLexicalComposerContext as useLexicalComposerContext7 } from "@lexical/react/LexicalComposerContext";
1750
+ import { trimTextContentFromAnchor } from "@lexical/selection";
1751
+ import { $restoreEditorState } from "@lexical/utils";
1752
+
1753
+ // src/rich-text-editor/model/to-text.ts
1754
+ function trim(str) {
1755
+ if (!str) {
1756
+ return "";
1757
+ }
1758
+ return str.replace(/^(\r|\n)+/, "").replace(/(\r|\n)+$/, "");
1759
+ }
1760
+ function toText(model, options) {
1761
+ function getTextFromNode(node) {
1762
+ if (!node) {
1763
+ return "";
1764
+ }
1765
+ let childrenText = "";
1766
+ if (node.children) {
1767
+ childrenText = node.children.reduce((acc, n) => acc + getTextFromNode(n), "");
1768
+ }
1769
+ let content = "";
1770
+ content += node.textContent || childrenText || "";
1771
+ if (node.kind === "block") {
1772
+ content = `
1773
+ ${content}
1774
+ `;
1775
+ } else if (options?.keepLineBreaks && node.type === "line-break") {
1776
+ content += "\n";
1777
+ }
1778
+ return content;
1779
+ }
1780
+ if (Array.isArray(model)) {
1781
+ return model.map(getTextFromNode).join("").trimStart().trimEnd();
1782
+ }
1783
+ return trim(getTextFromNode(model));
1784
+ }
1785
+
1786
+ // src/rich-text-editor/plugins/MaxLengthPlugin/index.tsx
1787
+ function MaxLengthPlugin({ maxLength }) {
1788
+ const [editor] = useLexicalComposerContext7();
1789
+ useEffect7(() => {
1790
+ let lastRestoredEditorState = null;
1791
+ return editor.registerUpdateListener(({ editorState, prevEditorState }) => {
1792
+ editor.update(() => {
1793
+ const selection = $getSelection6();
1794
+ if (!$isRangeSelection4(selection) || !selection.isCollapsed()) {
1795
+ return;
1796
+ }
1797
+ const prevTextContent = toText(lexicalToCrystallizeRichText({ editor, editorState: prevEditorState }));
1798
+ const textContent = toText(lexicalToCrystallizeRichText({ editor, editorState }));
1799
+ if (prevTextContent !== textContent) {
1800
+ const textLength = textContent.length;
1801
+ const delCount = textLength - maxLength;
1802
+ const anchor = selection.anchor;
1803
+ if (delCount > 0) {
1804
+ if (prevTextContent.length === maxLength && lastRestoredEditorState !== prevEditorState) {
1805
+ lastRestoredEditorState = prevEditorState;
1806
+ $restoreEditorState(editor, prevEditorState);
1807
+ } else {
1808
+ trimTextContentFromAnchor(editor, anchor, delCount);
1809
+ }
1810
+ }
1811
+ }
1812
+ });
1813
+ });
1814
+ }, [editor, maxLength]);
1815
+ return null;
1816
+ }
1817
+
1818
+ // src/rich-text-editor/plugins/TabFocusPlugin/index.tsx
1819
+ import { useEffect as useEffect8 } from "react";
1820
+ import { $getSelection as $getSelection7, $isRangeSelection as $isRangeSelection5, $setSelection as $setSelection2, FOCUS_COMMAND } from "lexical";
1821
+ import { useLexicalComposerContext as useLexicalComposerContext8 } from "@lexical/react/LexicalComposerContext";
1822
+ var COMMAND_PRIORITY_LOW3 = 1;
1823
+ var TAB_TO_FOCUS_INTERVAL = 100;
1824
+ var lastTabKeyDownTimestamp = 0;
1825
+ var hasRegisteredKeyDownListener = false;
1826
+ function registerKeyTimeStampTracker() {
1827
+ window.addEventListener(
1828
+ "keydown",
1829
+ (event) => {
1830
+ if (event.keyCode === 9) {
1831
+ lastTabKeyDownTimestamp = event.timeStamp;
1832
+ }
1833
+ },
1834
+ true
1835
+ );
1836
+ }
1837
+ function TabFocusPlugin() {
1838
+ const [editor] = useLexicalComposerContext8();
1839
+ useEffect8(() => {
1840
+ if (!hasRegisteredKeyDownListener) {
1841
+ registerKeyTimeStampTracker();
1842
+ hasRegisteredKeyDownListener = true;
1843
+ }
1844
+ return editor.registerCommand(
1845
+ FOCUS_COMMAND,
1846
+ (event) => {
1847
+ const selection = $getSelection7();
1848
+ if ($isRangeSelection5(selection)) {
1849
+ if (lastTabKeyDownTimestamp + TAB_TO_FOCUS_INTERVAL > event.timeStamp) {
1850
+ $setSelection2(selection.clone());
1851
+ }
1852
+ }
1853
+ return false;
1854
+ },
1855
+ COMMAND_PRIORITY_LOW3
1856
+ );
1857
+ }, [editor]);
1858
+ return null;
1859
+ }
1860
+
1861
+ // src/rich-text-editor/plugins/TableActionMenuPlugin/index.tsx
1862
+ import { useCallback as useCallback3, useEffect as useEffect9, useRef as useRef4, useState as useState7 } from "react";
1863
+ import { $getRoot as $getRoot3, $getSelection as $getSelection8, $isRangeSelection as $isRangeSelection6, DEPRECATED_$isGridSelection } from "lexical";
1864
+ import { createPortal as createPortal4 } from "react-dom";
1865
+ import { useLexicalComposerContext as useLexicalComposerContext9 } from "@lexical/react/LexicalComposerContext";
1866
+ import useLexicalEditable from "@lexical/react/useLexicalEditable";
1867
+ import {
1868
+ $deleteTableColumn,
1869
+ $getElementGridForTableNode,
1870
+ $getTableCellNodeFromLexicalNode,
1871
+ $getTableColumnIndexFromTableCellNode,
1872
+ $getTableNodeFromLexicalNodeOrThrow,
1873
+ $getTableRowIndexFromTableCellNode,
1874
+ $insertTableColumn,
1875
+ $insertTableRow,
1876
+ $isTableCellNode as $isTableCellNode2,
1877
+ $isTableNode as $isTableNode2,
1878
+ $isTableRowNode as $isTableRowNode2,
1879
+ $removeTableRowAtIndex,
1880
+ getTableSelectionFromTableElement,
1881
+ TableCellHeaderStates,
1882
+ TableCellNode as TableCellNode2
1883
+ } from "@lexical/table";
1884
+ import { Fragment as Fragment4, jsx as jsx11, jsxs as jsxs6 } from "react/jsx-runtime";
1885
+ function TableActionMenu({ tableCellNode: _tableCellNode, tableStats }) {
1886
+ const [editor] = useLexicalComposerContext9();
1887
+ const [tableCellNode, updateTableCellNode] = useState7(_tableCellNode);
1888
+ const [selectionCounts, updateSelectionCounts] = useState7({
1889
+ columns: 1,
1890
+ rows: 1
1891
+ });
1892
+ const tr = useTr();
1893
+ useEffect9(() => {
1894
+ return editor.registerMutationListener(TableCellNode2, (nodeMutations) => {
1895
+ const nodeUpdated = nodeMutations.get(tableCellNode.getKey()) === "updated";
1896
+ if (nodeUpdated) {
1897
+ editor.getEditorState().read(() => {
1898
+ updateTableCellNode(tableCellNode.getLatest());
1899
+ });
1900
+ }
1901
+ });
1902
+ }, [editor, tableCellNode]);
1903
+ useEffect9(() => {
1904
+ editor.getEditorState().read(() => {
1905
+ const selection = $getSelection8();
1906
+ if (DEPRECATED_$isGridSelection(selection)) {
1907
+ const selectionShape = selection.getShape();
1908
+ updateSelectionCounts({
1909
+ columns: selectionShape.toX - selectionShape.fromX + 1,
1910
+ rows: selectionShape.toY - selectionShape.fromY + 1
1911
+ });
1912
+ }
1913
+ });
1914
+ }, [editor]);
1915
+ const clearTableSelection = useCallback3(() => {
1916
+ editor.update(() => {
1917
+ if (tableCellNode.isAttached()) {
1918
+ const tableNode = $getTableNodeFromLexicalNodeOrThrow(tableCellNode);
1919
+ const tableElement = editor.getElementByKey(tableNode.getKey());
1920
+ if (!tableElement) {
1921
+ throw new Error("Expected to find tableElement in DOM");
1922
+ }
1923
+ const tableSelection = getTableSelectionFromTableElement(tableElement);
1924
+ if (tableSelection !== null) {
1925
+ tableSelection.clearHighlight();
1926
+ }
1927
+ tableNode.markDirty();
1928
+ updateTableCellNode(tableCellNode.getLatest());
1929
+ }
1930
+ const rootNode = $getRoot3();
1931
+ rootNode.selectStart();
1932
+ });
1933
+ }, [editor, tableCellNode]);
1934
+ const insertTableRowAtSelection = useCallback3(
1935
+ (shouldInsertAfter) => {
1936
+ editor.update(() => {
1937
+ const selection = $getSelection8();
1938
+ const tableNode = $getTableNodeFromLexicalNodeOrThrow(tableCellNode);
1939
+ let tableRowIndex;
1940
+ if (DEPRECATED_$isGridSelection(selection)) {
1941
+ const selectionShape = selection.getShape();
1942
+ tableRowIndex = shouldInsertAfter ? selectionShape.toY : selectionShape.fromY;
1943
+ } else {
1944
+ tableRowIndex = $getTableRowIndexFromTableCellNode(tableCellNode);
1945
+ }
1946
+ const grid = $getElementGridForTableNode(editor, tableNode);
1947
+ $insertTableRow(tableNode, tableRowIndex, shouldInsertAfter, selectionCounts.rows, grid);
1948
+ clearTableSelection();
1949
+ });
1950
+ },
1951
+ [editor, tableCellNode, selectionCounts.rows, clearTableSelection]
1952
+ );
1953
+ const insertTableColumnAtSelection = useCallback3(
1954
+ (shouldInsertAfter) => {
1955
+ editor.update(() => {
1956
+ const selection = $getSelection8();
1957
+ const tableNode = $getTableNodeFromLexicalNodeOrThrow(tableCellNode);
1958
+ let tableColumnIndex;
1959
+ if (DEPRECATED_$isGridSelection(selection)) {
1960
+ const selectionShape = selection.getShape();
1961
+ tableColumnIndex = shouldInsertAfter ? selectionShape.toX : selectionShape.fromX;
1962
+ } else {
1963
+ tableColumnIndex = $getTableColumnIndexFromTableCellNode(tableCellNode);
1964
+ }
1965
+ const grid = $getElementGridForTableNode(editor, tableNode);
1966
+ $insertTableColumn(tableNode, tableColumnIndex, shouldInsertAfter, selectionCounts.columns, grid);
1967
+ clearTableSelection();
1968
+ });
1969
+ },
1970
+ [editor, tableCellNode, selectionCounts.columns, clearTableSelection]
1971
+ );
1972
+ const deleteTableRowAtSelection = useCallback3(() => {
1973
+ editor.update(() => {
1974
+ const tableNode = $getTableNodeFromLexicalNodeOrThrow(tableCellNode);
1975
+ const tableRowIndex = $getTableRowIndexFromTableCellNode(tableCellNode);
1976
+ $removeTableRowAtIndex(tableNode, tableRowIndex);
1977
+ clearTableSelection();
1978
+ });
1979
+ }, [editor, tableCellNode, clearTableSelection]);
1980
+ const deleteTableAtSelection = useCallback3(() => {
1981
+ editor.update(() => {
1982
+ const tableNode = $getTableNodeFromLexicalNodeOrThrow(tableCellNode);
1983
+ tableNode.remove();
1984
+ clearTableSelection();
1985
+ });
1986
+ }, [editor, tableCellNode, clearTableSelection]);
1987
+ const deleteTableColumnAtSelection = useCallback3(() => {
1988
+ editor.update(() => {
1989
+ const tableNode = $getTableNodeFromLexicalNodeOrThrow(tableCellNode);
1990
+ const tableColumnIndex = $getTableColumnIndexFromTableCellNode(tableCellNode);
1991
+ $deleteTableColumn(tableNode, tableColumnIndex);
1992
+ clearTableSelection();
1993
+ });
1994
+ }, [editor, tableCellNode, clearTableSelection]);
1995
+ const toggleTableRowIsHeader = useCallback3(() => {
1996
+ editor.update(() => {
1997
+ const tableNode = $getTableNodeFromLexicalNodeOrThrow(tableCellNode);
1998
+ const tableRowIndex = $getTableRowIndexFromTableCellNode(tableCellNode);
1999
+ const tableRows = tableNode.getChildren();
2000
+ if (tableRowIndex >= tableRows.length || tableRowIndex < 0) {
2001
+ throw new Error("Expected table cell to be inside of table row.");
2002
+ }
2003
+ const tableRow = tableRows[tableRowIndex];
2004
+ if (!$isTableRowNode2(tableRow)) {
2005
+ throw new Error("Expected table row");
2006
+ }
2007
+ tableRow.getChildren().forEach((tableCell) => {
2008
+ if (!$isTableCellNode2(tableCell)) {
2009
+ throw new Error("Expected table cell");
2010
+ }
2011
+ tableCell.toggleHeaderStyle(TableCellHeaderStates.ROW);
2012
+ });
2013
+ clearTableSelection();
2014
+ });
2015
+ }, [editor, tableCellNode, clearTableSelection]);
2016
+ const toggleTableColumnIsHeader = useCallback3(() => {
2017
+ editor.update(() => {
2018
+ const tableNode = $getTableNodeFromLexicalNodeOrThrow(tableCellNode);
2019
+ const tableColumnIndex = $getTableColumnIndexFromTableCellNode(tableCellNode);
2020
+ const tableRows = tableNode.getChildren();
2021
+ for (let r = 0; r < tableRows.length; r++) {
2022
+ const tableRow = tableRows[r];
2023
+ if (!$isTableRowNode2(tableRow)) {
2024
+ throw new Error("Expected table row");
2025
+ }
2026
+ const tableCells = tableRow.getChildren();
2027
+ if (tableColumnIndex >= tableCells.length || tableColumnIndex < 0) {
2028
+ throw new Error("Expected table cell to be inside of table row.");
2029
+ }
2030
+ const tableCell = tableCells[tableColumnIndex];
2031
+ if (!$isTableCellNode2(tableCell)) {
2032
+ throw new Error("Expected table cell");
2033
+ }
2034
+ tableCell.toggleHeaderStyle(TableCellHeaderStates.COLUMN);
2035
+ }
2036
+ clearTableSelection();
2037
+ });
2038
+ }, [editor, tableCellNode, clearTableSelection]);
2039
+ return /* @__PURE__ */ jsxs6(Fragment4, {
2040
+ children: [
2041
+ /* @__PURE__ */ jsx11(DropdownMenu.Item, {
2042
+ onSelect: () => insertTableRowAtSelection(false),
2043
+ children: tr("actionTableInsertRowsAbove", selectionCounts.rows)
2044
+ }),
2045
+ /* @__PURE__ */ jsx11(DropdownMenu.Item, {
2046
+ onSelect: () => insertTableRowAtSelection(true),
2047
+ children: tr("actionTableInsertRowsBelow", selectionCounts.rows)
2048
+ }),
2049
+ /* @__PURE__ */ jsx11(DropdownMenu.Item, {
2050
+ onSelect: () => insertTableColumnAtSelection(false),
2051
+ children: tr("actionTableInsertColumnsBefore", selectionCounts.columns)
2052
+ }),
2053
+ /* @__PURE__ */ jsx11(DropdownMenu.Item, {
2054
+ onSelect: () => insertTableColumnAtSelection(true),
2055
+ children: tr("actionTableInsertColumnsAfter", selectionCounts.columns)
2056
+ }),
2057
+ /* @__PURE__ */ jsx11(DropdownMenu.Item, {
2058
+ onSelect: () => toggleTableRowIsHeader(),
2059
+ children: tr(
2060
+ (tableCellNode.__headerState & TableCellHeaderStates.ROW) === TableCellHeaderStates.ROW ? "actionTableRemoveRowHeader" : "actionTableAddRowHeader"
2061
+ )
2062
+ }),
2063
+ /* @__PURE__ */ jsx11(DropdownMenu.Item, {
2064
+ onSelect: () => toggleTableColumnIsHeader(),
2065
+ children: tr(
2066
+ (tableCellNode.__headerState & TableCellHeaderStates.COLUMN) === TableCellHeaderStates.COLUMN ? "actionTableRemoveColumnHeader" : "actionTableAddColumnHeader"
2067
+ )
2068
+ }),
2069
+ /* @__PURE__ */ jsx11(DropdownMenu.Separator, {}),
2070
+ tableStats.columns > 1 && /* @__PURE__ */ jsx11(DropdownMenu.Item, {
2071
+ onSelect: () => deleteTableColumnAtSelection(),
2072
+ children: tr("actionTableDeleteColumn")
2073
+ }),
2074
+ tableStats.rows > 1 && /* @__PURE__ */ jsx11(DropdownMenu.Item, {
2075
+ onSelect: () => deleteTableRowAtSelection(),
2076
+ children: tr("actionTableDeleteRow")
2077
+ }),
2078
+ /* @__PURE__ */ jsx11(DropdownMenu.Item, {
2079
+ onSelect: () => deleteTableAtSelection(),
2080
+ children: tr("actionTableDeleteTable")
2081
+ })
2082
+ ]
2083
+ });
2084
+ }
2085
+ function TableCellActionMenuContainer({ anchorElem }) {
2086
+ const [editor] = useLexicalComposerContext9();
2087
+ const tr = useTr();
2088
+ const menuButtonRef = useRef4(null);
2089
+ const [isMenuOpen, setIsMenuOpen] = useState7(false);
2090
+ const [tableCellNode, setTableMenuCellNode] = useState7(null);
2091
+ const [tableStats, setTablestats] = useState7({ rows: 1, columns: 1 });
2092
+ const moveMenu = useCallback3(() => {
2093
+ if (isMenuOpen) {
2094
+ return;
2095
+ }
2096
+ const menu = menuButtonRef.current;
2097
+ const selection = $getSelection8();
2098
+ const nativeSelection = window.getSelection();
2099
+ const activeElement = document.activeElement;
2100
+ if (selection == null || menu == null) {
2101
+ setTableMenuCellNode(null);
2102
+ return;
2103
+ }
2104
+ const rootElement = editor.getRootElement();
2105
+ if ($isRangeSelection6(selection) && rootElement !== null && nativeSelection !== null && rootElement.contains(nativeSelection.anchorNode)) {
2106
+ const tableCellNodeFromSelection = $getTableCellNodeFromLexicalNode(selection.anchor.getNode());
2107
+ if (tableCellNodeFromSelection == null) {
2108
+ setTableMenuCellNode(null);
2109
+ return;
2110
+ }
2111
+ const tableCellParentNodeDOM = editor.getElementByKey(tableCellNodeFromSelection.getKey());
2112
+ if (tableCellParentNodeDOM == null) {
2113
+ setTableMenuCellNode(null);
2114
+ return;
2115
+ }
2116
+ setTableMenuCellNode(tableCellNodeFromSelection);
2117
+ let rows = 1;
2118
+ let columns = 1;
2119
+ const parentRowNode = tableCellNodeFromSelection.getParent();
2120
+ if ($isTableRowNode2(parentRowNode)) {
2121
+ const parentTableNode = parentRowNode.getParent();
2122
+ if ($isTableNode2(parentTableNode)) {
2123
+ rows = parentTableNode.getChildrenSize();
2124
+ columns = parentRowNode.getChildrenSize();
2125
+ }
2126
+ }
2127
+ setTablestats({
2128
+ rows,
2129
+ columns
2130
+ });
2131
+ } else if (!activeElement) {
2132
+ setTableMenuCellNode(null);
2133
+ }
2134
+ }, [editor, isMenuOpen]);
2135
+ useEffect9(() => {
2136
+ return editor.registerUpdateListener(() => {
2137
+ editor.getEditorState().read(() => {
2138
+ moveMenu();
2139
+ });
2140
+ });
2141
+ });
2142
+ useEffect9(() => {
2143
+ const menuButtonDOM = menuButtonRef.current;
2144
+ if (menuButtonDOM != null && tableCellNode != null) {
2145
+ const tableCellNodeDOM = editor.getElementByKey(tableCellNode.getKey());
2146
+ if (tableCellNodeDOM != null) {
2147
+ const tableCellRect = tableCellNodeDOM.getBoundingClientRect();
2148
+ const menuRect = menuButtonDOM.getBoundingClientRect();
2149
+ const anchorRect = anchorElem.getBoundingClientRect();
2150
+ const top = tableCellRect.top - anchorRect.top + 4;
2151
+ const left = tableCellRect.right - menuRect.width - 10 - anchorRect.left;
2152
+ menuButtonDOM.style.opacity = "1";
2153
+ menuButtonDOM.style.transform = `translate(${left}px, ${top}px)`;
2154
+ } else {
2155
+ menuButtonDOM.style.opacity = "0";
2156
+ menuButtonDOM.style.transform = "translate(-10000px, -10000px)";
2157
+ }
2158
+ }
2159
+ }, [menuButtonRef, tableCellNode, editor, anchorElem]);
2160
+ return /* @__PURE__ */ jsx11("div", {
2161
+ className: "c-rte-table-cell-action-button-container",
2162
+ ref: menuButtonRef,
2163
+ children: tableCellNode != null && /* @__PURE__ */ jsx11(DropdownMenu.Root, {
2164
+ onOpenChange: (isOpen) => setIsMenuOpen(isOpen),
2165
+ content: /* @__PURE__ */ jsx11(TableActionMenu, {
2166
+ tableCellNode,
2167
+ tableStats
2168
+ }),
2169
+ children: /* @__PURE__ */ jsx11(IconButton, {
2170
+ size: "xs",
2171
+ "aria-label": tr("actionTableOpenOptions"),
2172
+ children: /* @__PURE__ */ jsx11(Icon.Arrow, {})
2173
+ })
2174
+ })
2175
+ });
2176
+ }
2177
+ function TableActionMenuPlugin({
2178
+ anchorElem = document.body
2179
+ }) {
2180
+ const isEditable = useLexicalEditable();
2181
+ return createPortal4(isEditable ? /* @__PURE__ */ jsx11(TableCellActionMenuContainer, {
2182
+ anchorElem
2183
+ }) : null, anchorElem);
2184
+ }
2185
+
2186
+ // src/rich-text-editor/plugins/ToolbarPlugin/index.tsx
2187
+ import { useCallback as useCallback4, useEffect as useEffect10, useState as useState9 } from "react";
2188
+ import {
2189
+ $createParagraphNode as $createParagraphNode2,
2190
+ $getNodeByKey,
2191
+ $getRoot as $getRoot4,
2192
+ $getSelection as $getSelection9,
2193
+ $isRangeSelection as $isRangeSelection7,
2194
+ $isRootOrShadowRoot,
2195
+ $isTextNode as $isTextNode5,
2196
+ CAN_REDO_COMMAND,
2197
+ CAN_UNDO_COMMAND,
2198
+ COMMAND_PRIORITY_CRITICAL as COMMAND_PRIORITY_CRITICAL3,
2199
+ DEPRECATED_$isGridSelection as DEPRECATED_$isGridSelection2,
2200
+ FORMAT_TEXT_COMMAND as FORMAT_TEXT_COMMAND2,
2201
+ REDO_COMMAND,
2202
+ SELECTION_CHANGE_COMMAND as SELECTION_CHANGE_COMMAND3,
2203
+ UNDO_COMMAND
2204
+ } from "lexical";
2205
+ import {
2206
+ $createCodeNode as $createCodeNode2,
2207
+ $isCodeNode as $isCodeNode5,
2208
+ CODE_LANGUAGE_FRIENDLY_NAME_MAP,
2209
+ CODE_LANGUAGE_MAP,
2210
+ getLanguageFriendlyName as getLanguageFriendlyName2
2211
+ } from "@lexical/code";
2212
+ import { $isLinkNode as $isLinkNode4, TOGGLE_LINK_COMMAND as TOGGLE_LINK_COMMAND3 } from "@lexical/link";
2213
+ import {
2214
+ $isListNode as $isListNode3,
2215
+ INSERT_ORDERED_LIST_COMMAND,
2216
+ INSERT_UNORDERED_LIST_COMMAND,
2217
+ ListNode as ListNode2,
2218
+ REMOVE_LIST_COMMAND
2219
+ } from "@lexical/list";
2220
+ import { useLexicalComposerContext as useLexicalComposerContext11 } from "@lexical/react/LexicalComposerContext";
2221
+ import { $isDecoratorBlockNode } from "@lexical/react/LexicalDecoratorBlockNode";
2222
+ import { INSERT_HORIZONTAL_RULE_COMMAND } from "@lexical/react/LexicalHorizontalRuleNode";
2223
+ import { $createHeadingNode as $createHeadingNode2, $createQuoteNode as $createQuoteNode2, $isHeadingNode as $isHeadingNode2 } from "@lexical/rich-text";
2224
+ import { $selectAll, $setBlocksType } from "@lexical/selection";
2225
+ import {
2226
+ $findMatchingParent as $findMatchingParent2,
2227
+ $getNearestBlockElementAncestorOrThrow,
2228
+ $getNearestNodeOfType,
2229
+ mergeRegister as mergeRegister3
2230
+ } from "@lexical/utils";
2231
+
2232
+ // src/rich-text-editor/plugins/ActionsPlugin/index.tsx
2233
+ import { CLEAR_EDITOR_COMMAND } from "lexical";
2234
+ import { useLexicalComposerContext as useLexicalComposerContext10 } from "@lexical/react/LexicalComposerContext";
2235
+ import { jsx as jsx12, jsxs as jsxs7 } from "react/jsx-runtime";
2236
+ async function copyJson(editor) {
2237
+ const json = lexicalToCrystallizeRichText({ editor, editorState: editor.getEditorState() });
2238
+ try {
2239
+ await navigator.clipboard.writeText(JSON.stringify(json, null, 1));
2240
+ } catch (error) {
2241
+ console.warn("Copy failed", error);
2242
+ }
2243
+ }
2244
+ function ActionsPlugin({ append, prepend, disabled }) {
2245
+ const [editor] = useLexicalComposerContext10();
2246
+ const tr = useTr();
2247
+ return /* @__PURE__ */ jsxs7(ActionMenu, {
2248
+ children: [
2249
+ !prepend ? null : prepend.map((actionItem) => /* @__PURE__ */ jsx12(ActionMenu.Item, {
2250
+ onSelect: actionItem.action,
2251
+ className: actionItem.type === "danger" ? "danger" : "",
2252
+ disabled: actionItem.disabled,
2253
+ children: actionItem.title
2254
+ }, actionItem.title)),
2255
+ /* @__PURE__ */ jsx12(ActionMenu.Item, {
2256
+ onSelect: () => copyJson(editor),
2257
+ children: tr("actionCopyJSON")
2258
+ }),
2259
+ /* @__PURE__ */ jsx12(ActionMenu.Item, {
2260
+ disabled,
2261
+ className: "danger",
2262
+ onSelect: () => {
2263
+ editor.dispatchCommand(CLEAR_EDITOR_COMMAND, void 0);
2264
+ editor.focus();
2265
+ },
2266
+ children: tr("actionClear")
2267
+ }),
2268
+ !append ? null : append.map((actionItem) => /* @__PURE__ */ jsx12(ActionMenu.Item, {
2269
+ onSelect: actionItem.action,
2270
+ className: actionItem.type === "danger" ? "danger" : "",
2271
+ disabled: actionItem.disabled,
2272
+ children: actionItem.title
2273
+ }, actionItem.title))
2274
+ ]
2275
+ });
2276
+ }
2277
+
2278
+ // src/rich-text-editor/plugins/ToolbarPlugin/insert-table.tsx
2279
+ import { useState as useState8 } from "react";
2280
+ import { INSERT_TABLE_COMMAND } from "@lexical/table";
2281
+ import { jsx as jsx13, jsxs as jsxs8 } from "react/jsx-runtime";
2282
+ function InsertTableDialog({ activeEditor }) {
2283
+ const [rows, setRows] = useState8("5");
2284
+ const [columns, setColumns] = useState8("5");
2285
+ const tr = useTr();
2286
+ const onClick = () => {
2287
+ if (parseInt(rows) < 1 || parseInt(columns) < 1) {
2288
+ return;
2289
+ }
2290
+ activeEditor.dispatchCommand(INSERT_TABLE_COMMAND, {
2291
+ columns,
2292
+ rows,
2293
+ includeHeaders: {
2294
+ columns: false,
2295
+ rows: false
2296
+ }
2297
+ });
2298
+ };
2299
+ return /* @__PURE__ */ jsxs8("div", {
2300
+ className: "c-rte-insert-table",
2301
+ children: [
2302
+ /* @__PURE__ */ jsxs8("div", {
2303
+ className: "c-rte-insert-table__dimensions",
2304
+ children: [
2305
+ /* @__PURE__ */ jsx13(InputWithLabel, {
2306
+ label: tr("insertTableRows"),
2307
+ value: rows,
2308
+ placeholder: "0",
2309
+ type: "text",
2310
+ inputMode: "numeric",
2311
+ onChange: (e) => setRows(e.target.value)
2312
+ }),
2313
+ /* @__PURE__ */ jsx13("span", {
2314
+ className: "c-rte-insert-table__dimensions__separator"
2315
+ }),
2316
+ /* @__PURE__ */ jsx13(InputWithLabel, {
2317
+ type: "text",
2318
+ label: tr("insertTableColumns"),
2319
+ placeholder: "0",
2320
+ value: columns,
2321
+ inputMode: "numeric",
2322
+ onChange: (e) => setColumns(e.target.value)
2323
+ })
2324
+ ]
2325
+ }),
2326
+ /* @__PURE__ */ jsx13("div", {
2327
+ className: "c-rte-insert-table__actions",
2328
+ children: /* @__PURE__ */ jsx13(Button, {
2329
+ as: Dialog.Close,
2330
+ size: "sm",
2331
+ intent: "action",
2332
+ "aria-label": tr("insertTableCommit"),
2333
+ onClick,
2334
+ children: tr("insertTableCommit")
2335
+ })
2336
+ })
2337
+ ]
2338
+ });
2339
+ }
2340
+
2341
+ // src/rich-text-editor/plugins/ToolbarPlugin/index.tsx
2342
+ import { Fragment as Fragment5, jsx as jsx14, jsxs as jsxs9 } from "react/jsx-runtime";
2343
+ var headingTypeToBlockName = {
2344
+ h1: "Heading 1",
2345
+ h2: "Heading 2",
2346
+ h3: "Heading 3",
2347
+ h4: "Heading 4",
2348
+ h5: "Heading 5",
2349
+ h6: "Heading 6"
2350
+ };
2351
+ var headings = Object.keys(headingTypeToBlockName);
2352
+ var blockTypeToBlockName = {
2353
+ ...headingTypeToBlockName,
2354
+ bullet: "Bulleted List",
2355
+ check: "Check List",
2356
+ code: "Code Block",
2357
+ number: "Numbered List",
2358
+ paragraph: "Normal",
2359
+ quote: "Quote"
2360
+ };
2361
+ function getCodeLanguageOptions() {
2362
+ const options = [];
2363
+ for (const [lang, friendlyName] of Object.entries(CODE_LANGUAGE_FRIENDLY_NAME_MAP)) {
2364
+ options.push([lang, friendlyName]);
2365
+ }
2366
+ return options;
2367
+ }
2368
+ var CODE_LANGUAGE_OPTIONS = getCodeLanguageOptions();
2369
+ function dropDownActiveClass(active) {
2370
+ if (active)
2371
+ return "active dropdown-item-active";
2372
+ else
2373
+ return "";
2374
+ }
2375
+ function BlockFormatDropDown({
2376
+ editor,
2377
+ blockType,
2378
+ disabled = false
2379
+ }) {
2380
+ const formatParagraph = () => {
2381
+ if (blockType !== "paragraph") {
2382
+ editor.update(() => {
2383
+ const selection = $getSelection9();
2384
+ if ($isRangeSelection7(selection) || DEPRECATED_$isGridSelection2(selection))
2385
+ $setBlocksType(selection, () => $createParagraphNode2());
2386
+ });
2387
+ }
2388
+ };
2389
+ const formatHeading = (headingSize) => {
2390
+ if (blockType !== headingSize) {
2391
+ editor.update(() => {
2392
+ const selection = $getSelection9();
2393
+ if ($isRangeSelection7(selection) || DEPRECATED_$isGridSelection2(selection)) {
2394
+ $setBlocksType(selection, () => $createHeadingNode2(headingSize));
2395
+ }
2396
+ });
2397
+ }
2398
+ };
2399
+ const formatBulletList = () => {
2400
+ if (blockType !== "bullet") {
2401
+ editor.dispatchCommand(INSERT_UNORDERED_LIST_COMMAND, void 0);
2402
+ } else {
2403
+ editor.dispatchCommand(REMOVE_LIST_COMMAND, void 0);
2404
+ }
2405
+ };
2406
+ const formatNumberedList = () => {
2407
+ if (blockType !== "number") {
2408
+ editor.dispatchCommand(INSERT_ORDERED_LIST_COMMAND, void 0);
2409
+ } else {
2410
+ editor.dispatchCommand(REMOVE_LIST_COMMAND, void 0);
2411
+ }
2412
+ };
2413
+ const formatQuote = () => {
2414
+ if (blockType !== "quote") {
2415
+ editor.update(() => {
2416
+ const selection = $getSelection9();
2417
+ if ($isRangeSelection7(selection) || DEPRECATED_$isGridSelection2(selection)) {
2418
+ $setBlocksType(selection, () => $createQuoteNode2());
2419
+ } else {
2420
+ $setBlocksType($getRoot4().select(), () => $createQuoteNode2());
2421
+ }
2422
+ });
2423
+ }
2424
+ };
2425
+ const formatCode = () => {
2426
+ if (blockType !== "code") {
2427
+ editor.update(() => {
2428
+ let selection = $getSelection9();
2429
+ if ($isRangeSelection7(selection) || DEPRECATED_$isGridSelection2(selection)) {
2430
+ if (selection.isCollapsed()) {
2431
+ $setBlocksType(selection, () => $createCodeNode2());
2432
+ } else {
2433
+ const textContent = selection.getTextContent();
2434
+ const codeNode = $createCodeNode2();
2435
+ selection.insertNodes([codeNode]);
2436
+ selection = $getSelection9();
2437
+ if ($isRangeSelection7(selection))
2438
+ selection.insertRawText(textContent);
2439
+ }
2440
+ } else {
2441
+ $setBlocksType($getRoot4().select(), () => $createCodeNode2());
2442
+ }
2443
+ });
2444
+ }
2445
+ };
2446
+ return /* @__PURE__ */ jsx14(DropdownMenu.Root, {
2447
+ disabled,
2448
+ style: { zIndex: 1 },
2449
+ content: /* @__PURE__ */ jsxs9(Fragment5, {
2450
+ children: [
2451
+ /* @__PURE__ */ jsxs9(DropdownMenu.Item, {
2452
+ onClick: formatParagraph,
2453
+ children: [
2454
+ /* @__PURE__ */ jsx14("i", {
2455
+ className: `c-rte-icon-paragraph c-rte-toolbar__block-format__icon ${blockType === "paragraph" ? "selected" : ""}`
2456
+ }),
2457
+ /* @__PURE__ */ jsx14("span", {
2458
+ className: `c-rte-toolbar__block-format__text ${blockType === "paragraph" ? "selected" : ""}`,
2459
+ children: "Normal"
2460
+ })
2461
+ ]
2462
+ }),
2463
+ headings.map((headingSize) => /* @__PURE__ */ jsxs9(DropdownMenu.Item, {
2464
+ onClick: () => formatHeading(headingSize),
2465
+ children: [
2466
+ /* @__PURE__ */ jsx14("i", {
2467
+ className: `c-rte-icon-${headingSize} c-rte-toolbar__block-format__icon ${blockType === headingSize ? "selected" : ""}`
2468
+ }),
2469
+ /* @__PURE__ */ jsx14("span", {
2470
+ className: `c-rte-toolbar__block-format__text ${blockType === headingSize ? "selected" : ""}`,
2471
+ children: headingTypeToBlockName[headingSize]
2472
+ })
2473
+ ]
2474
+ }, headingSize)),
2475
+ /* @__PURE__ */ jsxs9(DropdownMenu.Item, {
2476
+ onClick: formatBulletList,
2477
+ children: [
2478
+ /* @__PURE__ */ jsx14("i", {
2479
+ className: `c-rte-icon-bullet-list c-rte-toolbar__block-format__icon ${blockType === "bullet" ? "selected" : ""}`
2480
+ }),
2481
+ /* @__PURE__ */ jsx14("span", {
2482
+ className: `c-rte-toolbar__block-format__text ${blockType === "bullet" ? "selected" : ""}`,
2483
+ children: "Bullet List"
2484
+ })
2485
+ ]
2486
+ }),
2487
+ /* @__PURE__ */ jsxs9(DropdownMenu.Item, {
2488
+ onClick: formatNumberedList,
2489
+ children: [
2490
+ /* @__PURE__ */ jsx14("i", {
2491
+ className: `c-rte-icon-numbered-list c-rte-toolbar__block-format__icon ${blockType === "number" ? "selected" : ""}`
2492
+ }),
2493
+ /* @__PURE__ */ jsx14("span", {
2494
+ className: `c-rte-toolbar__block-format__text ${blockType === "number" ? "selected" : ""}`,
2495
+ children: "Numbered List"
2496
+ })
2497
+ ]
2498
+ }),
2499
+ /* @__PURE__ */ jsxs9(DropdownMenu.Item, {
2500
+ onClick: formatQuote,
2501
+ "data-testid": "toggle-block-format-quote",
2502
+ children: [
2503
+ /* @__PURE__ */ jsx14("i", {
2504
+ className: `c-rte-icon-quote c-rte-toolbar__block-format__icon ${blockType === "quote" ? "selected" : ""}`
2505
+ }),
2506
+ /* @__PURE__ */ jsx14("span", {
2507
+ className: `c-rte-toolbar__block-format__text ${blockType === "quote" ? "selected" : ""}`,
2508
+ children: "Quote"
2509
+ })
2510
+ ]
2511
+ }),
2512
+ /* @__PURE__ */ jsxs9(DropdownMenu.Item, {
2513
+ onClick: formatCode,
2514
+ "data-testid": "toggle-block-format-code",
2515
+ children: [
2516
+ /* @__PURE__ */ jsx14("i", {
2517
+ className: `icon c-rte-icon-code c-rte-toolbar__block-format__icon ${blockType === "code" ? "selected" : ""}`
2518
+ }),
2519
+ /* @__PURE__ */ jsx14("span", {
2520
+ className: `c-rte-toolbar__block-format__text ${blockType === "code" ? "selected" : ""}`,
2521
+ children: "Code block"
2522
+ })
2523
+ ]
2524
+ })
2525
+ ]
2526
+ }),
2527
+ children: /* @__PURE__ */ jsxs9(Button, {
2528
+ style: { backgroundColor: "transparent", padding: "0 8px" },
2529
+ "aria-label": "Formatting options for text style",
2530
+ "data-testid": "toggle-block-format",
2531
+ children: [
2532
+ /* @__PURE__ */ jsx14("i", {
2533
+ className: `c-rte-toolbar__toggle-icon c-rte-icon-${blockType}`
2534
+ }),
2535
+ /* @__PURE__ */ jsx14(Icon.Arrow, {})
2536
+ ]
2537
+ })
2538
+ });
2539
+ }
2540
+ function Divider() {
2541
+ return /* @__PURE__ */ jsx14("div", {
2542
+ className: "c-rte-toolbar__divider"
2543
+ });
2544
+ }
2545
+ function ToolbarPlugin({
2546
+ actionsMenuPrepend,
2547
+ actionsMenuAppend,
2548
+ disabled
2549
+ }) {
2550
+ const [editor] = useLexicalComposerContext11();
2551
+ const [activeEditor, setActiveEditor] = useState9(editor);
2552
+ const [blockType, setBlockType] = useState9("paragraph");
2553
+ const [selectedElementKey, setSelectedElementKey] = useState9(null);
2554
+ const [isLink, setIsLink] = useState9(false);
2555
+ const [isBold, setIsBold] = useState9(false);
2556
+ const [isItalic, setIsItalic] = useState9(false);
2557
+ const [isUnderline, setIsUnderline] = useState9(false);
2558
+ const [isStrikethrough, setIsStrikethrough] = useState9(false);
2559
+ const [isSubscript, setIsSubscript] = useState9(false);
2560
+ const [isSuperscript, setIsSuperscript] = useState9(false);
2561
+ const [isCode, setIsCode] = useState9(false);
2562
+ const [canUndo, setCanUndo] = useState9(false);
2563
+ const [canRedo, setCanRedo] = useState9(false);
2564
+ const tr = useTr();
2565
+ const [codeLanguage, setCodeLanguage] = useState9("");
2566
+ const [isEditable, setIsEditable] = useState9(() => editor.isEditable());
2567
+ const updateToolbar = useCallback4(() => {
2568
+ const selection = $getSelection9();
2569
+ if ($isRangeSelection7(selection)) {
2570
+ const anchorNode = selection.anchor.getNode();
2571
+ let element = anchorNode.getKey() === "root" ? anchorNode : $findMatchingParent2(anchorNode, (e) => {
2572
+ const parent3 = e.getParent();
2573
+ return parent3 !== null && $isRootOrShadowRoot(parent3);
2574
+ });
2575
+ if (element === null) {
2576
+ element = anchorNode.getTopLevelElementOrThrow();
2577
+ }
2578
+ const elementKey = element.getKey();
2579
+ const elementDOM = activeEditor.getElementByKey(elementKey);
2580
+ setIsBold(selection.hasFormat("bold"));
2581
+ setIsItalic(selection.hasFormat("italic"));
2582
+ setIsUnderline(selection.hasFormat("underline"));
2583
+ setIsStrikethrough(selection.hasFormat("strikethrough"));
2584
+ setIsSubscript(selection.hasFormat("subscript"));
2585
+ setIsSuperscript(selection.hasFormat("superscript"));
2586
+ setIsCode(selection.hasFormat("code"));
2587
+ const node = getSelectedNode(selection);
2588
+ const parent2 = node.getParent();
2589
+ if ($isLinkNode4(parent2) || $isLinkNode4(node)) {
2590
+ setIsLink(true);
2591
+ } else {
2592
+ setIsLink(false);
2593
+ }
2594
+ if (elementDOM !== null) {
2595
+ setSelectedElementKey(elementKey);
2596
+ if ($isListNode3(element)) {
2597
+ const parentList = $getNearestNodeOfType(anchorNode, ListNode2);
2598
+ const type = parentList ? parentList.getListType() : element.getListType();
2599
+ setBlockType(type);
2600
+ } else {
2601
+ const type = $isHeadingNode2(element) ? element.getTag() : element.getType();
2602
+ if (type in blockTypeToBlockName) {
2603
+ setBlockType(type);
2604
+ }
2605
+ if ($isCodeNode5(element)) {
2606
+ const language = element.getLanguage();
2607
+ setCodeLanguage(language ? CODE_LANGUAGE_MAP[language] || language : "");
2608
+ return;
2609
+ }
2610
+ }
2611
+ }
2612
+ }
2613
+ }, [activeEditor]);
2614
+ useEffect10(() => {
2615
+ return editor.registerCommand(
2616
+ SELECTION_CHANGE_COMMAND3,
2617
+ (_payload, newEditor) => {
2618
+ updateToolbar();
2619
+ setActiveEditor(newEditor);
2620
+ return false;
2621
+ },
2622
+ COMMAND_PRIORITY_CRITICAL3
2623
+ );
2624
+ }, [editor, updateToolbar]);
2625
+ useEffect10(() => {
2626
+ return mergeRegister3(
2627
+ editor.registerEditableListener((editable) => {
2628
+ setIsEditable(editable);
2629
+ }),
2630
+ activeEditor.registerUpdateListener(({ editorState }) => {
2631
+ editorState.read(() => {
2632
+ updateToolbar();
2633
+ });
2634
+ }),
2635
+ activeEditor.registerCommand(
2636
+ CAN_UNDO_COMMAND,
2637
+ (payload) => {
2638
+ setCanUndo(payload);
2639
+ return false;
2640
+ },
2641
+ COMMAND_PRIORITY_CRITICAL3
2642
+ ),
2643
+ activeEditor.registerCommand(
2644
+ CAN_REDO_COMMAND,
2645
+ (payload) => {
2646
+ setCanRedo(payload);
2647
+ return false;
2648
+ },
2649
+ COMMAND_PRIORITY_CRITICAL3
2650
+ )
2651
+ );
2652
+ }, [activeEditor, editor, updateToolbar]);
2653
+ const clearFormatting = useCallback4(() => {
2654
+ activeEditor.update(() => {
2655
+ const selection = $getSelection9();
2656
+ if ($isRangeSelection7(selection)) {
2657
+ $selectAll(selection);
2658
+ selection.getNodes().forEach((node) => {
2659
+ if ($isTextNode5(node)) {
2660
+ node.setFormat(0);
2661
+ node.setStyle("");
2662
+ $getNearestBlockElementAncestorOrThrow(node).setFormat("");
2663
+ }
2664
+ if ($isDecoratorBlockNode(node)) {
2665
+ node.setFormat("");
2666
+ }
2667
+ });
2668
+ }
2669
+ });
2670
+ }, [activeEditor]);
2671
+ const insertLink = useCallback4(() => {
2672
+ if (!isLink) {
2673
+ editor.dispatchCommand(TOGGLE_LINK_COMMAND3, sanitizeUrl("https://"));
2674
+ } else {
2675
+ editor.dispatchCommand(TOGGLE_LINK_COMMAND3, null);
2676
+ }
2677
+ }, [editor, isLink]);
2678
+ const onCodeLanguageSelect = useCallback4(
2679
+ (value) => {
2680
+ activeEditor.update(() => {
2681
+ if (selectedElementKey !== null) {
2682
+ const node = $getNodeByKey(selectedElementKey);
2683
+ if ($isCodeNode5(node)) {
2684
+ node.setLanguage(value);
2685
+ }
2686
+ }
2687
+ });
2688
+ },
2689
+ [activeEditor, selectedElementKey]
2690
+ );
2691
+ return /* @__PURE__ */ jsxs9("div", {
2692
+ className: "c-rte-toolbar",
2693
+ children: [
2694
+ /* @__PURE__ */ jsxs9("div", {
2695
+ className: "c-rte-toolbar__inner",
2696
+ children: [
2697
+ /* @__PURE__ */ jsx14(IconButton, {
2698
+ disabled: !canUndo || !isEditable,
2699
+ onClick: () => {
2700
+ activeEditor.dispatchCommand(UNDO_COMMAND, void 0);
2701
+ },
2702
+ type: "button",
2703
+ title: tr(IS_APPLE ? "actionUndoTitleApple" : "actionUndoTitle"),
2704
+ "aria-label": tr("actionUndoLabel"),
2705
+ "data-testid": "rich-text-undo-button",
2706
+ children: /* @__PURE__ */ jsx14("i", {
2707
+ className: `c-rte-icon-undo c-rte-toolbar__icon ${!canUndo ? "disabled" : ""}
2708
+ `
2709
+ })
2710
+ }),
2711
+ /* @__PURE__ */ jsx14(IconButton, {
2712
+ disabled: !canRedo || !isEditable,
2713
+ onClick: () => {
2714
+ activeEditor.dispatchCommand(REDO_COMMAND, void 0);
2715
+ },
2716
+ type: "button",
2717
+ title: tr(IS_APPLE ? "actionRedoTitleApple" : "actionRedoTitle"),
2718
+ "aria-label": tr("actionRedoLabel"),
2719
+ children: /* @__PURE__ */ jsx14("i", {
2720
+ className: `c-rte-icon-redo c-rte-toolbar__icon ${!canRedo ? "disabled" : ""}`
2721
+ })
2722
+ }),
2723
+ /* @__PURE__ */ jsx14(Divider, {}),
2724
+ blockType in blockTypeToBlockName && activeEditor === editor && /* @__PURE__ */ jsxs9(Fragment5, {
2725
+ children: [
2726
+ /* @__PURE__ */ jsx14(BlockFormatDropDown, {
2727
+ disabled: !isEditable,
2728
+ blockType,
2729
+ editor
2730
+ }),
2731
+ /* @__PURE__ */ jsx14(Divider, {})
2732
+ ]
2733
+ }),
2734
+ blockType === "code" ? /* @__PURE__ */ jsx14(Fragment5, {
2735
+ children: /* @__PURE__ */ jsx14(DropdownMenu.Root, {
2736
+ disabled: !isEditable,
2737
+ style: { zIndex: 1 },
2738
+ content: /* @__PURE__ */ jsx14(Fragment5, {
2739
+ children: CODE_LANGUAGE_OPTIONS.map(([value, name]) => {
2740
+ return /* @__PURE__ */ jsx14(DropdownMenu.Item, {
2741
+ className: `item ${dropDownActiveClass(value === codeLanguage)}`,
2742
+ onClick: () => onCodeLanguageSelect(value),
2743
+ children: /* @__PURE__ */ jsx14("span", {
2744
+ className: `c-rte-toolbar__code-lang__sel-item ${dropDownActiveClass(value === codeLanguage) ? "selected" : ""}`,
2745
+ children: name
2746
+ })
2747
+ }, value);
2748
+ })
2749
+ }),
2750
+ children: /* @__PURE__ */ jsx14(Button, {
2751
+ "aria-label": tr("codeSelectLanguage"),
2752
+ append: /* @__PURE__ */ jsx14(Icon.Arrow, {}),
2753
+ children: /* @__PURE__ */ jsx14("span", {
2754
+ className: "c-rte-toolbar__code-lang__button-text",
2755
+ children: getLanguageFriendlyName2(codeLanguage)
2756
+ })
2757
+ })
2758
+ })
2759
+ }) : /* @__PURE__ */ jsx14(Dialog, {
2760
+ children: /* @__PURE__ */ jsxs9("div", {
2761
+ className: "c-rte-toolbar__actions-rest",
2762
+ children: [
2763
+ /* @__PURE__ */ jsx14(IconButton, {
2764
+ disabled: !isEditable,
2765
+ className: `c-rte-toolbar__icon-btn ${isBold ? "selected" : ""}`,
2766
+ type: "button",
2767
+ title: tr(IS_APPLE ? "actionFormatAsStrongTitleApple" : "actionFormatAsStrongTitle"),
2768
+ "aria-label": tr("actionFormatAsStrongLabel"),
2769
+ "data-testid": "toggle-format-bold",
2770
+ onClick: () => {
2771
+ activeEditor.dispatchCommand(FORMAT_TEXT_COMMAND2, "bold");
2772
+ },
2773
+ children: /* @__PURE__ */ jsx14("i", {
2774
+ className: `c-rte-toolbar__icon-btn__icon c-rte-icon-bold`
2775
+ })
2776
+ }),
2777
+ /* @__PURE__ */ jsx14(IconButton, {
2778
+ className: `c-rte-toolbar__icon-btn ${isItalic ? "selected" : ""}`,
2779
+ disabled: !isEditable,
2780
+ onClick: () => {
2781
+ activeEditor.dispatchCommand(FORMAT_TEXT_COMMAND2, "italic");
2782
+ },
2783
+ type: "button",
2784
+ title: tr(IS_APPLE ? "actionFormatAsEmphasizedTitleApple" : "actionFormatAsEmphasizedTitle"),
2785
+ "aria-label": tr("actionFormatAsEmphasizedLabel"),
2786
+ "data-testid": "toggle-format-emphasized",
2787
+ children: /* @__PURE__ */ jsx14("i", {
2788
+ className: `c-rte-toolbar__icon-btn__icon c-rte-icon-italic`
2789
+ })
2790
+ }),
2791
+ /* @__PURE__ */ jsx14(IconButton, {
2792
+ className: `c-rte-toolbar__icon-btn ${isUnderline ? "selected" : ""}`,
2793
+ disabled: !isEditable,
2794
+ onClick: () => {
2795
+ activeEditor.dispatchCommand(FORMAT_TEXT_COMMAND2, "underline");
2796
+ },
2797
+ type: "button",
2798
+ title: tr(IS_APPLE ? "actionFormatAsUnderlinedTitleApple" : "actionFormatAsUnderlinedTitle"),
2799
+ "aria-label": tr("actionFormatAsUnderlinedLabel"),
2800
+ "data-testid": "toggle-format-underlined",
2801
+ children: /* @__PURE__ */ jsx14("i", {
2802
+ className: `c-rte-toolbar__icon-btn__icon c-rte-icon-underline`
2803
+ })
2804
+ }),
2805
+ /* @__PURE__ */ jsx14(IconButton, {
2806
+ className: `c-rte-toolbar__icon-btn ${isCode ? "selected" : ""}`,
2807
+ disabled: !isEditable,
2808
+ onClick: () => {
2809
+ activeEditor.dispatchCommand(FORMAT_TEXT_COMMAND2, "code");
2810
+ },
2811
+ type: "button",
2812
+ title: tr("actionInsertCodeBlock"),
2813
+ "aria-label": tr("actionInsertCodeBlock"),
2814
+ "data-testid": "toggle-format-code",
2815
+ children: /* @__PURE__ */ jsx14("i", {
2816
+ className: `c-rte-toolbar__icon-btn__icon c-rte-icon-code`
2817
+ })
2818
+ }),
2819
+ /* @__PURE__ */ jsx14(IconButton, {
2820
+ className: `c-rte-toolbar__icon-btn ${isLink ? "selected" : ""}`,
2821
+ disabled: !isEditable,
2822
+ onClick: insertLink,
2823
+ type: "button",
2824
+ "aria-label": tr("actionInsertlink"),
2825
+ title: tr("actionInsertlink"),
2826
+ children: /* @__PURE__ */ jsx14("i", {
2827
+ className: `c-rte-toolbar__icon-btn__icon c-rte-icon-link`
2828
+ })
2829
+ }),
2830
+ /* @__PURE__ */ jsx14(DropdownMenu.Root, {
2831
+ disabled: !isEditable,
2832
+ style: { zIndex: 1 },
2833
+ content: /* @__PURE__ */ jsxs9(Fragment5, {
2834
+ children: [
2835
+ /* @__PURE__ */ jsxs9(DropdownMenu.Item, {
2836
+ disabled: !isEditable,
2837
+ onClick: () => activeEditor.dispatchCommand(FORMAT_TEXT_COMMAND2, "strikethrough"),
2838
+ title: tr("actionFormatWithStrikethroughTitle"),
2839
+ "aria-label": tr("actionFormatWithStrikethroughLabel"),
2840
+ children: [
2841
+ /* @__PURE__ */ jsx14("i", {
2842
+ className: `c-rte-icon-strikethrough c-rte-toolbar__dd-item__icon ${isStrikethrough ? "selected" : ""}`
2843
+ }),
2844
+ /* @__PURE__ */ jsx14("span", {
2845
+ className: `c-rte-toolbar__dd-item__text ${isStrikethrough ? "selected" : ""}`,
2846
+ children: tr("actionFormatWithStrikethroughTitle")
2847
+ })
2848
+ ]
2849
+ }),
2850
+ /* @__PURE__ */ jsxs9(DropdownMenu.Item, {
2851
+ disabled: !isEditable,
2852
+ onClick: () => activeEditor.dispatchCommand(FORMAT_TEXT_COMMAND2, "subscript"),
2853
+ title: tr("actionFormatWithSubscriptTitle"),
2854
+ "aria-label": tr("actionFormatWithSubscriptLabel"),
2855
+ children: [
2856
+ /* @__PURE__ */ jsx14("i", {
2857
+ className: `c-rte-icon-subscript c-rte-toolbar__dd-item__icon ${isSubscript ? "selected" : ""}`
2858
+ }),
2859
+ /* @__PURE__ */ jsx14("span", {
2860
+ className: `c-rte-toolbar__dd-item__text ${isSubscript ? "selected" : ""}`,
2861
+ children: tr("actionFormatWithSubscriptTitle")
2862
+ })
2863
+ ]
2864
+ }),
2865
+ /* @__PURE__ */ jsxs9(DropdownMenu.Item, {
2866
+ disabled: !isEditable,
2867
+ onClick: () => activeEditor.dispatchCommand(FORMAT_TEXT_COMMAND2, "superscript"),
2868
+ title: tr("actionFormatWithSuperscriptTitle"),
2869
+ "aria-label": tr("actionFormatWithSuperscriptLabel"),
2870
+ children: [
2871
+ /* @__PURE__ */ jsx14("i", {
2872
+ className: `c-rte-icon-superscript c-rte-toolbar__dd-item__icon ${isSuperscript ? "selected" : ""}`
2873
+ }),
2874
+ /* @__PURE__ */ jsx14("span", {
2875
+ className: `c-rte-toolbar__dd-item__text ${isSuperscript ? "selected" : ""}`,
2876
+ children: tr("actionFormatWithSuperscriptTitle")
2877
+ })
2878
+ ]
2879
+ }),
2880
+ /* @__PURE__ */ jsxs9(DropdownMenu.Item, {
2881
+ disabled: !isEditable,
2882
+ onClick: clearFormatting,
2883
+ className: "item",
2884
+ title: tr("actionClearTextFormatting"),
2885
+ "aria-label": tr("actionClearTextFormatting"),
2886
+ children: [
2887
+ /* @__PURE__ */ jsx14("i", {
2888
+ className: "c-rte-icon-clear c-rte-toolbar__dd-item__icon"
2889
+ }),
2890
+ /* @__PURE__ */ jsx14("span", {
2891
+ className: "c-rte-toolbar__dd-item__text--clear",
2892
+ children: tr("actionFormatClear")
2893
+ })
2894
+ ]
2895
+ })
2896
+ ]
2897
+ }),
2898
+ children: /* @__PURE__ */ jsxs9(Button, {
2899
+ style: { backgroundColor: "transparent", padding: "0 8px" },
2900
+ "aria-label": tr("actionTextFormattingOptions"),
2901
+ children: [
2902
+ /* @__PURE__ */ jsx14("i", {
2903
+ className: `c-rte-icon-dropdown-more c-rte-toolbar__toggle-icon`
2904
+ }),
2905
+ /* @__PURE__ */ jsx14(Icon.Arrow, {})
2906
+ ]
2907
+ })
2908
+ }),
2909
+ /* @__PURE__ */ jsx14(Divider, {}),
2910
+ /* @__PURE__ */ jsx14(DropdownMenu.Root, {
2911
+ style: { zIndex: 1 },
2912
+ disabled: !isEditable,
2913
+ content: /* @__PURE__ */ jsxs9(Fragment5, {
2914
+ children: [
2915
+ /* @__PURE__ */ jsxs9(DropdownMenu.Item, {
2916
+ onClick: () => {
2917
+ activeEditor.dispatchCommand(INSERT_HORIZONTAL_RULE_COMMAND, void 0);
2918
+ },
2919
+ children: [
2920
+ /* @__PURE__ */ jsx14("i", {
2921
+ className: "c-rte-toolbar__dd-item__icon c-rte-icon-horizontal-rule"
2922
+ }),
2923
+ /* @__PURE__ */ jsx14("span", {
2924
+ className: "c-rte-toolbar__dd-item__text",
2925
+ children: tr("horizontalRule")
2926
+ })
2927
+ ]
2928
+ }),
2929
+ /* @__PURE__ */ jsx14(DropdownMenu.Item, {
2930
+ children: /* @__PURE__ */ jsx14(Dialog.Trigger, {
2931
+ asChild: true,
2932
+ children: /* @__PURE__ */ jsxs9("div", {
2933
+ className: "c-rte-toolbar__dd-item--table",
2934
+ children: [
2935
+ /* @__PURE__ */ jsx14("i", {
2936
+ className: "c-rte-toolbar__dd-item__icon c-rte-icon-table"
2937
+ }),
2938
+ /* @__PURE__ */ jsx14("span", {
2939
+ className: "c-rte-toolbar__dd-item__text",
2940
+ children: tr("table")
2941
+ })
2942
+ ]
2943
+ })
2944
+ })
2945
+ })
2946
+ ]
2947
+ }),
2948
+ children: /* @__PURE__ */ jsx14(IconButton, {
2949
+ children: /* @__PURE__ */ jsx14("i", {
2950
+ className: "c-rte-icon-plus c-rte-toolbar__plus"
2951
+ })
2952
+ })
2953
+ }),
2954
+ /* @__PURE__ */ jsxs9(Dialog.Content, {
2955
+ children: [
2956
+ /* @__PURE__ */ jsx14(Dialog.Title, {
2957
+ children: tr("insertTableTitle")
2958
+ }),
2959
+ /* @__PURE__ */ jsx14(Dialog.Description, {
2960
+ children: tr("insertTableDescription")
2961
+ }),
2962
+ /* @__PURE__ */ jsx14(InsertTableDialog, {
2963
+ activeEditor
2964
+ })
2965
+ ]
2966
+ })
2967
+ ]
2968
+ })
2969
+ })
2970
+ ]
2971
+ }),
2972
+ /* @__PURE__ */ jsx14(ActionsPlugin, {
2973
+ disabled,
2974
+ prepend: actionsMenuPrepend,
2975
+ append: actionsMenuAppend
2976
+ })
2977
+ ]
2978
+ });
2979
+ }
2980
+
2981
+ // src/rich-text-editor/themes/CrystallizeRTEditorTheme.ts
2982
+ var theme = {
2983
+ blockCursor: "CrystallizeRTEditorTheme__blockCursor",
2984
+ characterLimit: "CrystallizeRTEditorTheme__characterLimit",
2985
+ code: "CrystallizeRTEditorTheme__code",
2986
+ codeHighlight: {
2987
+ atrule: "CrystallizeRTEditorTheme__tokenAttr",
2988
+ attr: "CrystallizeRTEditorTheme__tokenAttr",
2989
+ boolean: "CrystallizeRTEditorTheme__tokenProperty",
2990
+ builtin: "CrystallizeRTEditorTheme__tokenSelector",
2991
+ cdata: "CrystallizeRTEditorTheme__tokenComment",
2992
+ char: "CrystallizeRTEditorTheme__tokenSelector",
2993
+ class: "CrystallizeRTEditorTheme__tokenFunction",
2994
+ "class-name": "CrystallizeRTEditorTheme__tokenFunction",
2995
+ comment: "CrystallizeRTEditorTheme__tokenComment",
2996
+ constant: "CrystallizeRTEditorTheme__tokenProperty",
2997
+ deleted: "CrystallizeRTEditorTheme__tokenProperty",
2998
+ doctype: "CrystallizeRTEditorTheme__tokenComment",
2999
+ entity: "CrystallizeRTEditorTheme__tokenOperator",
3000
+ function: "CrystallizeRTEditorTheme__tokenFunction",
3001
+ important: "CrystallizeRTEditorTheme__tokenVariable",
3002
+ inserted: "CrystallizeRTEditorTheme__tokenSelector",
3003
+ keyword: "CrystallizeRTEditorTheme__tokenAttr",
3004
+ namespace: "CrystallizeRTEditorTheme__tokenVariable",
3005
+ number: "CrystallizeRTEditorTheme__tokenProperty",
3006
+ operator: "CrystallizeRTEditorTheme__tokenOperator",
3007
+ prolog: "CrystallizeRTEditorTheme__tokenComment",
3008
+ property: "CrystallizeRTEditorTheme__tokenProperty",
3009
+ punctuation: "CrystallizeRTEditorTheme__tokenPunctuation",
3010
+ regex: "CrystallizeRTEditorTheme__tokenVariable",
3011
+ selector: "CrystallizeRTEditorTheme__tokenSelector",
3012
+ string: "CrystallizeRTEditorTheme__tokenSelector",
3013
+ symbol: "CrystallizeRTEditorTheme__tokenProperty",
3014
+ tag: "CrystallizeRTEditorTheme__tokenProperty",
3015
+ url: "CrystallizeRTEditorTheme__tokenOperator",
3016
+ variable: "CrystallizeRTEditorTheme__tokenVariable"
3017
+ },
3018
+ embedBlock: {
3019
+ base: "CrystallizeRTEditorTheme__embedBlock",
3020
+ focus: "CrystallizeRTEditorTheme__embedBlockFocus"
3021
+ },
3022
+ hashtag: "CrystallizeRTEditorTheme__hashtag",
3023
+ heading: {
3024
+ h1: "CrystallizeRTEditorTheme__h1",
3025
+ h2: "CrystallizeRTEditorTheme__h2",
3026
+ h3: "CrystallizeRTEditorTheme__h3",
3027
+ h4: "CrystallizeRTEditorTheme__h4",
3028
+ h5: "CrystallizeRTEditorTheme__h5",
3029
+ h6: "CrystallizeRTEditorTheme__h6"
3030
+ },
3031
+ image: "",
3032
+ indent: "CrystallizeRTEditorTheme__indent",
3033
+ link: "CrystallizeRTEditorTheme__link",
3034
+ list: {
3035
+ listitem: "CrystallizeRTEditorTheme__listItem",
3036
+ listitemChecked: "CrystallizeRTEditorTheme__listItemChecked",
3037
+ listitemUnchecked: "CrystallizeRTEditorTheme__listItemUnchecked",
3038
+ nested: {
3039
+ listitem: "CrystallizeRTEditorTheme__nestedListItem"
3040
+ },
3041
+ olDepth: [
3042
+ "CrystallizeRTEditorTheme__ol1",
3043
+ "CrystallizeRTEditorTheme__ol2",
3044
+ "CrystallizeRTEditorTheme__ol3",
3045
+ "CrystallizeRTEditorTheme__ol4",
3046
+ "CrystallizeRTEditorTheme__ol5"
3047
+ ],
3048
+ ul: "CrystallizeRTEditorTheme__ul"
3049
+ },
3050
+ ltr: "CrystallizeRTEditorTheme__ltr",
3051
+ mark: "CrystallizeRTEditorTheme__mark",
3052
+ markOverlap: "CrystallizeRTEditorTheme__markOverlap",
3053
+ paragraph: "CrystallizeRTEditorTheme__paragraph",
3054
+ quote: "CrystallizeRTEditorTheme__quote",
3055
+ rtl: "CrystallizeRTEditorTheme__rtl",
3056
+ table: "CrystallizeRTEditorTheme__table",
3057
+ tableAddColumns: "CrystallizeRTEditorTheme__tableAddColumns",
3058
+ tableAddRows: "CrystallizeRTEditorTheme__tableAddRows",
3059
+ tableCell: "CrystallizeRTEditorTheme__tableCell",
3060
+ tableCellActionButton: "CrystallizeRTEditorTheme__tableCellActionButton",
3061
+ tableCellActionButtonContainer: "CrystallizeRTEditorTheme__tableCellActionButtonContainer",
3062
+ tableCellEditing: "CrystallizeRTEditorTheme__tableCellEditing",
3063
+ tableCellHeader: "CrystallizeRTEditorTheme__tableCellHeader",
3064
+ tableCellPrimarySelected: "CrystallizeRTEditorTheme__tableCellPrimarySelected",
3065
+ tableCellResizer: "CrystallizeRTEditorTheme__tableCellResizer",
3066
+ tableCellSelected: "CrystallizeRTEditorTheme__tableCellSelected",
3067
+ tableCellSortedIndicator: "CrystallizeRTEditorTheme__tableCellSortedIndicator",
3068
+ tableResizeRuler: "CrystallizeRTEditorTheme__tableCellResizeRuler",
3069
+ tableSelected: "CrystallizeRTEditorTheme__tableSelected",
3070
+ text: {
3071
+ bold: "CrystallizeRTEditorTheme__textBold",
3072
+ code: "CrystallizeRTEditorTheme__textCode",
3073
+ italic: "CrystallizeRTEditorTheme__textItalic",
3074
+ strikethrough: "CrystallizeRTEditorTheme__textStrikethrough",
3075
+ subscript: "CrystallizeRTEditorTheme__textSubscript",
3076
+ superscript: "CrystallizeRTEditorTheme__textSuperscript",
3077
+ underline: "CrystallizeRTEditorTheme__textUnderline",
3078
+ underlineStrikethrough: "CrystallizeRTEditorTheme__textUnderlineStrikethrough"
3079
+ }
3080
+ };
3081
+ var CrystallizeRTEditorTheme_default = theme;
3082
+
3083
+ // src/rich-text-editor/rich-text-editor.tsx
3084
+ import { Fragment as Fragment6, jsx as jsx15, jsxs as jsxs10 } from "react/jsx-runtime";
3085
+ function RichTextEditor({
3086
+ initialData,
3087
+ language = "en",
3088
+ labelTranslations,
3089
+ ...rest
3090
+ }) {
3091
+ return /* @__PURE__ */ jsx15(LexicalComposer, {
3092
+ initialConfig: {
3093
+ editable: !rest.disabled,
3094
+ namespace: "crystallize-rich-text-editor",
3095
+ nodes: [...BaseNodes],
3096
+ theme: CrystallizeRTEditorTheme_default,
3097
+ editorState: initialData ? composeInitialState({ richText: initialData }) : void 0,
3098
+ onError: (error) => {
3099
+ throw error;
3100
+ }
3101
+ },
3102
+ children: /* @__PURE__ */ jsx15(I18nProvider, {
3103
+ language,
3104
+ labelTranslations,
3105
+ children: /* @__PURE__ */ jsx15(SharedHistoryContext, {
3106
+ children: /* @__PURE__ */ jsx15("div", {
3107
+ className: "c-rich-text-editor",
3108
+ children: /* @__PURE__ */ jsx15(RichTextEditorWithoutContext, {
3109
+ ...rest
3110
+ })
3111
+ })
3112
+ })
3113
+ })
3114
+ });
3115
+ }
3116
+ function RichTextEditorWithoutContext({
3117
+ placeholder: placeholderText,
3118
+ onChange,
3119
+ triggerOnChangeOnAutoFocus,
3120
+ autoFocus,
3121
+ actionsMenuPrepend,
3122
+ actionsMenuAppend,
3123
+ slotPreContent,
3124
+ maxLength,
3125
+ disabled,
3126
+ id
3127
+ }) {
3128
+ const editable = !disabled;
3129
+ const { historyState } = useSharedHistoryContext();
3130
+ const placeholder = /* @__PURE__ */ jsx15("div", {
3131
+ className: "c-rte-placeholder",
3132
+ children: placeholderText ?? ""
3133
+ });
3134
+ const [editor] = useLexicalComposerContext12();
3135
+ const [floatingAnchorElem, setFloatingAnchorElem] = useState10(null);
3136
+ const firstOnChangeTriggeredRef = useRef5(!autoFocus);
3137
+ const onRef = (_floatingAnchorElem) => {
3138
+ if (_floatingAnchorElem !== null) {
3139
+ setFloatingAnchorElem(_floatingAnchorElem);
3140
+ }
3141
+ };
3142
+ useEffect11(() => {
3143
+ editor.setEditable(editable || false);
3144
+ }, [editable, editor]);
3145
+ function onLocalChange(editorState) {
3146
+ if (onChange) {
3147
+ if (triggerOnChangeOnAutoFocus || firstOnChangeTriggeredRef.current) {
3148
+ onChange(lexicalToCrystallizeRichText({ editor, editorState }));
3149
+ }
3150
+ }
3151
+ firstOnChangeTriggeredRef.current = true;
3152
+ }
3153
+ return /* @__PURE__ */ jsxs10(Fragment6, {
3154
+ children: [
3155
+ /* @__PURE__ */ jsx15(OnChangePlugin, {
3156
+ onChange: onLocalChange,
3157
+ ignoreSelectionChange: true
3158
+ }),
3159
+ /* @__PURE__ */ jsx15(ToolbarPlugin, {
3160
+ disabled,
3161
+ actionsMenuPrepend,
3162
+ actionsMenuAppend
3163
+ }),
3164
+ slotPreContent,
3165
+ /* @__PURE__ */ jsxs10("div", {
3166
+ className: `c-rte-editor-container ${disabled ? "disabled" : ""}`,
3167
+ children: [
3168
+ maxLength != null ? /* @__PURE__ */ jsx15(MaxLengthPlugin, {
3169
+ maxLength
3170
+ }) : null,
3171
+ !autoFocus ? null : /* @__PURE__ */ jsx15(AutoFocusPlugin, {}),
3172
+ /* @__PURE__ */ jsx15(ClearEditorPlugin, {}),
3173
+ /* @__PURE__ */ jsx15(LexicalAutoLinkPlugin, {}),
3174
+ /* @__PURE__ */ jsx15(HistoryPlugin, {
3175
+ externalHistoryState: historyState
3176
+ }),
3177
+ /* @__PURE__ */ jsx15(RichTextPlugin, {
3178
+ contentEditable: /* @__PURE__ */ jsx15("div", {
3179
+ className: "c-rte-editor-scroller",
3180
+ children: /* @__PURE__ */ jsx15("div", {
3181
+ className: "c-rte-editor",
3182
+ ref: onRef,
3183
+ children: /* @__PURE__ */ jsx15(ContentEditable, {
3184
+ className: "c-rte-contenteditable-root",
3185
+ id
3186
+ })
3187
+ })
3188
+ }),
3189
+ placeholder,
3190
+ ErrorBoundary: LexicalErrorBoundary
3191
+ }),
3192
+ /* @__PURE__ */ jsx15(CodeHighlightPlugin, {}),
3193
+ /* @__PURE__ */ jsx15(ListPlugin, {}),
3194
+ /* @__PURE__ */ jsx15(ListMaxIndentLevelPlugin, {
3195
+ maxDepth: 7
3196
+ }),
3197
+ /* @__PURE__ */ jsx15(TablePlugin, {}),
3198
+ /* @__PURE__ */ jsx15(LinkPlugin, {}),
3199
+ /* @__PURE__ */ jsx15(HorizontalRulePlugin, {}),
3200
+ /* @__PURE__ */ jsx15(TabFocusPlugin, {}),
3201
+ /* @__PURE__ */ jsx15(TabIndentationPlugin, {}),
3202
+ floatingAnchorElem && /* @__PURE__ */ jsxs10(Fragment6, {
3203
+ children: [
3204
+ /* @__PURE__ */ jsx15(CodeActionMenuPlugin, {
3205
+ anchorElem: floatingAnchorElem
3206
+ }),
3207
+ /* @__PURE__ */ jsx15(FloatingLinkEditorPlugin, {
3208
+ anchorElem: floatingAnchorElem
3209
+ }),
3210
+ /* @__PURE__ */ jsx15(TableActionMenuPlugin, {
3211
+ anchorElem: floatingAnchorElem
3212
+ }),
3213
+ /* @__PURE__ */ jsx15(FloatingTextFormatToolbarPlugin, {
3214
+ anchorElem: floatingAnchorElem
3215
+ })
3216
+ ]
3217
+ })
3218
+ ]
3219
+ })
3220
+ ]
3221
+ });
3222
+ }
3223
+ var rich_text_editor_default = RichTextEditor;
3224
+ export {
3225
+ RichTextEditor,
3226
+ rich_text_editor_default as default
3227
+ };