@bendyline/squisq-editor-react 2.13.0 → 2.13.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.
@@ -5,7 +5,7 @@ import {
5
5
  import {
6
6
  markdownToTiptap,
7
7
  tiptapToMarkdown
8
- } from "./chunk-LTT6QQHJ.js";
8
+ } from "./chunk-V7HUUMMB.js";
9
9
 
10
10
  // src/InsertMenuItems.tsx
11
11
  import { createContext, useContext, useEffect, useMemo, useRef } from "react";
@@ -1133,8 +1133,67 @@ import {
1133
1133
  import { createDocument } from "@tiptap/core";
1134
1134
  import { closeHistory as closeHistory2 } from "@tiptap/pm/history";
1135
1135
 
1136
+ // src/tiptap/replaceSelection.ts
1137
+ import { createNodeFromContent, selectionToInsertionEnd } from "@tiptap/core";
1138
+ import { Fragment as Fragment2, Slice } from "@tiptap/pm/model";
1139
+ import { AllSelection, Selection as Selection2, TextSelection as TextSelection2 } from "@tiptap/pm/state";
1140
+ function trimEmptyEdges(doc, $from, $to) {
1141
+ let start = $from;
1142
+ let end = $to;
1143
+ if (!start.sameParent(end) && end.parent.isTextblock && end.parentOffset === 0) {
1144
+ const previous = Selection2.findFrom(doc.resolve(end.before()), -1, true);
1145
+ if (previous && previous.$head.pos >= start.pos) end = previous.$head;
1146
+ }
1147
+ if (!start.sameParent(end) && start.parent.isTextblock && start.parentOffset === start.parent.content.size) {
1148
+ const next = Selection2.findFrom(doc.resolve(start.after()), 1, true);
1149
+ if (next && next.$head.pos <= end.pos) start = next.$head;
1150
+ }
1151
+ return [start, end];
1152
+ }
1153
+ function wholeBlocks(doc, $from, $to, content) {
1154
+ const range = $from.blockRange($to);
1155
+ if (!range) return null;
1156
+ const first = Selection2.findFrom(doc.resolve(range.start), 1, true);
1157
+ const last = Selection2.findFrom(doc.resolve(range.end), -1, true);
1158
+ if (!first || !last || $from.pos > first.from || $to.pos < last.to) return null;
1159
+ if (!range.parent.canReplace(range.startIndex, range.endIndex, content)) return null;
1160
+ return { from: range.start, to: range.end };
1161
+ }
1162
+ function replaceSelectionWith(tr, content) {
1163
+ const { selection, doc } = tr;
1164
+ if (selection.empty) return false;
1165
+ if (!(selection instanceof TextSelection2 || selection instanceof AllSelection)) return false;
1166
+ const [$from, $to] = trimEmptyEdges(doc, selection.$from, selection.$to);
1167
+ const single = content.childCount === 1 ? content.firstChild : null;
1168
+ if (single?.isTextblock && !single.type.spec.code && $from.sameParent($to) && $from.parent.isTextblock && !$from.parent.type.spec.code) {
1169
+ tr.replace($from.pos, $to.pos, new Slice(Fragment2.from(single), 1, 1));
1170
+ } else {
1171
+ const blocks = wholeBlocks(doc, $from, $to, content);
1172
+ if (blocks) {
1173
+ tr.replaceWith(blocks.from, blocks.to, content);
1174
+ } else {
1175
+ tr.replaceRange($from.pos, $to.pos, Slice.maxOpen(content));
1176
+ }
1177
+ }
1178
+ selectionToInsertionEnd(tr, tr.steps.length - 1, -1);
1179
+ return true;
1180
+ }
1181
+ function replaceEditorSelection(editor, html) {
1182
+ if (editor.state.selection.empty) return false;
1183
+ let content;
1184
+ try {
1185
+ const parsed = createNodeFromContent(html, editor.schema, {
1186
+ parseOptions: { preserveWhitespace: "full", ...editor.options.parseOptions }
1187
+ });
1188
+ content = parsed instanceof Fragment2 ? parsed : Fragment2.from(parsed);
1189
+ } catch {
1190
+ return false;
1191
+ }
1192
+ return editor.chain().focus().command(({ tr }) => replaceSelectionWith(tr, content)).run();
1193
+ }
1194
+
1136
1195
  // src/selectionMarkdown.ts
1137
- import { DOMSerializer, Fragment as Fragment2 } from "@tiptap/pm/model";
1196
+ import { DOMSerializer, Fragment as Fragment3 } from "@tiptap/pm/model";
1138
1197
  function selectionMarkdown(state) {
1139
1198
  const { selection } = state;
1140
1199
  if (selection.empty) return "";
@@ -1143,7 +1202,7 @@ function selectionMarkdown(state) {
1143
1202
  let inline = false;
1144
1203
  if ($from.sameParent($to) && $from.parent.isTextblock) {
1145
1204
  inline = $from.parentOffset !== 0 || $to.parentOffset !== $from.parent.content.size;
1146
- fragment = !inline ? Fragment2.from($from.parent) : state.doc.slice(from, to).content;
1205
+ fragment = !inline ? Fragment3.from($from.parent) : state.doc.slice(from, to).content;
1147
1206
  }
1148
1207
  const container = document.createElement("div");
1149
1208
  const target = inline ? container.appendChild(document.createElement("p")) : container;
@@ -1942,7 +2001,10 @@ function EditorProvider({
1942
2001
  const replaceSelection = useCallback3(
1943
2002
  (markdown) => {
1944
2003
  if (activeView === "wysiwyg" && tiptapEditor) {
1945
- tiptapEditor.chain().focus().insertContent(markdownToTiptap(markdown)).run();
2004
+ const html = markdownToTiptap(markdown);
2005
+ if (!replaceEditorSelection(tiptapEditor, html)) {
2006
+ tiptapEditor.chain().focus().insertContent(html).run();
2007
+ }
1946
2008
  return true;
1947
2009
  }
1948
2010
  if (activeView === "raw" && monacoEditor) {
@@ -1,10 +1,12 @@
1
1
  import {
2
+ AlignedTableCell,
3
+ AlignedTableHeader,
2
4
  MarkdownEscape
3
- } from "./chunk-MJNLKPGH.js";
5
+ } from "./chunk-2D2VBYX7.js";
4
6
  import {
5
7
  markdownToTiptap,
6
8
  tiptapToMarkdown
7
- } from "./chunk-LTT6QQHJ.js";
9
+ } from "./chunk-V7HUUMMB.js";
8
10
 
9
11
  // src/jsonEditor/JsonEditorContext.tsx
10
12
  import { createContext, useContext, useEffect, useMemo } from "react";
@@ -70,8 +72,6 @@ import { useEditor, EditorContent } from "@tiptap/react";
70
72
  import StarterKit from "@tiptap/starter-kit";
71
73
  import Table from "@tiptap/extension-table";
72
74
  import TableRow from "@tiptap/extension-table-row";
73
- import TableCell from "@tiptap/extension-table-cell";
74
- import TableHeader from "@tiptap/extension-table-header";
75
75
  import TaskList from "@tiptap/extension-task-list";
76
76
  import TaskItem from "@tiptap/extension-task-item";
77
77
  import Placeholder from "@tiptap/extension-placeholder";
@@ -90,16 +90,16 @@ function EmbeddedRichTextField(props) {
90
90
  }),
91
91
  Table.configure({ resizable: false }),
92
92
  TableRow,
93
- TableCell,
94
- TableHeader,
93
+ AlignedTableCell,
94
+ AlignedTableHeader,
95
95
  TaskList,
96
96
  TaskItem.configure({ nested: true }),
97
97
  Placeholder.configure({ placeholder: placeholder ?? "" }),
98
98
  MarkdownEscape
99
99
  ],
100
100
  content: markdownToTiptap(value),
101
- onUpdate: ({ editor: ed }) => {
102
- if (isExternalUpdate.current) return;
101
+ onUpdate: ({ editor: ed, transaction }) => {
102
+ if (!transaction.docChanged || isExternalUpdate.current) return;
103
103
  const html = ed.getHTML();
104
104
  const md = tiptapToMarkdown(html);
105
105
  lastValueRef.current = md;
@@ -673,6 +673,7 @@ function tiptapToMarkdown(html) {
673
673
  "| " + aligns.map((a) => {
674
674
  if (a === "center") return ":---:";
675
675
  if (a === "right") return "---:";
676
+ if (a === "left") return ":---";
676
677
  return "---";
677
678
  }).join(" | ") + " |"
678
679
  );
package/dist/index.js CHANGED
@@ -243,7 +243,7 @@ import {
243
243
  videoEmbedParagraphJson,
244
244
  viewStateFromBinding,
245
245
  writeHeadingViewState
246
- } from "./chunk-SDSVFFJO.js";
246
+ } from "./chunk-NRJDPKOS.js";
247
247
  import {
248
248
  EditorProvider,
249
249
  applySourceEditsToText,
@@ -264,7 +264,7 @@ import {
264
264
  useBlockNavigator,
265
265
  useEditorContext,
266
266
  useEditorInsertMenuItems
267
- } from "./chunk-2DHVG55U.js";
267
+ } from "./chunk-OMSRCHQ4.js";
268
268
  import {
269
269
  SPEECH_INPUT_SAMPLE_RATE,
270
270
  isSpeechInputProviderFactory,
@@ -273,14 +273,14 @@ import {
273
273
  import "./chunk-A2H3JOA5.js";
274
274
  import {
275
275
  JsonEditor
276
- } from "./chunk-HXQQK2S2.js";
276
+ } from "./chunk-S73OV74D.js";
277
277
  import {
278
278
  MarkdownEscape
279
- } from "./chunk-MJNLKPGH.js";
279
+ } from "./chunk-2D2VBYX7.js";
280
280
  import {
281
281
  markdownToTiptap,
282
282
  tiptapToMarkdown
283
- } from "./chunk-LTT6QQHJ.js";
283
+ } from "./chunk-V7HUUMMB.js";
284
284
  import {
285
285
  ImageEditor,
286
286
  ImageViewer,
@@ -1,8 +1,8 @@
1
1
  import {
2
2
  JsonEditor
3
- } from "../chunk-HXQQK2S2.js";
4
- import "../chunk-MJNLKPGH.js";
5
- import "../chunk-LTT6QQHJ.js";
3
+ } from "../chunk-S73OV74D.js";
4
+ import "../chunk-2D2VBYX7.js";
5
+ import "../chunk-V7HUUMMB.js";
6
6
  export {
7
7
  JsonEditor
8
8
  };
@@ -19,9 +19,9 @@ import {
19
19
  updateReviewDecorations,
20
20
  useReview,
21
21
  useReviewState
22
- } from "../chunk-2DHVG55U.js";
22
+ } from "../chunk-OMSRCHQ4.js";
23
23
  import "../chunk-DNEVUOBZ.js";
24
- import "../chunk-LTT6QQHJ.js";
24
+ import "../chunk-V7HUUMMB.js";
25
25
 
26
26
  // src/review/proofingAdapter.ts
27
27
  import {
@@ -5,16 +5,16 @@ import {
5
5
  RawEditor,
6
6
  WysiwygEditor,
7
7
  useEditorContextMenuItems
8
- } from "../chunk-SDSVFFJO.js";
8
+ } from "../chunk-NRJDPKOS.js";
9
9
  import {
10
10
  EditorProvider,
11
11
  useEditorContext,
12
12
  useEditorInsertMenuItems
13
- } from "../chunk-2DHVG55U.js";
13
+ } from "../chunk-OMSRCHQ4.js";
14
14
  import "../chunk-DNEVUOBZ.js";
15
15
  import "../chunk-A2H3JOA5.js";
16
- import "../chunk-MJNLKPGH.js";
17
- import "../chunk-LTT6QQHJ.js";
16
+ import "../chunk-2D2VBYX7.js";
17
+ import "../chunk-V7HUUMMB.js";
18
18
  import "../chunk-HLU6ZBS7.js";
19
19
  import "../chunk-LXGQA2SY.js";
20
20
  import "../chunk-LRZJD5YD.js";
@@ -8018,14 +8018,7 @@
8018
8018
  background: var(--squisq-surface-overlay);
8019
8019
  box-shadow: 0 12px 32px rgba(15, 23, 42, 0.2), 0 2px 6px rgba(15, 23, 42, 0.08);
8020
8020
  box-sizing: border-box;
8021
- font-family:
8022
- -apple-system,
8023
- BlinkMacSystemFont,
8024
- "Segoe UI",
8025
- "Noto Sans",
8026
- Helvetica,
8027
- Arial,
8028
- sans-serif;
8021
+ font-family: var( --squisq-ux-font, -apple-system, BlinkMacSystemFont, "Segoe UI", "Noto Sans", Helvetica, Arial, sans-serif );
8029
8022
  animation: squisq-use-mode-menu-in 0.12s ease-out;
8030
8023
  }
8031
8024
  .squisq-use-mode-menu-item {
@@ -8184,10 +8177,7 @@
8184
8177
  background: var(--cover-bg);
8185
8178
  color: var(--cover-text);
8186
8179
  box-shadow: 0 12px 32px rgba(0, 0, 0, 0.2);
8187
- font-family:
8188
- system-ui,
8189
- -apple-system,
8190
- sans-serif;
8180
+ font-family: var(--squisq-ux-font, system-ui, -apple-system, sans-serif);
8191
8181
  color-scheme: light;
8192
8182
  }
8193
8183
  .squisq-cover-slide-menu[data-theme=dark] {
@@ -8618,6 +8608,7 @@
8618
8608
  border: 1px solid var(--squisq-border-subtle);
8619
8609
  border-radius: 6px;
8620
8610
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.12);
8611
+ font-family: var(--squisq-ux-font, system-ui, sans-serif);
8621
8612
  }
8622
8613
  .squisq-toolbar-overflow-menu--down {
8623
8614
  top: 100%;
@@ -9805,6 +9796,7 @@
9805
9796
  border: 1px solid var(--squisq-block-props-divider);
9806
9797
  border-radius: 10px;
9807
9798
  box-shadow: 0 8px 24px rgba(0, 0, 0, 0.12), 0 2px 6px rgba(0, 0, 0, 0.08);
9799
+ font-family: var(--squisq-ux-font, system-ui, sans-serif);
9808
9800
  }
9809
9801
  .squisq-block-props-row {
9810
9802
  display: flex;
@@ -14180,6 +14172,7 @@ button.squisq-view-menu-radio-row:focus-visible {
14180
14172
  border-radius: 8px;
14181
14173
  box-shadow: 0 8px 28px rgba(0, 0, 0, 0.18);
14182
14174
  padding: 6px;
14175
+ font-family: var(--squisq-ux-font, system-ui, sans-serif);
14183
14176
  display: grid;
14184
14177
  grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
14185
14178
  gap: 4px;
@@ -14601,6 +14594,7 @@ button.squisq-view-menu-radio-row:focus-visible {
14601
14594
  border: 1px solid var(--squisq-block-props-divider);
14602
14595
  border-radius: 10px;
14603
14596
  box-shadow: 0 8px 24px rgba(0, 0, 0, 0.12), 0 2px 6px rgba(0, 0, 0, 0.08);
14597
+ font-family: var(--squisq-ux-font, system-ui, sans-serif);
14604
14598
  overflow: hidden;
14605
14599
  }
14606
14600
  .squisq-transition-flyout-search {
@@ -19334,6 +19328,7 @@ button.squisq-ascii-timeline-track-name:focus-visible {
19334
19328
  border-radius: 8px;
19335
19329
  box-shadow: 0 6px 24px rgba(0, 0, 0, 0.14);
19336
19330
  padding: 4px;
19331
+ font-family: var(--squisq-ux-font, system-ui, sans-serif);
19337
19332
  font-size: 13px;
19338
19333
  }
19339
19334
  .squisq-proof-menu-header {
@@ -19381,6 +19376,7 @@ button.squisq-ascii-timeline-track-name:focus-visible {
19381
19376
  border-radius: 8px;
19382
19377
  box-shadow: 0 6px 24px rgba(0, 0, 0, 0.14);
19383
19378
  padding: 8px 10px;
19379
+ font-family: var(--squisq-ux-font, system-ui, sans-serif);
19384
19380
  font-size: 12px;
19385
19381
  line-height: 1.4;
19386
19382
  color: var(--squisq-text);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bendyline/squisq-editor-react",
3
- "version": "2.13.0",
3
+ "version": "2.13.2",
4
4
  "description": "React editor shell with raw/WYSIWYG/preview modes for Squisq documents",
5
5
  "license": "MIT",
6
6
  "author": "Bendyline",
@@ -104,10 +104,10 @@
104
104
  "dependencies": {
105
105
  "@bendyline/squisq": "2.13.0",
106
106
  "@bendyline/squisq-calc": "2.11.2",
107
- "@bendyline/squisq-formats": "2.8.0",
107
+ "@bendyline/squisq-formats": "2.8.1",
108
108
  "@bendyline/squisq-grid-react": "2.11.29",
109
- "@bendyline/squisq-react": "2.12.8",
110
- "@bendyline/squisq-video-react": "2.5.9",
109
+ "@bendyline/squisq-react": "2.12.9",
110
+ "@bendyline/squisq-video-react": "2.5.10",
111
111
  "@fortawesome/fontawesome-free": "7.3.1",
112
112
  "@tiptap/core": "2.27.3",
113
113
  "@tiptap/extension-heading": "2.27.3",
@@ -1,20 +0,0 @@
1
- import {
2
- MARKDOWN_ESCAPE_ATTR
3
- } from "./chunk-LTT6QQHJ.js";
4
-
5
- // src/MarkdownEscape.ts
6
- import { Mark, mergeAttributes } from "@tiptap/core";
7
- var MarkdownEscape = Mark.create({
8
- name: "markdownEscape",
9
- inclusive: false,
10
- parseHTML() {
11
- return [{ tag: `span[${MARKDOWN_ESCAPE_ATTR}]` }];
12
- },
13
- renderHTML({ HTMLAttributes }) {
14
- return ["span", mergeAttributes(HTMLAttributes, { [MARKDOWN_ESCAPE_ATTR]: "" }), 0];
15
- }
16
- });
17
-
18
- export {
19
- MarkdownEscape
20
- };