@pie-lib/editable-html-tip-tap 3.0.0 → 3.0.1-next.20261002220849

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.
@@ -1,35 +1,36 @@
1
- import { normalizeInitialMarkup as e } from "../utils/helper.js";
2
- import t from "../extensions/extended-table.js";
3
- import { ExtendedTableCell as n, ExtendedTableHeader as r } from "../extensions/extended-table-cell.js";
4
- import { DivNode as i } from "../extensions/div-node.js";
5
- import { EnsureEmptyRootIsDiv as a } from "../extensions/ensure-empty-root-div.js";
1
+ import { PlainTextPaste as e } from "../plain-text-paste.js";
2
+ import { normalizeInitialMarkup as t } from "../utils/helper.js";
3
+ import n from "../extensions/extended-table.js";
4
+ import { ExtendedTableCell as r, ExtendedTableHeader as i } from "../extensions/extended-table-cell.js";
5
+ import { DivNode as a } from "../extensions/div-node.js";
6
+ import { EnsureEmptyRootIsDiv as ee } from "../extensions/ensure-empty-root-div.js";
6
7
  import { EnsureListItemContentIsDiv as o } from "../extensions/ensure-list-item-content-is-div.js";
7
- import { DragInTheBlankNode as s, ExplicitConstructedResponseNode as c, InlineDropdownNode as l, MathTemplatedNode as u, ResponseAreaExtension as ee } from "../extensions/responseArea.js";
8
- import { MathNode as te } from "../extensions/math.js";
9
- import { ImageUploadNode as d } from "../extensions/image.js";
10
- import { Media as f } from "../extensions/media.js";
11
- import { CSSMark as ne } from "../extensions/css.js";
12
- import { ExtendedListItem as p } from "../extensions/extended-list-item.js";
13
- import { HeadingParagraph as re } from "../extensions/heading-paragraph.js";
8
+ import { DragInTheBlankNode as s, ExplicitConstructedResponseNode as c, InlineDropdownNode as te, MathTemplatedNode as ne, ResponseAreaExtension as re } from "../extensions/responseArea.js";
9
+ import { MathNode as l } from "../extensions/math.js";
10
+ import { ImageUploadNode as u } from "../extensions/image.js";
11
+ import { Media as d } from "../extensions/media.js";
12
+ import { CSSMark as f } from "../extensions/css.js";
13
+ import { ExtendedListItem as ie } from "../extensions/extended-list-item.js";
14
+ import { HeadingParagraph as p } from "../extensions/heading-paragraph.js";
14
15
  import { valueToSize as m } from "../utils/size.js";
15
- import h from "./TiptapContainer.js";
16
- import { PLUGINS_MAP as g, buildExtensions as _ } from "../extensions/index.js";
17
- import { useCallback as v, useEffect as y, useMemo as b, useState as x } from "react";
18
- import { debounce as S } from "@pie-element/shared-lodash";
19
- import { EditorContent as C, useEditor as w, useEditorState as T } from "@tiptap/react";
20
- import { styled as E } from "@mui/material/styles";
21
- import D from "@tiptap/starter-kit";
22
- import { TextStyleKit as O } from "@tiptap/extension-text-style";
23
- import { CharacterCount as k } from "@tiptap/extension-character-count";
24
- import A from "@tiptap/extension-superscript";
25
- import j from "@tiptap/extension-subscript";
26
- import M from "@tiptap/extension-text-align";
27
- import N from "@tiptap/extension-image";
28
- import P from "@tiptap/extension-placeholder";
29
- import { TableRow as F } from "@tiptap/extension-table-row";
30
- import { jsx as I } from "react/jsx-runtime";
16
+ import ae from "./TiptapContainer.js";
17
+ import { PLUGINS_MAP as h, buildExtensions as g } from "../extensions/index.js";
18
+ import { useCallback as _, useEffect as v, useMemo as y, useState as b } from "react";
19
+ import { debounce as x } from "@pie-element/shared-lodash";
20
+ import { EditorContent as S, useEditor as C, useEditorState as w } from "@tiptap/react";
21
+ import { styled as T } from "@mui/material/styles";
22
+ import E from "@tiptap/starter-kit";
23
+ import { TextStyleKit as D } from "@tiptap/extension-text-style";
24
+ import { CharacterCount as O } from "@tiptap/extension-character-count";
25
+ import k from "@tiptap/extension-superscript";
26
+ import A from "@tiptap/extension-subscript";
27
+ import j from "@tiptap/extension-text-align";
28
+ import M from "@tiptap/extension-image";
29
+ import N from "@tiptap/extension-placeholder";
30
+ import { TableRow as P } from "@tiptap/extension-table-row";
31
+ import { jsx as F } from "react/jsx-runtime";
31
32
  //#region src/components/EditableHtml.tsx
32
- var ie = {
33
+ var I = {
33
34
  position: "bottom",
34
35
  alignment: "left",
35
36
  alwaysVisible: !1,
@@ -87,50 +88,50 @@ var ie = {
87
88
  spellcheck: e ? "true" : "false",
88
89
  autocorrect: e ? "on" : "off",
89
90
  autocapitalize: e ? "on" : "off"
90
- }), V = (C) => {
91
- let { showParagraphs: E, separateParagraphs: V } = C.pluginProps || {}, [ae, U] = x([]), [W, G] = x(!1), { toolbarOpts: K } = C, q = v((e) => {
91
+ }), V = (S) => {
92
+ let { showParagraphs: T, separateParagraphs: V } = S.pluginProps || {}, [oe, U] = b([]), [W, G] = b(!1), { toolbarOpts: K } = S, q = _((e) => {
92
93
  U((t) => {
93
94
  let n = t.filter((t) => t.pos !== e);
94
95
  return n.length === 0 && G(!1), n;
95
96
  });
96
97
  }, [U]), J = {
97
- ...ie,
98
+ ...I,
98
99
  ...K
99
- }, Y = v((e) => {
100
+ }, Y = _((e) => {
100
101
  let t = e.getHTML();
101
- C.markup !== t && C.onChange?.(t), J.doneOn === "blur" && C.onDone?.(t);
102
+ S.markup !== t && S.onChange?.(t), J.doneOn === "blur" && S.onDone?.(t);
102
103
  }, [
103
- C.markup,
104
- C.onChange,
105
- C.onDone,
104
+ S.markup,
105
+ S.onChange,
106
+ S.onDone,
106
107
  J.doneOn
107
- ]), X = b(() => ({
108
+ ]), X = y(() => ({
108
109
  ...L,
109
- ...C.responseAreaProps,
110
+ ...S.responseAreaProps,
110
111
  onInlineDropdownToolbarClose: Y
111
- }), [C.responseAreaProps, Y]), oe = b(() => {
112
- let { customPlugins: e, ...t } = C.pluginProps || {};
112
+ }), [S.responseAreaProps, Y]), se = y(() => {
113
+ let { customPlugins: e, ...t } = S.pluginProps || {};
113
114
  e ||= [];
114
- let n = (C.activePlugins || R)?.filter((e) => {
115
- let n = g[e] || e, r = t[n] || {};
115
+ let n = (S.activePlugins || R)?.filter((e) => {
116
+ let n = h[e] || e, r = t[n] || {};
116
117
  return !r || !r.disabled;
117
118
  });
118
- return _(n, e, {
119
+ return g(n, e, {
119
120
  math: {},
120
- textAlign: C.textAlign,
121
+ textAlign: S.textAlign,
121
122
  html: {},
122
- extraCSSRules: C.extraCSSRules || {},
123
- image: { ...C.imageSupport },
123
+ extraCSSRules: S.extraCSSRules || {},
124
+ image: { ...S.imageSupport },
124
125
  toolbar: {},
125
126
  table: {},
126
127
  responseArea: { type: X.type },
127
- languageCharacters: C.languageCharactersProps,
128
+ languageCharacters: S.languageCharactersProps,
128
129
  keyPadCharacterRef: {},
129
130
  setKeypadInteraction: {},
130
131
  media: {}
131
132
  });
132
- }, [C, X.type]), se = [
133
- M.configure({
133
+ }, [S, X.type]), ce = [
134
+ j.configure({
134
135
  types: [
135
136
  "heading",
136
137
  "paragraph",
@@ -152,9 +153,10 @@ var ie = {
152
153
  "justify"
153
154
  ]
154
155
  }),
155
- O,
156
- k.configure({ limit: C.charactersLimit || 1e6 }),
157
- D.configure({
156
+ D,
157
+ e,
158
+ O.configure({ limit: S.charactersLimit || 1e6 }),
159
+ E.configure({
158
160
  trailingNode: {
159
161
  node: "paragraph",
160
162
  notAfter: ["paragraph", "div"]
@@ -164,51 +166,51 @@ var ie = {
164
166
  linkOnPaste: !1
165
167
  }
166
168
  }),
167
- p,
168
- i,
169
- re,
169
+ ie,
170
170
  a,
171
+ p,
172
+ ee,
171
173
  o,
172
- P.configure({
173
- placeholder: C.placeholder,
174
+ N.configure({
175
+ placeholder: S.placeholder,
174
176
  showOnlyWhenEditable: !0,
175
177
  showOnlyCurrent: !1,
176
178
  includeChildren: !0
177
179
  }),
178
- t,
179
- F,
180
- r,
181
180
  n,
182
- ee.configure(X),
181
+ P,
182
+ i,
183
+ r,
184
+ re.configure(X),
183
185
  c.configure(X),
184
186
  s.configure(X),
185
- l.configure(X),
186
- u.configure(X),
187
- te.configure({
187
+ te.configure(X),
188
+ ne.configure(X),
189
+ l.configure({
188
190
  toolbarOpts: J,
189
- math: C.pluginProps?.math || {}
191
+ math: S.pluginProps?.math || {}
190
192
  }),
191
- j,
192
193
  A,
193
- N,
194
- d.configure({
194
+ k,
195
+ M,
196
+ u.configure({
195
197
  toolbarOpts: J,
196
198
  imageHandling: {
197
- disableImageAlignmentButtons: C.disableImageAlignmentButtons,
198
- onDone: (e) => C.onDone?.(e.getHTML()),
199
- onDelete: C.imageSupport && C.imageSupport.delete && ((e) => {
199
+ disableImageAlignmentButtons: S.disableImageAlignmentButtons,
200
+ onDone: (e) => S.onDone?.(e.getHTML()),
201
+ onDelete: S.imageSupport && S.imageSupport.delete && ((e) => {
200
202
  let { src: t } = e.attrs;
201
- C.imageSupport.delete(t, (t) => {
203
+ S.imageSupport.delete(t, (t) => {
202
204
  q(e.pos);
203
205
  });
204
206
  }),
205
- insertImageRequested: C.imageSupport && ((e, t, n) => {
207
+ insertImageRequested: S.imageSupport && ((e, t, n) => {
206
208
  let [r, i] = t, a = (t) => {
207
209
  let n;
208
- W && t && (n = C.onChange), q(i), n?.(e.getHTML());
210
+ W && t && (n = S.onChange), q(i), n?.(e.getHTML());
209
211
  };
210
212
  e._insertingImage = !0, U((e) => [...e, r]), (() => {
211
- let t = n(a), r = S(() => {
213
+ let t = n(a), r = x(() => {
212
214
  let t = () => window.removeEventListener("focus", r);
213
215
  if (!e._insertingImage) {
214
216
  t();
@@ -216,39 +218,39 @@ var ie = {
216
218
  }
217
219
  q(i), e._insertingImage = !1, t();
218
220
  }, 500);
219
- window.addEventListener("focus", r), C.imageSupport.add(t);
221
+ window.addEventListener("focus", r), S.imageSupport.add(t);
220
222
  })();
221
223
  }),
222
- maxImageWidth: C.maxImageWidth,
223
- maxImageHeight: C.maxImageHeight
224
+ maxImageWidth: S.maxImageWidth,
225
+ maxImageHeight: S.maxImageHeight
224
226
  },
225
227
  limit: 3
226
228
  }),
227
- f.configure({ uploadSoundSupport: C.uploadSoundSupport }),
228
- ne.configure({ extraCSSRules: C.extraCSSRules })
229
- ], Z = C.spellCheck !== !1, Q = w({
230
- extensions: se,
229
+ d.configure({ uploadSoundSupport: S.uploadSoundSupport }),
230
+ f.configure({ extraCSSRules: S.extraCSSRules })
231
+ ], Z = S.spellCheck !== !1, Q = C({
232
+ extensions: ce,
231
233
  immediatelyRender: !1,
232
234
  editorProps: {
233
235
  attributes: B(Z),
234
236
  handleKeyDown(e, t) {
235
- return C.onKeyDown ? C.onKeyDown(t) : !1;
237
+ return S.onKeyDown ? S.onKeyDown(t) : !1;
236
238
  }
237
239
  },
238
- editable: !C.disabled,
239
- content: e(C.markup),
240
+ editable: !S.disabled,
241
+ content: t(S.markup),
240
242
  onUpdate: ({ editor: e, transaction: t }) => {
241
- t.isDone && C.onChange?.(e.getHTML());
243
+ t.isDone && S.onChange?.(e.getHTML());
242
244
  },
243
245
  onBlur: ({ editor: e }) => {
244
246
  e._insertingImage || e._toolbarOpened || e.isActive("inline_dropdown") || e.isActive("explicit_constructed_response") || !e.schema || Y(e);
245
247
  }
246
- }, [C.charactersLimit]);
247
- y(() => {
248
- C.editorRef && C.editorRef(Q);
249
- }, [C.editorRef, Q]), y(() => {
250
- Q?.setEditable(!C.disabled);
251
- }, [C.disabled, Q]), y(() => {
248
+ }, [S.charactersLimit]);
249
+ v(() => {
250
+ S.editorRef && S.editorRef(Q);
251
+ }, [S.editorRef, Q]), v(() => {
252
+ Q?.setEditable(!S.disabled);
253
+ }, [S.disabled, Q]), v(() => {
252
254
  if (!Q) return;
253
255
  let e = Q.options?.editorProps, t = {
254
256
  ...e?.attributes,
@@ -258,20 +260,20 @@ var ie = {
258
260
  ...e,
259
261
  attributes: t
260
262
  } });
261
- }, [Z, Q]), y(() => {
263
+ }, [Z, Q]), v(() => {
262
264
  if (!Q) return;
263
- let t = e(C.markup);
264
- t !== Q.getHTML() && Q.commands.setContent(t, { emitUpdate: !1 });
265
- }, [C.markup, Q]), y(() => {
265
+ let e = t(S.markup);
266
+ e !== Q.getHTML() && Q.commands.setContent(e, { emitUpdate: !1 });
267
+ }, [S.markup, Q]), v(() => {
266
268
  Object.entries(z).forEach(([e, t]) => {
267
269
  document.documentElement.style.setProperty(e, t);
268
270
  });
269
271
  }, []);
270
- let ce = T({
272
+ let le = w({
271
273
  editor: Q,
272
274
  selector: (e) => ({ isFocused: e.editor?.isFocused })
273
- }), $ = b(() => {
274
- let { minWidth: e, width: t, maxWidth: n, minHeight: r, height: i, maxHeight: a } = C;
275
+ }), $ = y(() => {
276
+ let { minWidth: e, width: t, maxWidth: n, minHeight: r, height: i, maxHeight: a } = S;
275
277
  return {
276
278
  width: m(t),
277
279
  minWidth: m(e),
@@ -280,25 +282,25 @@ var ie = {
280
282
  minHeight: m(r),
281
283
  maxHeight: m(a)
282
284
  };
283
- }, [C]);
284
- return /* @__PURE__ */ I(h, {
285
- ...C,
286
- activePlugins: oe,
285
+ }, [S]);
286
+ return /* @__PURE__ */ F(ae, {
287
+ ...S,
288
+ activePlugins: se,
287
289
  toolbarOpts: J,
288
- editorState: ce,
290
+ editorState: le,
289
291
  editor: Q,
290
- children: Q && /* @__PURE__ */ I(H, {
292
+ children: Q && /* @__PURE__ */ F(H, {
291
293
  style: {
292
294
  minHeight: $.minHeight,
293
295
  height: $.height,
294
296
  maxHeight: $.maxHeight
295
297
  },
296
- showParagraph: E && !E.disabled,
298
+ showParagraph: T && !T.disabled,
297
299
  separateParagraph: V && !V.disabled,
298
300
  editor: Q
299
301
  })
300
302
  });
301
- }, H = E(C, { shouldForwardProp: (e) => !["showParagraph", "separateParagraph"].includes(e) })(({ showParagraph: e, separateParagraph: t }) => ({
303
+ }, H = T(S, { shouldForwardProp: (e) => !["showParagraph", "separateParagraph"].includes(e) })(({ showParagraph: e, separateParagraph: t }) => ({
302
304
  display: "flex",
303
305
  outline: "none !important",
304
306
  "& .ProseMirror": {
@@ -0,0 +1,12 @@
1
+ import { Extension } from '@tiptap/core';
2
+ /**
3
+ * Pastes and drops rich text from outside a PIE editor as plain text, as the Slate editor did,
4
+ * except that math copied from rendered PIE content stays math. Parsed as HTML, content from Word
5
+ * keeps its fonts, sizes, colours, alignment and class names through TextStyleKit, TextAlign and
6
+ * CSSMark (PIE-1145).
7
+ *
8
+ * Mirrored in `packages/lib-svelte/editable-html-tiptap-svelte/src/plain-text-paste.ts`. Upstream
9
+ * pie-lib has no such file, so upstream sync preserves this one and re-registers it in
10
+ * `EditableHtml.tsx` (`preserve.editable-html-tip-tap.plain-text-paste`).
11
+ */
12
+ export declare const PlainTextPaste: Extension<any, any>;
@@ -0,0 +1,75 @@
1
+ import { Extension as e } from "@tiptap/core";
2
+ import { Plugin as t, PluginKey as n, TextSelection as r } from "@tiptap/pm/state";
3
+ //#region src/plain-text-paste.ts
4
+ var i = (e) => Array.from(e.items ?? []).some((e) => e.kind === "file" && e.type.startsWith("image/")), a = (e, t) => new DOMParser().parseFromString(e, "text/html").querySelector(t) !== null, o = (e) => e.includes("data-pm-slice") && a(e, "[data-pm-slice]"), s = (e) => /data-latex|data-type="?mathml/.test(e) && a(e, "[data-latex], [data-type=\"mathml\"]"), c = !1, l = (e) => e.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;"), u = (e) => e.replace(/\r*\n|\r/g, "\n").replace(/\n+$/, "");
5
+ function d(e) {
6
+ let t = e?.getData("text/html");
7
+ if (!e || !t || o(t)) return null;
8
+ let n = e.getData("text/plain"), r = Array.from(e.types).includes("text/rtf") && n.trim() !== "";
9
+ return !n || i(e) && !r ? null : {
10
+ text: n,
11
+ html: t
12
+ };
13
+ }
14
+ function f(e, t) {
15
+ let { schema: n } = t, r = t.selection.$from.marks(), i = (e) => {
16
+ let t = [];
17
+ return e.descendants((e) => (e.isTextblock && t.length && t.push(n.text(" ", r)), e.isText && e.text && t.push(n.text(e.text, r)), e.type === n.nodes.math && t.push(e.mark([])), !e.isInline)), t;
18
+ }, a = [];
19
+ e.content.firstChild?.isInline ? a.push(i(n.nodes.paragraph.create(null, e.content))) : e.content.descendants((e) => {
20
+ if (e.type.spec.tableRole === "row") {
21
+ let t = [];
22
+ return e.forEach((e) => {
23
+ t.push(i(e));
24
+ }), a.push(t.flatMap((e, t) => t ? [n.text(" ", r), ...e] : e)), !1;
25
+ }
26
+ return e.isTextblock ? (a.push(i(e)), !1) : !0;
27
+ });
28
+ let o = n.topNodeType.create(null, a.map((e) => n.nodes.paragraph.create(null, e)));
29
+ return a.length ? o.slice(1, o.content.size - 1) : o.slice(0, 0);
30
+ }
31
+ function p(e, { text: t, html: n }) {
32
+ let { selection: r } = e.state;
33
+ if ("$anchorCell" in r) {
34
+ let n = u(t).split("\n").map((e) => `<tr>${e.split(" ").map((e) => `<td>${l(e)}</td>`).join("")}</tr>`);
35
+ e.pasteHTML(`<table><tbody>${n.join("")}</tbody></table>`);
36
+ return;
37
+ }
38
+ if (e.state.schema.nodes.math && s(n)) {
39
+ c = !0;
40
+ try {
41
+ e.pasteHTML(n);
42
+ } finally {
43
+ c = !1;
44
+ }
45
+ return;
46
+ }
47
+ e.pasteText(r.$from.parent.type.spec.code ? u(t) : u(t).replace(/^$/gm, "\xA0"));
48
+ }
49
+ var m = e.create({
50
+ name: "plainTextPaste",
51
+ priority: 1e3,
52
+ addProseMirrorPlugins() {
53
+ return [new t({
54
+ key: new n("plainTextPaste"),
55
+ props: {
56
+ transformPasted(e, t) {
57
+ return c ? f(e, t.state) : e;
58
+ },
59
+ handlePaste(e, t) {
60
+ let n = d(t.clipboardData);
61
+ return n === null ? !1 : (p(e, n), !0);
62
+ },
63
+ handleDrop(e, t) {
64
+ let n = e.dragging ? null : d(t.dataTransfer), i = n === null ? null : e.posAtCoords({
65
+ left: t.clientX,
66
+ top: t.clientY
67
+ });
68
+ return n === null || !i ? !1 : (e.dispatch(e.state.tr.setSelection(r.near(e.state.doc.resolve(i.pos)))), p(e, n), e.focus(), !0);
69
+ }
70
+ }
71
+ })];
72
+ }
73
+ });
74
+ //#endregion
75
+ export { m as PlainTextPaste };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pie-lib/editable-html-tip-tap",
3
- "version": "3.0.0",
3
+ "version": "3.0.1-next.20261002220849",
4
4
  "description": "",
5
5
  "repository": {
6
6
  "type": "git",
@@ -13,10 +13,10 @@
13
13
  "@dnd-kit/utilities": "3.2.2",
14
14
  "@mui/icons-material": "^7.3.4",
15
15
  "@mui/material": "^7.3.4",
16
- "@pie-lib/drag": "5.0.0",
17
- "@pie-lib/math-input": "9.0.0",
18
- "@pie-lib/math-toolbar": "4.0.0",
19
- "@pie-lib/render-ui": "8.0.0",
16
+ "@pie-lib/drag": "5.0.1-next.20261002215153",
17
+ "@pie-lib/math-input": "9.0.1-next.20261002215153",
18
+ "@pie-lib/math-toolbar": "4.0.1-next.20261002215153",
19
+ "@pie-lib/render-ui": "8.0.1-next.20261002215153",
20
20
  "@tiptap/core": "3.31.3",
21
21
  "@tiptap/extension-character-count": "3.31.3",
22
22
  "@tiptap/extension-color": "3.31.3",
@@ -43,10 +43,10 @@
43
43
  "react-portal": "^4.2.0",
44
44
  "tippy.js": "latest",
45
45
  "to-style": "^1.3.3",
46
- "@pie-element/shared-lodash": "0.1.1",
46
+ "@pie-element/shared-lodash": "0.1.2-next.20261002215153",
47
47
  "clsx": "^2.1.1",
48
48
  "prosemirror-state": "^1.4.4",
49
- "@pie-element/shared-math-rendering-mathjax": "0.1.1",
49
+ "@pie-element/shared-math-rendering-mathjax": "0.1.2-next.20261002215153",
50
50
  "@tiptap/extensions": "3.31.3",
51
51
  "@tiptap/extension-list": "3.31.3",
52
52
  "@tiptap/extension-bubble-menu": "3.31.3",