@pixerate/editor 0.5.1 → 0.6.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.
package/dist/index.cjs CHANGED
@@ -39,6 +39,7 @@ __export(src_exports, {
39
39
  FormulaParser: () => FormulaParser,
40
40
  GradientText: () => GradientText,
41
41
  INSTRUCTION_REGEX: () => INSTRUCTION_REGEX,
42
+ Image: () => Image2,
42
43
  LoadingNode: () => LoadingNode,
43
44
  Markdown: () => Markdown2,
44
45
  Mention: () => Mention,
@@ -62,8 +63,11 @@ __export(src_exports, {
62
63
  getEditorMarkdown: () => getEditorMarkdown,
63
64
  getEditorText: () => getEditorText,
64
65
  getLatestVersion: () => getLatestVersion,
66
+ handleImageInsertion: () => handleImageInsertion,
65
67
  htmlToPlainText: () => htmlToPlainText,
68
+ imagePastePluginKey: () => imagePastePluginKey,
66
69
  indexToColName: () => indexToColName,
70
+ insertImageNode: () => insertImageNode,
67
71
  instructionRegex: () => instructionRegex,
68
72
  mapRawOffsetToResolved: () => mapRawOffsetToResolved,
69
73
  mapResolvedOffsetToRaw: () => mapResolvedOffsetToRaw,
@@ -72,12 +76,14 @@ __export(src_exports, {
72
76
  parseFormula: () => parseFormula,
73
77
  parseRange: () => parseRange,
74
78
  plainTextToTipTapHtml: () => plainTextToTipTapHtml,
79
+ removeImageNode: () => removeImageNode,
75
80
  resolveTemplates: () => resolveTemplates,
76
81
  resolveTemplatesWithMapping: () => resolveTemplatesWithMapping,
77
82
  resolveVariables: () => resolveVariables,
78
83
  templateRegex: () => templateRegex,
79
84
  tokenizeFormula: () => tokenizeFormula,
80
85
  tokenizePrompt: () => tokenizePrompt,
86
+ updateImageSrc: () => updateImageSrc,
81
87
  variableRegex: () => variableRegex
82
88
  });
83
89
  module.exports = __toCommonJS(src_exports);
@@ -1965,20 +1971,183 @@ var Markdown = import_core8.Extension.create({
1965
1971
  var resolveExt = (mod, name) => mod?.[name] || mod?.default?.[name] || mod?.default?.default || mod?.default || mod;
1966
1972
  var Markdown2 = resolveExt(Markdown, "Markdown");
1967
1973
 
1968
- // src/extensions/rich-text-preset.ts
1974
+ // src/extensions/image.ts
1975
+ var _Image = __toESM(require("@tiptap/extension-image"), 1);
1976
+ var import_state5 = require("@tiptap/pm/state");
1969
1977
  var resolveExt2 = (mod, name) => mod?.[name] || mod?.default?.[name] || mod?.default?.default || mod?.default || mod;
1970
- var StarterKit = resolveExt2(_StarterKit, "StarterKit");
1971
- var Color = resolveExt2(_Color, "Color");
1972
- var Highlight = resolveExt2(_Highlight, "Highlight");
1973
- var Link2 = resolveExt2(_Link, "Link");
1974
- var TaskList2 = resolveExt2(_TaskList, "TaskList");
1975
- var TaskItem2 = resolveExt2(_TaskItem, "TaskItem");
1976
- var TextAlign = resolveExt2(_TextAlign, "TextAlign");
1977
- var TextStyle = resolveExt2(_TextStyle, "TextStyle");
1978
- var Typography = resolveExt2(_Typography, "Typography");
1979
- var Underline = resolveExt2(_Underline, "Underline");
1980
- var Placeholder = resolveExt2(_Placeholder, "Placeholder");
1981
- var CharacterCount = resolveExt2(_CharacterCount, "CharacterCount");
1978
+ var BaseImage = resolveExt2(_Image, "Image");
1979
+ var imagePastePluginKey = new import_state5.PluginKey("imagePasteHandler");
1980
+ function insertImageNode(view, src, alt) {
1981
+ const { schema } = view.state;
1982
+ const imageType = schema.nodes.image;
1983
+ if (!imageType) return;
1984
+ const node = imageType.create({ src, alt: alt || "" });
1985
+ const tr = view.state.tr.replaceSelectionWith(node);
1986
+ view.dispatch(tr);
1987
+ }
1988
+ function updateImageSrc(view, oldSrc, newSrc) {
1989
+ const { doc } = view.state;
1990
+ let foundPos = null;
1991
+ let foundAttrs = null;
1992
+ doc.descendants((node, pos) => {
1993
+ if (node.type.name === "image" && node.attrs.src === oldSrc) {
1994
+ foundPos = pos;
1995
+ foundAttrs = node.attrs;
1996
+ return false;
1997
+ }
1998
+ });
1999
+ if (foundPos !== null && foundAttrs) {
2000
+ const tr = view.state.tr.setNodeMarkup(foundPos, void 0, {
2001
+ ...foundAttrs,
2002
+ src: newSrc
2003
+ });
2004
+ view.dispatch(tr);
2005
+ }
2006
+ }
2007
+ function removeImageNode(view, src) {
2008
+ const { doc } = view.state;
2009
+ let foundPos = null;
2010
+ let nodeSize = 0;
2011
+ doc.descendants((node, pos) => {
2012
+ if (node.type.name === "image" && node.attrs.src === src) {
2013
+ foundPos = pos;
2014
+ nodeSize = node.nodeSize;
2015
+ return false;
2016
+ }
2017
+ });
2018
+ if (foundPos !== null) {
2019
+ const tr = view.state.tr.delete(foundPos, foundPos + nodeSize);
2020
+ view.dispatch(tr);
2021
+ }
2022
+ }
2023
+ function handleImageInsertion(view, file, options) {
2024
+ if (typeof options.upload === "function") {
2025
+ const hasObjectUrl = typeof URL !== "undefined" && typeof URL.createObjectURL === "function";
2026
+ const tempUrl = hasObjectUrl ? URL.createObjectURL(file) : null;
2027
+ if (tempUrl) {
2028
+ insertImageNode(view, tempUrl, file.name);
2029
+ }
2030
+ Promise.resolve(options.upload(file)).then((uploadedUrl) => {
2031
+ if (!uploadedUrl) {
2032
+ throw new Error("Upload handler returned empty URL");
2033
+ }
2034
+ if (tempUrl) {
2035
+ updateImageSrc(view, tempUrl, uploadedUrl);
2036
+ if (typeof URL.revokeObjectURL === "function") {
2037
+ URL.revokeObjectURL(tempUrl);
2038
+ }
2039
+ } else {
2040
+ insertImageNode(view, uploadedUrl, file.name);
2041
+ }
2042
+ }).catch((err) => {
2043
+ const error = err instanceof Error ? err : new Error(String(err));
2044
+ console.error("Failed to upload pasted image:", error);
2045
+ if (tempUrl) {
2046
+ removeImageNode(view, tempUrl);
2047
+ if (typeof URL.revokeObjectURL === "function") {
2048
+ URL.revokeObjectURL(tempUrl);
2049
+ }
2050
+ }
2051
+ if (typeof options.onUploadError === "function") {
2052
+ options.onUploadError(error, file);
2053
+ }
2054
+ });
2055
+ } else if (options.allowBase64 !== false) {
2056
+ const maxBase64Size = options.maxBase64Size ?? 65536;
2057
+ if (file.size > maxBase64Size) {
2058
+ const err = new Error(
2059
+ `Image size (${Math.round(file.size / 1024)}KB) exceeds maxBase64Size (${Math.round(
2060
+ maxBase64Size / 1024
2061
+ )}KB). Provide an upload handler to support large images.`
2062
+ );
2063
+ console.warn(`[Editor] ${err.message}`);
2064
+ if (typeof options.onUploadError === "function") {
2065
+ options.onUploadError(err, file);
2066
+ }
2067
+ return;
2068
+ }
2069
+ if (typeof FileReader !== "undefined") {
2070
+ const reader = new FileReader();
2071
+ reader.onload = () => {
2072
+ const src = reader.result;
2073
+ if (src) {
2074
+ insertImageNode(view, src, file.name);
2075
+ }
2076
+ };
2077
+ reader.readAsDataURL(file);
2078
+ }
2079
+ }
2080
+ }
2081
+ var Image2 = BaseImage.extend({
2082
+ addOptions() {
2083
+ return {
2084
+ ...this.parent?.(),
2085
+ allowBase64: true,
2086
+ maxBase64Size: 65536,
2087
+ enablePaste: true,
2088
+ enableDrop: true,
2089
+ upload: void 0,
2090
+ onUploadError: void 0,
2091
+ HTMLAttributes: {
2092
+ class: "rounded-md max-w-full h-auto my-2"
2093
+ }
2094
+ };
2095
+ },
2096
+ addProseMirrorPlugins() {
2097
+ const parentPlugins = this.parent?.() || [];
2098
+ const options = this.options;
2099
+ if (!options.enablePaste && !options.enableDrop) {
2100
+ return parentPlugins;
2101
+ }
2102
+ const pastePlugin = new import_state5.Plugin({
2103
+ key: imagePastePluginKey,
2104
+ props: {
2105
+ handlePaste(view, event) {
2106
+ if (!options.enablePaste) return false;
2107
+ const items = Array.from(event.clipboardData?.items || []);
2108
+ const imageItems = items.filter(
2109
+ (item) => item.kind === "file" && item.type.startsWith("image/")
2110
+ );
2111
+ if (imageItems.length === 0) return false;
2112
+ event.preventDefault();
2113
+ for (const item of imageItems) {
2114
+ const file = item.getAsFile();
2115
+ if (!file) continue;
2116
+ handleImageInsertion(view, file, options);
2117
+ }
2118
+ return true;
2119
+ },
2120
+ handleDrop(view, event) {
2121
+ if (!options.enableDrop) return false;
2122
+ const files = Array.from(event.dataTransfer?.files || []);
2123
+ const imageFiles = files.filter((f) => f.type.startsWith("image/"));
2124
+ if (imageFiles.length === 0) return false;
2125
+ event.preventDefault();
2126
+ for (const file of imageFiles) {
2127
+ handleImageInsertion(view, file, options);
2128
+ }
2129
+ return true;
2130
+ }
2131
+ }
2132
+ });
2133
+ return [...parentPlugins, pastePlugin];
2134
+ }
2135
+ });
2136
+
2137
+ // src/extensions/rich-text-preset.ts
2138
+ var resolveExt3 = (mod, name) => mod?.[name] || mod?.default?.[name] || mod?.default?.default || mod?.default || mod;
2139
+ var StarterKit = resolveExt3(_StarterKit, "StarterKit");
2140
+ var Color = resolveExt3(_Color, "Color");
2141
+ var Highlight = resolveExt3(_Highlight, "Highlight");
2142
+ var Link2 = resolveExt3(_Link, "Link");
2143
+ var TaskList2 = resolveExt3(_TaskList, "TaskList");
2144
+ var TaskItem2 = resolveExt3(_TaskItem, "TaskItem");
2145
+ var TextAlign = resolveExt3(_TextAlign, "TextAlign");
2146
+ var TextStyle = resolveExt3(_TextStyle, "TextStyle");
2147
+ var Typography = resolveExt3(_Typography, "Typography");
2148
+ var Underline = resolveExt3(_Underline, "Underline");
2149
+ var Placeholder = resolveExt3(_Placeholder, "Placeholder");
2150
+ var CharacterCount = resolveExt3(_CharacterCount, "CharacterCount");
1982
2151
  function createRichTextPreset(options = {}) {
1983
2152
  const {
1984
2153
  placeholder = "Start typing...",
@@ -2100,6 +2269,18 @@ function createRichTextPreset(options = {}) {
2100
2269
  })
2101
2270
  );
2102
2271
  }
2272
+ if (options.image !== false) {
2273
+ const imageConfig = typeof options.image === "object" ? options.image : {};
2274
+ extensions2.push(
2275
+ Image2.configure({
2276
+ HTMLAttributes: {
2277
+ class: "rounded-md max-w-full h-auto my-2",
2278
+ ...imageConfig.HTMLAttributes || {}
2279
+ },
2280
+ ...imageConfig
2281
+ })
2282
+ );
2283
+ }
2103
2284
  return extensions2;
2104
2285
  }
2105
2286
 
@@ -3665,6 +3846,7 @@ var SpreadsheetController = class {
3665
3846
  FormulaParser,
3666
3847
  GradientText,
3667
3848
  INSTRUCTION_REGEX,
3849
+ Image,
3668
3850
  LoadingNode,
3669
3851
  Markdown,
3670
3852
  Mention,
@@ -3688,8 +3870,11 @@ var SpreadsheetController = class {
3688
3870
  getEditorMarkdown,
3689
3871
  getEditorText,
3690
3872
  getLatestVersion,
3873
+ handleImageInsertion,
3691
3874
  htmlToPlainText,
3875
+ imagePastePluginKey,
3692
3876
  indexToColName,
3877
+ insertImageNode,
3693
3878
  instructionRegex,
3694
3879
  mapRawOffsetToResolved,
3695
3880
  mapResolvedOffsetToRaw,
@@ -3698,12 +3883,14 @@ var SpreadsheetController = class {
3698
3883
  parseFormula,
3699
3884
  parseRange,
3700
3885
  plainTextToTipTapHtml,
3886
+ removeImageNode,
3701
3887
  resolveTemplates,
3702
3888
  resolveTemplatesWithMapping,
3703
3889
  resolveVariables,
3704
3890
  templateRegex,
3705
3891
  tokenizeFormula,
3706
3892
  tokenizePrompt,
3893
+ updateImageSrc,
3707
3894
  variableRegex
3708
3895
  });
3709
3896
  //# sourceMappingURL=index.cjs.map