tiptap-markdown-react 0.8.12 → 0.9.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (43) hide show
  1. package/README.md +32 -0
  2. package/dist/ReportContent-Re3hNps8.js +368 -0
  3. package/dist/ReportContent-Re3hNps8.js.map +1 -0
  4. package/dist/chart/ChartExtension.d.ts +21 -0
  5. package/dist/chart/chartRoundTrip.test.d.ts +1 -0
  6. package/dist/chart/columnMatching.d.ts +19 -0
  7. package/dist/chart/createChart.d.ts +19 -0
  8. package/dist/chart/mapData.d.ts +22 -0
  9. package/dist/chart/mapData.test.d.ts +1 -0
  10. package/dist/chart/parse.d.ts +31 -0
  11. package/dist/chart/parse.test.d.ts +1 -0
  12. package/dist/chart/prepareChartMarkdown.d.ts +5 -0
  13. package/dist/chart/renderChart.d.ts +12 -0
  14. package/dist/chart/serialize.d.ts +1 -0
  15. package/dist/chart/theme.d.ts +3 -0
  16. package/dist/chart/types.d.ts +41 -0
  17. package/dist/components/ChartEditorPopover.d.ts +12 -0
  18. package/dist/components/ChartMount.d.ts +14 -0
  19. package/dist/components/ChartView.d.ts +2 -0
  20. package/dist/components/MarkdownPreview.d.ts +3 -2
  21. package/dist/components/ReportContentWithCharts.d.ts +13 -0
  22. package/dist/extensions.d.ts +4 -3
  23. package/dist/{extractToc-CecK9W_w.js → extractToc-Dv40DtV5.js} +145 -9
  24. package/dist/extractToc-Dv40DtV5.js.map +1 -0
  25. package/dist/index.d.ts +8 -2
  26. package/dist/index.js +426 -128
  27. package/dist/index.js.map +1 -1
  28. package/dist/labels.d.ts +9 -0
  29. package/dist/markdownPaste.chart.test.d.ts +1 -0
  30. package/dist/reader.d.ts +3 -8
  31. package/dist/reader.js +9 -6
  32. package/dist/scrollToTocHeading-CIJu2AcX.js +496 -0
  33. package/dist/scrollToTocHeading-CIJu2AcX.js.map +1 -0
  34. package/dist/server.d.ts +4 -1
  35. package/dist/server.js +17 -9
  36. package/dist/server.js.map +1 -1
  37. package/dist/style.css +144 -0
  38. package/package.json +12 -4
  39. package/dist/ReportContent-c_UlJnVY.js +0 -68
  40. package/dist/ReportContent-c_UlJnVY.js.map +0 -1
  41. package/dist/extractToc-CecK9W_w.js.map +0 -1
  42. package/dist/scrollToTocHeading-CwapFaVP.js +0 -126
  43. package/dist/scrollToTocHeading-CwapFaVP.js.map +0 -1
package/dist/index.js CHANGED
@@ -1,25 +1,26 @@
1
1
  "use client";
2
2
  import { Markdown } from "@tiptap/markdown";
3
+ import { c as renderOrUpdateChart, d as destroyChart } from "./scrollToTocHeading-CIJu2AcX.js";
4
+ import { C, a, R, b, f, m, r, s } from "./scrollToTocHeading-CIJu2AcX.js";
3
5
  import { jsx, jsxs, Fragment as Fragment$1 } from "react/jsx-runtime";
4
6
  import CodeBlockLowlight from "@tiptap/extension-code-block-lowlight";
5
7
  import Image from "@tiptap/extension-image";
6
8
  import { TableOfContents } from "@tiptap/extension-table-of-contents";
7
9
  import { NodeViewWrapper, ReactNodeViewRenderer, NodeViewContent, useEditor, EditorContent, useEditorState } from "@tiptap/react";
8
- import { forwardRef, useEffect, useRef, useImperativeHandle, useMemo, useState, useId, useCallback, useContext, createContext } from "react";
9
- import { e as enrichMarkdownCitations, s as styles$5 } from "./ReportContent-c_UlJnVY.js";
10
- import { R, a } from "./ReportContent-c_UlJnVY.js";
11
- import { C as CitationRef, g as mergeCommentIntervals, f as mapCommentAnchors, b as baseExtensions, c as CommentMark, l as lowlight, m as makeTocGetId, p as pureCodeBlock, a as pureImage, h as renderMathInto, i as subscribeMathClick } from "./extractToc-CecK9W_w.js";
12
- import { d, e, s } from "./extractToc-CecK9W_w.js";
10
+ import { useId, useState, useRef, useEffect, useMemo, forwardRef, useImperativeHandle, useCallback, useContext, createContext } from "react";
11
+ import { s as serializeChartPayload, u as unwrapChartConfigs, b as parseGfmTable, c as normalizeChartPayload, e as enrichMarkdownCitations, d as styles$5 } from "./ReportContent-Re3hNps8.js";
12
+ import { R as R2, a as a2 } from "./ReportContent-Re3hNps8.js";
13
+ import { C as CitationRef, i as mergeCommentIntervals, h as mapCommentAnchors, p as prepareChartMarkdown, j as reportChart, b as baseExtensions, f as CommentMark, l as lowlight, m as makeTocGetId, a as pureCodeBlock, c as pureImage, k as renderMathInto, n as subscribeMathClick } from "./extractToc-Dv40DtV5.js";
14
+ import { g, e, d, s as s2 } from "./extractToc-Dv40DtV5.js";
13
15
  import { Slice, Fragment } from "@tiptap/pm/model";
14
16
  import { Extension, Node as Node$1 } from "@tiptap/core";
15
17
  import { PluginKey, Plugin } from "@tiptap/pm/state";
16
18
  import { DecorationSet, Decoration } from "@tiptap/pm/view";
17
19
  import { FileHandlePlugin } from "@tiptap/extension-file-handler";
20
+ import { createPortal } from "react-dom";
18
21
  import * as DropdownMenu from "@radix-ui/react-dropdown-menu";
19
22
  import * as Popover from "@radix-ui/react-popover";
20
- import { createPortal } from "react-dom";
21
23
  import { isInTable, selectedRect, rowIsHeader, CellSelection } from "@tiptap/pm/tables";
22
- import { C, R as R2, f, r, s as s2 } from "./scrollToTocHeading-CwapFaVP.js";
23
24
  function CitationRefView({ node, extension }) {
24
25
  const index = String(node.attrs.index ?? "");
25
26
  const url = node.attrs.url || null;
@@ -86,9 +87,9 @@ function stripCommentAnchorMarks(slice, markType) {
86
87
  const strip = (fragment) => {
87
88
  const children = [];
88
89
  fragment.forEach((child) => {
89
- if (child.isText && child.marks.some((m) => m.type === markType)) {
90
+ if (child.isText && child.marks.some((m2) => m2.type === markType)) {
90
91
  children.push(
91
- child.mark(child.marks.filter((m) => m.type !== markType))
92
+ child.mark(child.marks.filter((m2) => m2.type !== markType))
92
93
  );
93
94
  } else if (child.content.size > 0) {
94
95
  children.push(child.copy(strip(child.content)));
@@ -103,7 +104,7 @@ function stripCommentAnchorMarks(slice, markType) {
103
104
  function sliceHasCommentMarks(slice, markType) {
104
105
  let found = false;
105
106
  slice.content.descendants((node) => {
106
- if (node.isText && node.marks.some((m) => m.type === markType)) {
107
+ if (node.isText && node.marks.some((m2) => m2.type === markType)) {
107
108
  found = true;
108
109
  return false;
109
110
  }
@@ -122,9 +123,9 @@ function collectCommentRanges(doc) {
122
123
  const byId = /* @__PURE__ */ new Map();
123
124
  doc.descendants((node, pos) => {
124
125
  if (!node.isText) return true;
125
- for (const m of node.marks) {
126
- if (m.type.name !== "commentAnchor") continue;
127
- const ids = m.attrs.commentIds ?? [];
126
+ for (const m2 of node.marks) {
127
+ if (m2.type.name !== "commentAnchor") continue;
128
+ const ids = m2.attrs.commentIds ?? [];
128
129
  for (const id of ids) {
129
130
  const arr = byId.get(id) ?? [];
130
131
  arr.push({ from: pos, to: pos + node.nodeSize });
@@ -180,19 +181,19 @@ function commentAnchorPlugin(options = {}) {
180
181
  const decos = [];
181
182
  const bounds = blockBounds(state.doc);
182
183
  if (showGutter) {
183
- for (const b of bounds) {
184
+ for (const b2 of bounds) {
184
185
  const idsInBlock = [];
185
186
  for (const [id, ranges] of byId) {
186
- if (rangesIntersectBlock(ranges, b.start, b.end)) {
187
+ if (rangesIntersectBlock(ranges, b2.start, b2.end)) {
187
188
  idsInBlock.push(id);
188
189
  }
189
190
  }
190
191
  if (idsInBlock.length > 0) {
191
192
  decos.push(
192
193
  Decoration.widget(
193
- b.start,
194
- (view) => gutterDom(idsInBlock, view, b.start),
195
- { side: -1, key: `tmr-gutter:${b.start}` }
194
+ b2.start,
195
+ (view) => gutterDom(idsInBlock, view, b2.start),
196
+ { side: -1, key: `tmr-gutter:${b2.start}` }
196
197
  )
197
198
  );
198
199
  }
@@ -206,10 +207,10 @@ function commentAnchorPlugin(options = {}) {
206
207
  Decoration.inline(r2.from, r2.to, { class: "tmr-comment-active" })
207
208
  );
208
209
  }
209
- for (const b of bounds) {
210
- if (rangesIntersectBlock(ranges, b.start, b.end)) {
210
+ for (const b2 of bounds) {
211
+ if (rangesIntersectBlock(ranges, b2.start, b2.end)) {
211
212
  decos.push(
212
- Decoration.node(b.start, b.end, {
213
+ Decoration.node(b2.start, b2.end, {
213
214
  class: "tmr-comment-block-active"
214
215
  })
215
216
  );
@@ -272,9 +273,9 @@ function collectCommentIds(editor) {
272
273
  const ids = [];
273
274
  editor.state.doc.descendants((node) => {
274
275
  if (!node.isText) return true;
275
- for (const m of node.marks) {
276
- if (m.type.name !== "commentAnchor") continue;
277
- for (const id of m.attrs.commentIds ?? []) {
276
+ for (const m2 of node.marks) {
277
+ if (m2.type.name !== "commentAnchor") continue;
278
+ for (const id of m2.attrs.commentIds ?? []) {
278
279
  if (!ids.includes(id)) ids.push(id);
279
280
  }
280
281
  }
@@ -286,9 +287,9 @@ function commentRangesById(editor, commentId) {
286
287
  const ranges = [];
287
288
  editor.state.doc.descendants((node, pos) => {
288
289
  if (!node.isText) return true;
289
- for (const m of node.marks) {
290
- if (m.type.name !== "commentAnchor") continue;
291
- const ids = m.attrs.commentIds ?? [];
290
+ for (const m2 of node.marks) {
291
+ if (m2.type.name !== "commentAnchor") continue;
292
+ const ids = m2.attrs.commentIds ?? [];
292
293
  if (ids.includes(commentId)) {
293
294
  ranges.push({ from: pos, to: pos + node.nodeSize });
294
295
  }
@@ -461,7 +462,8 @@ function looksLikeMarkdown(text) {
461
462
  /^>\s/m.test(text) || // 引用
462
463
  /^```/m.test(text) || // 代码围栏
463
464
  /^\|.+\|\s*$/m.test(text) || // 表格行
464
- /^(-{3,}|\*{3,})\s*$/m.test(text);
465
+ /^(-{3,}|\*{3,})\s*$/m.test(text) || // 分割线
466
+ /<!--\s*[\[{][\s\S]*?"chartType"[\s\S]*?-->/.test(text);
465
467
  }
466
468
  const MarkdownPaste = Extension.create({
467
469
  name: "markdownPaste",
@@ -483,7 +485,7 @@ const MarkdownPaste = Extension.create({
483
485
  const markdown = editor.markdown;
484
486
  if (!markdown) return false;
485
487
  try {
486
- const json = markdown.parse(text);
488
+ const json = markdown.parse(prepareChartMarkdown(text));
487
489
  editor.commands.insertContent(json);
488
490
  return true;
489
491
  } catch (err) {
@@ -496,6 +498,374 @@ const MarkdownPaste = Extension.create({
496
498
  ];
497
499
  }
498
500
  });
501
+ const defaultChartLabels = {
502
+ tabLabel: (chartType, index) => `${chartType} ${index + 1}`,
503
+ done: "Done",
504
+ cancel: "Cancel",
505
+ configLabel: "Chart config (JSON)",
506
+ tableLabel: "Data table (Markdown)"
507
+ };
508
+ const defaultToolbarLabels = {
509
+ undo: "Undo",
510
+ redo: "Redo",
511
+ style: "Style",
512
+ normalText: "Normal text",
513
+ headingLabel: (level) => `Heading ${level}`,
514
+ fontSize: "Font size",
515
+ fontSizeDefault: "Default",
516
+ bold: "Bold",
517
+ italic: "Italic",
518
+ underline: "Underline",
519
+ strike: "Strikethrough",
520
+ code: "Inline code",
521
+ textColor: "Text color",
522
+ highlight: "Highlight",
523
+ colorNone: "None",
524
+ colorTheme: "THEME",
525
+ scriptMenu: "Superscript / Subscript",
526
+ scriptNormal: "Normal",
527
+ superscript: "Superscript",
528
+ subscript: "Subscript",
529
+ link: "Link",
530
+ linkPrompt: "Enter URL",
531
+ image: "Image",
532
+ imageUploadFailed: "Image upload failed",
533
+ importMarkdownFailed: "Markdown import failed",
534
+ importDocument: "Import",
535
+ importDocumentHint: "Import a file",
536
+ importDocumentOther: "Document",
537
+ importDocumentBusy: "Importing…",
538
+ importDocumentUploading: (percent) => `Uploading ${percent}%`,
539
+ importDocumentConverting: "Converting…",
540
+ importDocumentFailed: "Import failed",
541
+ blockquote: "Blockquote",
542
+ bulletList: "Bullet list",
543
+ orderedList: "Ordered list",
544
+ taskList: "Task list",
545
+ more: "More",
546
+ codeBlock: "Code block",
547
+ hr: "Divider",
548
+ importMarkdown: "Markdown",
549
+ tableInsert: "Insert table",
550
+ tableSizeSelected: (cols, rows) => `${cols} × ${rows}`,
551
+ tableAddColumnBefore: "Add column before",
552
+ tableAddColumnAfter: "Add column after",
553
+ tableDeleteColumn: "Delete column",
554
+ tableAddRowBefore: "Add row before",
555
+ tableAddRowAfter: "Add row after",
556
+ tableDeleteRow: "Delete row",
557
+ tableAddColumnBeforeN: (n) => `Add ${n} columns before`,
558
+ tableAddColumnAfterN: (n) => `Add ${n} columns after`,
559
+ tableDeleteColumnN: (n) => `Delete ${n} columns`,
560
+ tableAddRowBeforeN: (n) => `Add ${n} rows before`,
561
+ tableAddRowAfterN: (n) => `Add ${n} rows after`,
562
+ tableDeleteRowN: (n) => `Delete ${n} rows`,
563
+ tableDeleteTable: "Delete table",
564
+ inlineMath: "Inline equation",
565
+ blockMath: "Block equation",
566
+ mathPlaceholder: "E = mc^2",
567
+ mathDone: "Done",
568
+ mathCancel: "Cancel",
569
+ mathNewInline: "New equation",
570
+ mathNewBlock: "Add a TeX equation"
571
+ };
572
+ const defaultColorPaletteLabels = {
573
+ none: "None",
574
+ theme: "THEME"
575
+ };
576
+ const defaultTocLabels = {
577
+ title: "Contents",
578
+ expand: "Expand",
579
+ collapse: "Collapse"
580
+ };
581
+ const defaultCodeBlockLabels = {
582
+ autoDetect: "Auto-detect",
583
+ delete: "Delete code block"
584
+ };
585
+ const defaultCommentLabels = {
586
+ open: "Open",
587
+ resolved: "Resolved",
588
+ dismissed: "Dismissed",
589
+ outdated: "Outdated",
590
+ ambiguous: "Ambiguous",
591
+ partial: "Partially matched",
592
+ gutterTitle: "Comment"
593
+ };
594
+ function buildEditors(payload) {
595
+ const flat = payload.config.length === 1 ? payload.config[0] : payload.config;
596
+ const full = serializeChartPayload(payload);
597
+ const lines = full.split("\n");
598
+ const tableText = lines.slice(2).join("\n");
599
+ return {
600
+ configText: JSON.stringify(flat, null, 2),
601
+ tableText
602
+ };
603
+ }
604
+ function ChartEditorPopover({
605
+ payload,
606
+ anchor,
607
+ doneLabel = "Done",
608
+ cancelLabel = "Cancel",
609
+ configLabel = "Chart config (JSON)",
610
+ tableLabel = "Data table (Markdown)",
611
+ onConfirm,
612
+ onCancel
613
+ }) {
614
+ const titleId = useId();
615
+ const initial = buildEditors(payload);
616
+ const [configText, setConfigText] = useState(initial.configText);
617
+ const [tableText, setTableText] = useState(initial.tableText);
618
+ const [error, setError] = useState(null);
619
+ const panelRef = useRef(null);
620
+ useEffect(() => {
621
+ const onKey = (e2) => {
622
+ if (e2.key === "Escape") onCancel();
623
+ };
624
+ window.addEventListener("keydown", onKey);
625
+ return () => window.removeEventListener("keydown", onKey);
626
+ }, [onCancel]);
627
+ useEffect(() => {
628
+ const onDown = (e2) => {
629
+ var _a;
630
+ const t = e2.target;
631
+ if ((_a = panelRef.current) == null ? void 0 : _a.contains(t)) return;
632
+ if (anchor == null ? void 0 : anchor.contains(t)) return;
633
+ onCancel();
634
+ };
635
+ window.addEventListener("mousedown", onDown);
636
+ return () => window.removeEventListener("mousedown", onDown);
637
+ }, [anchor, onCancel]);
638
+ const style = (() => {
639
+ if (!anchor) return { top: 80, left: 80 };
640
+ const r2 = anchor.getBoundingClientRect();
641
+ const top = Math.min(r2.bottom + 8, window.innerHeight - 40);
642
+ const left = Math.min(Math.max(8, r2.left), window.innerWidth - 340);
643
+ return { top, left };
644
+ })();
645
+ const submit = () => {
646
+ try {
647
+ const parsed = JSON.parse(configText);
648
+ const configs = unwrapChartConfigs(parsed);
649
+ if (!(configs == null ? void 0 : configs.length)) {
650
+ setError("Invalid chart config JSON");
651
+ return;
652
+ }
653
+ const table = parseGfmTable(
654
+ tableText.endsWith("\n") ? tableText : `${tableText}
655
+ `
656
+ );
657
+ if (!table) {
658
+ setError("Invalid Markdown table");
659
+ return;
660
+ }
661
+ const next = normalizeChartPayload(
662
+ configs,
663
+ table.columns,
664
+ table.dataSource
665
+ );
666
+ if (!next) {
667
+ setError("No supported chartType / axes in config");
668
+ return;
669
+ }
670
+ onConfirm(next);
671
+ } catch (e2) {
672
+ setError(e2.message || "Parse error");
673
+ }
674
+ };
675
+ const onKeyDown = (e2) => {
676
+ if ((e2.metaKey || e2.ctrlKey) && e2.key === "Enter") {
677
+ e2.preventDefault();
678
+ submit();
679
+ }
680
+ };
681
+ return createPortal(
682
+ /* @__PURE__ */ jsxs(
683
+ "div",
684
+ {
685
+ ref: panelRef,
686
+ className: "tmr-chart-popover",
687
+ style: { top: style.top, left: style.left },
688
+ role: "dialog",
689
+ "aria-labelledby": titleId,
690
+ onKeyDown,
691
+ children: [
692
+ /* @__PURE__ */ jsx("div", { id: titleId, className: "tmr-chart-title", children: "Edit chart" }),
693
+ /* @__PURE__ */ jsxs("label", { children: [
694
+ configLabel,
695
+ /* @__PURE__ */ jsx(
696
+ "textarea",
697
+ {
698
+ value: configText,
699
+ onChange: (e2) => setConfigText(e2.target.value),
700
+ spellCheck: false
701
+ }
702
+ )
703
+ ] }),
704
+ /* @__PURE__ */ jsxs("label", { children: [
705
+ tableLabel,
706
+ /* @__PURE__ */ jsx(
707
+ "textarea",
708
+ {
709
+ value: tableText,
710
+ onChange: (e2) => setTableText(e2.target.value),
711
+ spellCheck: false
712
+ }
713
+ )
714
+ ] }),
715
+ error ? /* @__PURE__ */ jsx("div", { className: "tmr-chart-popover-error", children: error }) : null,
716
+ /* @__PURE__ */ jsxs("div", { className: "tmr-chart-popover-actions", children: [
717
+ /* @__PURE__ */ jsx("button", { type: "button", onClick: onCancel, children: cancelLabel }),
718
+ /* @__PURE__ */ jsx("button", { type: "button", "data-primary": "true", onClick: submit, children: doneLabel })
719
+ ] })
720
+ ]
721
+ }
722
+ ),
723
+ document.body
724
+ );
725
+ }
726
+ function tabLabel(chartType, title, index, fallback) {
727
+ if (title == null ? void 0 : title.trim()) return title;
728
+ return fallback(chartType, index);
729
+ }
730
+ function ChartView({
731
+ node,
732
+ updateAttributes,
733
+ editor,
734
+ extension,
735
+ selected
736
+ }) {
737
+ const canvasRef = useRef(null);
738
+ const chartRef = useRef(null);
739
+ const rootRef = useRef(null);
740
+ const [active2, setActive2] = useState(0);
741
+ const [editing, setEditing] = useState(false);
742
+ const payload = useMemo(
743
+ () => ({
744
+ config: node.attrs.config ?? [],
745
+ columns: node.attrs.columns ?? [],
746
+ dataSource: node.attrs.dataSource ?? []
747
+ }),
748
+ [node.attrs.config, node.attrs.columns, node.attrs.dataSource]
749
+ );
750
+ const editable = Boolean(editor == null ? void 0 : editor.isEditable) && extension.options.chartEditable !== false;
751
+ const theme = extension.options.chartTheme ?? null;
752
+ const configs = payload.config;
753
+ const safeIndex = Math.min(active2, Math.max(0, configs.length - 1));
754
+ const config = configs[safeIndex];
755
+ const height = (config == null ? void 0 : config.height) ?? 320;
756
+ useEffect(() => {
757
+ const canvas = canvasRef.current;
758
+ if (!canvas || !config) return;
759
+ chartRef.current = renderOrUpdateChart({
760
+ canvas,
761
+ config,
762
+ payload,
763
+ theme,
764
+ chart: chartRef.current
765
+ });
766
+ return () => {
767
+ };
768
+ }, [config, payload, theme]);
769
+ useEffect(() => {
770
+ return () => {
771
+ destroyChart(chartRef.current);
772
+ chartRef.current = null;
773
+ };
774
+ }, []);
775
+ useEffect(() => {
776
+ destroyChart(chartRef.current);
777
+ chartRef.current = null;
778
+ const canvas = canvasRef.current;
779
+ if (!canvas || !config) return;
780
+ chartRef.current = renderOrUpdateChart({
781
+ canvas,
782
+ config,
783
+ payload,
784
+ theme,
785
+ chart: null
786
+ });
787
+ }, [safeIndex]);
788
+ const labels = {
789
+ ...defaultChartLabels,
790
+ ...extension.options.chartLabels
791
+ };
792
+ const onOpenEdit = () => {
793
+ if (!editable) return;
794
+ setEditing(true);
795
+ };
796
+ return /* @__PURE__ */ jsxs(
797
+ NodeViewWrapper,
798
+ {
799
+ as: "div",
800
+ className: `tmr-chart${editable ? " tmr-chart--interactive" : ""}`,
801
+ "data-type": "chart",
802
+ "data-selected": selected ? "true" : void 0,
803
+ ref: rootRef,
804
+ onClick: (e2) => {
805
+ if (e2.target.closest("button")) return;
806
+ onOpenEdit();
807
+ },
808
+ children: [
809
+ (config == null ? void 0 : config.title) ? /* @__PURE__ */ jsx("div", { className: "tmr-chart-title", children: config.title }) : null,
810
+ (config == null ? void 0 : config.dataTime) ? /* @__PURE__ */ jsx("div", { className: "tmr-chart-time", children: config.dataTime }) : null,
811
+ configs.length > 1 ? /* @__PURE__ */ jsx("div", { className: "tmr-chart-tabs", role: "tablist", children: configs.map((c, i) => /* @__PURE__ */ jsx(
812
+ "button",
813
+ {
814
+ type: "button",
815
+ role: "tab",
816
+ className: "tmr-chart-tab",
817
+ "data-active": i === safeIndex ? "true" : "false",
818
+ "aria-selected": i === safeIndex,
819
+ onClick: (e2) => {
820
+ e2.stopPropagation();
821
+ setActive2(i);
822
+ },
823
+ children: tabLabel(c.chartType, c.title, i, labels.tabLabel)
824
+ },
825
+ `${c.chartType}-${i}`
826
+ )) }) : null,
827
+ /* @__PURE__ */ jsx("div", { className: "tmr-chart-canvas-host", style: { height }, children: /* @__PURE__ */ jsx("canvas", { ref: canvasRef }) }),
828
+ editing ? /* @__PURE__ */ jsx(
829
+ ChartEditorPopover,
830
+ {
831
+ payload,
832
+ anchor: rootRef.current,
833
+ doneLabel: labels.done,
834
+ cancelLabel: labels.cancel,
835
+ configLabel: labels.configLabel,
836
+ tableLabel: labels.tableLabel,
837
+ onCancel: () => setEditing(false),
838
+ onConfirm: (next) => {
839
+ updateAttributes({
840
+ config: next.config,
841
+ columns: next.columns,
842
+ dataSource: next.dataSource
843
+ });
844
+ setEditing(false);
845
+ setActive2(0);
846
+ }
847
+ }
848
+ ) : null
849
+ ]
850
+ }
851
+ );
852
+ }
853
+ function createChart(options = {}) {
854
+ const { editable = true, chartTheme = null, chartLabels } = options;
855
+ return reportChart.extend({
856
+ addOptions() {
857
+ return {
858
+ HTMLAttributes: {},
859
+ chartEditable: editable,
860
+ chartTheme,
861
+ chartLabels
862
+ };
863
+ },
864
+ addNodeView() {
865
+ return ReactNodeViewRenderer(ChartView);
866
+ }
867
+ });
868
+ }
499
869
  function Svg({ size = "1em", children, ...rest }) {
500
870
  return /* @__PURE__ */ jsx(
501
871
  "svg",
@@ -644,92 +1014,6 @@ const TableDeleteIcon = (p) => /* @__PURE__ */ jsxs(Svg, { ...p, children: [
644
1014
  /* @__PURE__ */ jsx("path", { d: "M15 5v14" }),
645
1015
  /* @__PURE__ */ jsx("path", { d: "m7 2 10 20" })
646
1016
  ] });
647
- const defaultToolbarLabels = {
648
- undo: "Undo",
649
- redo: "Redo",
650
- style: "Style",
651
- normalText: "Normal text",
652
- headingLabel: (level) => `Heading ${level}`,
653
- fontSize: "Font size",
654
- fontSizeDefault: "Default",
655
- bold: "Bold",
656
- italic: "Italic",
657
- underline: "Underline",
658
- strike: "Strikethrough",
659
- code: "Inline code",
660
- textColor: "Text color",
661
- highlight: "Highlight",
662
- colorNone: "None",
663
- colorTheme: "THEME",
664
- scriptMenu: "Superscript / Subscript",
665
- scriptNormal: "Normal",
666
- superscript: "Superscript",
667
- subscript: "Subscript",
668
- link: "Link",
669
- linkPrompt: "Enter URL",
670
- image: "Image",
671
- imageUploadFailed: "Image upload failed",
672
- importMarkdownFailed: "Markdown import failed",
673
- importDocument: "Import",
674
- importDocumentHint: "Import a file",
675
- importDocumentOther: "Document",
676
- importDocumentBusy: "Importing…",
677
- importDocumentUploading: (percent) => `Uploading ${percent}%`,
678
- importDocumentConverting: "Converting…",
679
- importDocumentFailed: "Import failed",
680
- blockquote: "Blockquote",
681
- bulletList: "Bullet list",
682
- orderedList: "Ordered list",
683
- taskList: "Task list",
684
- more: "More",
685
- codeBlock: "Code block",
686
- hr: "Divider",
687
- importMarkdown: "Markdown",
688
- tableInsert: "Insert table",
689
- tableSizeSelected: (cols, rows) => `${cols} × ${rows}`,
690
- tableAddColumnBefore: "Add column before",
691
- tableAddColumnAfter: "Add column after",
692
- tableDeleteColumn: "Delete column",
693
- tableAddRowBefore: "Add row before",
694
- tableAddRowAfter: "Add row after",
695
- tableDeleteRow: "Delete row",
696
- tableAddColumnBeforeN: (n) => `Add ${n} columns before`,
697
- tableAddColumnAfterN: (n) => `Add ${n} columns after`,
698
- tableDeleteColumnN: (n) => `Delete ${n} columns`,
699
- tableAddRowBeforeN: (n) => `Add ${n} rows before`,
700
- tableAddRowAfterN: (n) => `Add ${n} rows after`,
701
- tableDeleteRowN: (n) => `Delete ${n} rows`,
702
- tableDeleteTable: "Delete table",
703
- inlineMath: "Inline equation",
704
- blockMath: "Block equation",
705
- mathPlaceholder: "E = mc^2",
706
- mathDone: "Done",
707
- mathCancel: "Cancel",
708
- mathNewInline: "New equation",
709
- mathNewBlock: "Add a TeX equation"
710
- };
711
- const defaultColorPaletteLabels = {
712
- none: "None",
713
- theme: "THEME"
714
- };
715
- const defaultTocLabels = {
716
- title: "Contents",
717
- expand: "Expand",
718
- collapse: "Collapse"
719
- };
720
- const defaultCodeBlockLabels = {
721
- autoDetect: "Auto-detect",
722
- delete: "Delete code block"
723
- };
724
- const defaultCommentLabels = {
725
- open: "Open",
726
- resolved: "Resolved",
727
- dismissed: "Dismissed",
728
- outdated: "Outdated",
729
- ambiguous: "Ambiguous",
730
- partial: "Partially matched",
731
- gutterTitle: "Comment"
732
- };
733
1017
  const wrapper = "_wrapper_5i2vi_2";
734
1018
  const header$1 = "_header_5i2vi_18";
735
1019
  const langTrigger = "_langTrigger_5i2vi_28";
@@ -922,9 +1206,8 @@ const MarkdownWysiwygEditor = forwardRef(function MarkdownWysiwygEditor2({
922
1206
  showCommentGutter = true,
923
1207
  commentInteractive = true
924
1208
  }, ref) {
925
- const preparedInitial = enrichMarkdownCitations(
926
- initialMarkdown,
927
- sources ?? []
1209
+ const preparedInitial = prepareChartMarkdown(
1210
+ enrichMarkdownCitations(initialMarkdown, sources ?? [])
928
1211
  );
929
1212
  const editor = useEditor({
930
1213
  extensions: [
@@ -932,6 +1215,7 @@ const MarkdownWysiwygEditor = forwardRef(function MarkdownWysiwygEditor2({
932
1215
  CodeBlock.configure({ lowlight, codeBlockLabels }),
933
1216
  ImageWithConfirmDelete.configure({ inline: false }),
934
1217
  ImportPlaceholder,
1218
+ createChart({ editable: true }),
935
1219
  createCitationRef({ renderCitation }),
936
1220
  CommentMark,
937
1221
  commentAnchorExtension({
@@ -943,7 +1227,7 @@ const MarkdownWysiwygEditor = forwardRef(function MarkdownWysiwygEditor2({
943
1227
  getId: makeTocGetId(),
944
1228
  onUpdate: (anchors) => {
945
1229
  onTocChange == null ? void 0 : onTocChange(
946
- anchors.filter((a2) => a2.level <= 6).map((a2) => ({ id: a2.id, level: a2.level, text: a2.textContent }))
1230
+ anchors.filter((a3) => a3.level <= 6).map((a3) => ({ id: a3.id, level: a3.level, text: a3.textContent }))
947
1231
  );
948
1232
  }
949
1233
  }),
@@ -1054,7 +1338,9 @@ function MarkdownPreview({
1054
1338
  className
1055
1339
  }) {
1056
1340
  const prepared = useMemo(
1057
- () => enrichMarkdownCitations(markdown, sources ?? []),
1341
+ () => prepareChartMarkdown(
1342
+ enrichMarkdownCitations(markdown, sources ?? [])
1343
+ ),
1058
1344
  [markdown, sources]
1059
1345
  );
1060
1346
  const extensions = useMemo(
@@ -1062,6 +1348,7 @@ function MarkdownPreview({
1062
1348
  ...baseExtensions,
1063
1349
  pureCodeBlock,
1064
1350
  pureImage,
1351
+ createChart({ editable: false }),
1065
1352
  createCitationRef({ renderCitation }),
1066
1353
  Markdown
1067
1354
  ],
@@ -1119,7 +1406,9 @@ function resolveImportMenuItems({
1119
1406
  return [markdown];
1120
1407
  }
1121
1408
  function insertMarkdown(editor, markdown, sources = []) {
1122
- const prepared = enrichMarkdownCitations(markdown, sources);
1409
+ const prepared = prepareChartMarkdown(
1410
+ enrichMarkdownCitations(markdown, sources)
1411
+ );
1123
1412
  if (!prepared) return;
1124
1413
  if (tryInsertMarkdown(editor, prepared)) return;
1125
1414
  for (const block of splitTopLevelBlocks(prepared)) {
@@ -2849,9 +3138,10 @@ export {
2849
3138
  COMMENT_ACTIVE_META,
2850
3139
  COMMENT_CLICK_META,
2851
3140
  COMMENT_GUTTER_META,
3141
+ C as ChartMount,
2852
3142
  CheckIcon,
2853
3143
  ChevronDownIcon,
2854
- C as CitationInteractive,
3144
+ a as CitationInteractive,
2855
3145
  CitationRef,
2856
3146
  CodeBlockView,
2857
3147
  CodeIcon,
@@ -2877,8 +3167,9 @@ export {
2877
3167
  MarkdownWysiwygEditor,
2878
3168
  MenuIcon,
2879
3169
  RedoIcon,
2880
- R as ReportContent,
2881
- R2 as ReportContentInteractive,
3170
+ R2 as ReportContent,
3171
+ R as ReportContentInteractive,
3172
+ b as ReportContentWithCharts,
2882
3173
  RowAfterIcon,
2883
3174
  RowBeforeIcon,
2884
3175
  RowDeleteIcon,
@@ -2888,16 +3179,18 @@ export {
2888
3179
  TrashIcon,
2889
3180
  UnderlineIcon,
2890
3181
  UndoIcon,
2891
- a as applyCitationSources,
3182
+ a2 as applyCitationSources,
2892
3183
  applyCommentAnchorsToEditor,
2893
3184
  baseExtensions,
2894
- d as blockTextHash,
3185
+ g as blockTextHash,
2895
3186
  collectCommentIds,
2896
3187
  commentAnchorExtension,
2897
3188
  commentAnchorPlugin,
2898
3189
  commentAnchorPluginKey,
2899
3190
  commentRangesById,
3191
+ createChart,
2900
3192
  createCitationRef,
3193
+ defaultChartLabels,
2901
3194
  defaultCodeBlockLabels,
2902
3195
  defaultColorPaletteLabels,
2903
3196
  defaultCommentLabels,
@@ -2913,12 +3206,17 @@ export {
2913
3206
  makeTocGetId,
2914
3207
  mapCommentAnchors,
2915
3208
  mergeCommentIntervals,
3209
+ m as mountChartsInContainer,
2916
3210
  nextComment,
3211
+ prepareChartMarkdown,
3212
+ d as pureChart,
2917
3213
  pureCodeBlock,
2918
3214
  pureImage,
2919
3215
  r as readCitationAttrs,
2920
- s2 as scrollToTocHeading,
2921
- s as stabilizeMarkdown,
3216
+ reportChart,
3217
+ s as scrollToTocHeading,
3218
+ serializeChartPayload,
3219
+ s2 as stabilizeMarkdown,
2922
3220
  stripCommentAnchorMarks,
2923
3221
  useIsMobile
2924
3222
  };