@mhamz.01/easyflow-texteditor 0.1.157 → 0.1.159

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.d.mts CHANGED
@@ -18,7 +18,7 @@ interface EditorTab$1 {
18
18
  subtabs: EditorSubTab$1[];
19
19
  }
20
20
 
21
- type EditorChangeSource = "editor" | "tab-switch" | "subtab-switch" | "add-tab" | "add-subtab" | "delete-tab" | "delete-subtab" | "restore" | "storage" | "manual";
21
+ type EditorChangeSource = "editor" | "tab-switch" | "subtab-switch" | "add-tab" | "add-subtab" | "delete-tab" | "delete-subtab" | "restore" | "storage" | "manual" | "rename-tab" | "rename-subtab";
22
22
  interface EditorChangePayload {
23
23
  tabs: EditorTab$1[];
24
24
  activeTabId: string;
package/dist/index.d.ts CHANGED
@@ -18,7 +18,7 @@ interface EditorTab$1 {
18
18
  subtabs: EditorSubTab$1[];
19
19
  }
20
20
 
21
- type EditorChangeSource = "editor" | "tab-switch" | "subtab-switch" | "add-tab" | "add-subtab" | "delete-tab" | "delete-subtab" | "restore" | "storage" | "manual";
21
+ type EditorChangeSource = "editor" | "tab-switch" | "subtab-switch" | "add-tab" | "add-subtab" | "delete-tab" | "delete-subtab" | "restore" | "storage" | "manual" | "rename-tab" | "rename-subtab";
22
22
  interface EditorChangePayload {
23
23
  tabs: EditorTab$1[];
24
24
  activeTabId: string;
package/dist/index.js CHANGED
@@ -1235,9 +1235,13 @@ function EditorLayout({ children, onChange, initialTabs, onTabsChange }) {
1235
1235
  );
1236
1236
  const renameTab = (0, import_react9.useCallback)(
1237
1237
  (id, title) => {
1238
- setTabs((prev) => prev.map((t) => t.id === id ? { ...t, title } : t));
1238
+ setTabs((prev) => {
1239
+ const updated = prev.map((t) => t.id === id ? { ...t, title } : t);
1240
+ emitChangeDebounced({ tabs: updated, activeTabId, activeSubTabId, source: "rename-tab" });
1241
+ return updated;
1242
+ });
1239
1243
  },
1240
- []
1244
+ [emitChangeDebounced, activeTabId, activeSubTabId]
1241
1245
  );
1242
1246
  const deleteTab = (0, import_react9.useCallback)(
1243
1247
  (id) => {
@@ -1281,18 +1285,15 @@ function EditorLayout({ children, onChange, initialTabs, onTabsChange }) {
1281
1285
  );
1282
1286
  const renameSubTab = (0, import_react9.useCallback)(
1283
1287
  (tabId, subTabId, title) => {
1284
- setTabs(
1285
- (prev) => prev.map(
1286
- (tab) => tab.id === tabId ? {
1287
- ...tab,
1288
- subtabs: tab.subtabs.map(
1289
- (st) => st.id === subTabId ? { ...st, title } : st
1290
- )
1291
- } : tab
1292
- )
1293
- );
1288
+ setTabs((prev) => {
1289
+ const updated = prev.map(
1290
+ (tab) => tab.id === tabId ? { ...tab, subtabs: tab.subtabs.map((st) => st.id === subTabId ? { ...st, title } : st) } : tab
1291
+ );
1292
+ emitChangeDebounced({ tabs: updated, activeTabId, activeSubTabId, source: "rename-subtab" });
1293
+ return updated;
1294
+ });
1294
1295
  },
1295
- []
1296
+ [emitChangeDebounced, activeTabId, activeSubTabId]
1296
1297
  );
1297
1298
  const editorActions = (0, import_react9.useMemo)(
1298
1299
  () => ({
@@ -1865,7 +1866,7 @@ var FONT_SIZES = [
1865
1866
  "64px"
1866
1867
  ];
1867
1868
  var FontSizeExtension = import_core4.Extension.create({
1868
- name: "fontSize",
1869
+ name: "customFontSize",
1869
1870
  addOptions() {
1870
1871
  return {
1871
1872
  types: ["textStyle"]
@@ -1900,15 +1901,15 @@ var FontSizeExtension = import_core4.Extension.create({
1900
1901
  increaseFontSize: () => ({ editor }) => {
1901
1902
  const currentSize = editor.getAttributes("textStyle").fontSize;
1902
1903
  const currentIndex = FONT_SIZES.indexOf(currentSize || "16px");
1903
- const nextIndex = Math.min(currentIndex + 1, FONT_SIZES.length - 1);
1904
- const nextSize = FONT_SIZES[nextIndex];
1904
+ const fromIndex = currentIndex === -1 ? FONT_SIZES.indexOf("16px") : currentIndex;
1905
+ const nextSize = FONT_SIZES[Math.min(fromIndex + 1, FONT_SIZES.length - 1)];
1905
1906
  return editor.chain().focus().setFontSize(nextSize).run();
1906
1907
  },
1907
1908
  decreaseFontSize: () => ({ editor }) => {
1908
1909
  const currentSize = editor.getAttributes("textStyle").fontSize;
1909
1910
  const currentIndex = FONT_SIZES.indexOf(currentSize || "16px");
1910
- const nextIndex = Math.max(currentIndex - 1, 0);
1911
- const nextSize = FONT_SIZES[nextIndex];
1911
+ const fromIndex = currentIndex === -1 ? FONT_SIZES.indexOf("16px") : currentIndex;
1912
+ const nextSize = FONT_SIZES[Math.max(fromIndex - 1, 0)];
1912
1913
  return editor.chain().focus().setFontSize(nextSize).run();
1913
1914
  }
1914
1915
  };
@@ -7326,23 +7327,32 @@ function ColorPicker({ type = "text" }) {
7326
7327
  (value) => {
7327
7328
  if (!editor) return;
7328
7329
  const { state } = editor;
7329
- const { $from, $to, empty } = state.selection;
7330
+ const { $from } = state.selection;
7330
7331
  editor.chain().focus().setColor(value).run();
7331
- const depth = $from.depth;
7332
- const nodePos = $from.before(depth);
7333
- const node = $from.node(depth);
7334
- const supportsColor = [
7335
- "paragraph",
7336
- "heading",
7337
- "listItem",
7338
- "taskItem",
7339
- "blockquote"
7340
- ].includes(node.type.name);
7341
- if (supportsColor) {
7342
- const tr = state.tr.setNodeMarkup(nodePos, void 0, {
7343
- ...node.attrs,
7344
- color: value
7345
- });
7332
+ const tr = editor.state.tr;
7333
+ let trDirty = false;
7334
+ for (let depth = $from.depth; depth >= 1; depth--) {
7335
+ const node = $from.node(depth);
7336
+ const pos = $from.before(depth);
7337
+ const supportsColor = [
7338
+ "paragraph",
7339
+ "heading",
7340
+ "listItem",
7341
+ "taskItem",
7342
+ "blockquote"
7343
+ ].includes(node.type.name);
7344
+ if (supportsColor && node.attrs.color !== value) {
7345
+ tr.setNodeMarkup(pos, void 0, {
7346
+ ...node.attrs,
7347
+ color: value
7348
+ });
7349
+ trDirty = true;
7350
+ }
7351
+ if (node.type.name === "listItem" || node.type.name === "taskItem") {
7352
+ break;
7353
+ }
7354
+ }
7355
+ if (trDirty) {
7346
7356
  editor.view.dispatch(tr);
7347
7357
  }
7348
7358
  setTimeout(() => {
@@ -7423,7 +7433,7 @@ function ColorPicker({ type = "text" }) {
7423
7433
  {
7424
7434
  className: "flex flex-col gap-3",
7425
7435
  onMouseDown: (e) => e.stopPropagation(),
7426
- onMouseUp: ((e) => e.stopPropagation()),
7436
+ onMouseUp: (e) => e.stopPropagation(),
7427
7437
  onPointerDown: (e) => e.stopPropagation(),
7428
7438
  onPointerUp: (e) => e.stopPropagation(),
7429
7439
  onClick: (e) => e.stopPropagation(),
@@ -7853,6 +7863,7 @@ var ColorBlock = import_core5.Extension.create({
7853
7863
  }
7854
7864
  });
7855
7865
  var stylePersistenceKey = new import_state5.PluginKey("stylePersistence");
7866
+ var STYLED_NODES = ["paragraph", "heading", "listItem", "taskItem", "blockquote"];
7856
7867
  var StylePersistence = import_core5.Extension.create({
7857
7868
  name: "stylePersistence",
7858
7869
  addOptions() {
@@ -7880,8 +7891,7 @@ var StylePersistence = import_core5.Extension.create({
7880
7891
  );
7881
7892
  let isInCodeBlock = false;
7882
7893
  for (let depth = $from.depth; depth > 0; depth--) {
7883
- const node = $from.node(depth);
7884
- if (node.type.name === "codeBlock") {
7894
+ if ($from.node(depth).type.name === "codeBlock") {
7885
7895
  isInCodeBlock = true;
7886
7896
  break;
7887
7897
  }
@@ -7889,16 +7899,17 @@ var StylePersistence = import_core5.Extension.create({
7889
7899
  if (hasExcludedMarks || isInCodeBlock) {
7890
7900
  return value;
7891
7901
  }
7892
- const parentNode = $from.parent;
7893
- let font = parentNode.attrs.fontFamily;
7894
- let color = parentNode.attrs.color;
7895
- const textStyleMark = marks.find((m) => m.type.name === "textStyle");
7896
- if (!font && textStyleMark?.attrs.fontFamily) {
7897
- font = textStyleMark.attrs.fontFamily;
7898
- }
7899
- if (!color && textStyleMark?.attrs.color) {
7900
- color = textStyleMark.attrs.color;
7902
+ let font = null;
7903
+ let color = null;
7904
+ for (let depth = $from.depth; depth >= 1; depth--) {
7905
+ const node = $from.node(depth);
7906
+ if (!font && node.attrs?.fontFamily) font = node.attrs.fontFamily;
7907
+ if (!color && node.attrs?.color) color = node.attrs.color;
7908
+ if (font && color) break;
7901
7909
  }
7910
+ const textStyleMark = marks.find((m) => m.type.name === "textStyle");
7911
+ if (!font && textStyleMark?.attrs.fontFamily) font = textStyleMark.attrs.fontFamily;
7912
+ if (!color && textStyleMark?.attrs.color) color = textStyleMark.attrs.color;
7902
7913
  return {
7903
7914
  lastFont: font || value.lastFont,
7904
7915
  lastColor: color || value.lastColor
@@ -7914,15 +7925,13 @@ var StylePersistence = import_core5.Extension.create({
7914
7925
  return null;
7915
7926
  }
7916
7927
  const { $from } = newState.selection;
7917
- const parentNode = $from.parent;
7918
7928
  const marks = $from.marks();
7919
7929
  const hasExcludedMarks = marks.some(
7920
7930
  (mark) => excludedMarks.includes(mark.type.name)
7921
7931
  );
7922
7932
  let isInCodeBlock = false;
7923
7933
  for (let depth = $from.depth; depth > 0; depth--) {
7924
- const node = $from.node(depth);
7925
- if (node.type.name === "codeBlock") {
7934
+ if ($from.node(depth).type.name === "codeBlock") {
7926
7935
  isInCodeBlock = true;
7927
7936
  break;
7928
7937
  }
@@ -7930,32 +7939,30 @@ var StylePersistence = import_core5.Extension.create({
7930
7939
  if (hasExcludedMarks || isInCodeBlock) {
7931
7940
  return null;
7932
7941
  }
7933
- const supportsAttributes = [
7934
- "paragraph",
7935
- "heading",
7936
- "listItem",
7937
- "taskItem",
7938
- "blockquote"
7939
- ].includes(parentNode.type.name);
7940
- if (!supportsAttributes) {
7941
- return null;
7942
- }
7943
- const currentFont = parentNode.attrs.fontFamily;
7944
- const currentColor = parentNode.attrs.color;
7945
- const needsFont = !currentFont && pluginState.lastFont;
7946
- const needsColor = !currentColor && pluginState.lastColor;
7947
- if (!needsFont && !needsColor) {
7948
- return null;
7949
- }
7950
7942
  const tr = newState.tr;
7951
- try {
7952
- const depth = $from.depth;
7953
- const pos = $from.before(depth);
7943
+ let trDirty = false;
7944
+ for (let depth = $from.depth; depth >= 1; depth--) {
7954
7945
  const node = $from.node(depth);
7946
+ if (!STYLED_NODES.includes(node.type.name)) continue;
7947
+ const pos = $from.before(depth);
7948
+ const needsFont = !node.attrs.fontFamily && pluginState.lastFont;
7949
+ const needsColor = !node.attrs.color && pluginState.lastColor;
7950
+ if (!needsFont && !needsColor) {
7951
+ break;
7952
+ }
7955
7953
  const newAttrs = { ...node.attrs };
7956
7954
  if (needsFont) newAttrs.fontFamily = pluginState.lastFont;
7957
7955
  if (needsColor) newAttrs.color = pluginState.lastColor;
7958
7956
  tr.setNodeMarkup(pos, void 0, newAttrs);
7957
+ trDirty = true;
7958
+ if (node.type.name === "listItem" || node.type.name === "taskItem") {
7959
+ break;
7960
+ }
7961
+ }
7962
+ if (!trDirty) {
7963
+ return null;
7964
+ }
7965
+ try {
7959
7966
  const storedMarks = newState.storedMarks || $from.marks();
7960
7967
  const filteredMarks = storedMarks.filter(
7961
7968
  (mark) => mark.type.name !== "textStyle" && !excludedMarks.includes(mark.type.name)
@@ -7968,11 +7975,9 @@ var StylePersistence = import_core5.Extension.create({
7968
7975
  newState.schema.marks.textStyle.create(textStyleAttrs)
7969
7976
  ];
7970
7977
  tr.setStoredMarks(newMarks);
7971
- return tr;
7972
- } catch (error) {
7973
- console.error("StylePersistence error:", error);
7974
- return null;
7978
+ } catch (e) {
7975
7979
  }
7980
+ return tr;
7976
7981
  },
7977
7982
  props: {
7978
7983
  handleKeyDown(view, event) {
@@ -7980,33 +7985,28 @@ var StylePersistence = import_core5.Extension.create({
7980
7985
  const { state } = view;
7981
7986
  const { $from } = state.selection;
7982
7987
  const marks = $from.marks();
7983
- const hasExcludedMarks = marks.some(
7984
- (mark) => excludedMarks.includes(mark.type.name)
7985
- );
7986
- if (hasExcludedMarks) {
7988
+ if (marks.some((mark) => excludedMarks.includes(mark.type.name))) {
7987
7989
  return false;
7988
7990
  }
7989
7991
  let isInCodeBlock = false;
7990
7992
  for (let depth = $from.depth; depth > 0; depth--) {
7991
- const node = $from.node(depth);
7992
- if (node.type.name === "codeBlock") {
7993
+ if ($from.node(depth).type.name === "codeBlock") {
7993
7994
  isInCodeBlock = true;
7994
7995
  break;
7995
7996
  }
7996
7997
  }
7997
- if (isInCodeBlock) {
7998
- return false;
7998
+ if (isInCodeBlock) return false;
7999
+ let font = null;
8000
+ let color = null;
8001
+ for (let depth = $from.depth; depth >= 1; depth--) {
8002
+ const node = $from.node(depth);
8003
+ if (!font && node.attrs?.fontFamily) font = node.attrs.fontFamily;
8004
+ if (!color && node.attrs?.color) color = node.attrs.color;
8005
+ if (font && color) break;
7999
8006
  }
8000
- const parentNode = $from.parent;
8001
- let font = parentNode.attrs.fontFamily;
8002
- let color = parentNode.attrs.color;
8003
8007
  const textStyleMark = marks.find((m) => m.type.name === "textStyle");
8004
- if (!font && textStyleMark?.attrs.fontFamily) {
8005
- font = textStyleMark.attrs.fontFamily;
8006
- }
8007
- if (!color && textStyleMark?.attrs.color) {
8008
- color = textStyleMark.attrs.color;
8009
- }
8008
+ if (!font && textStyleMark?.attrs.fontFamily) font = textStyleMark.attrs.fontFamily;
8009
+ if (!color && textStyleMark?.attrs.color) color = textStyleMark.attrs.color;
8010
8010
  if (font || color) {
8011
8011
  const pluginState = stylePersistenceKey.getState(state);
8012
8012
  pluginState.lastFont = font || pluginState.lastFont;