@kopexa/editor-utils 17.1.8 → 17.2.0

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.
@@ -0,0 +1,30 @@
1
+ "use client";
2
+
3
+ // src/hooks/use-is-editor-empty.ts
4
+ import { useCurrentEditor, useEditorState } from "@tiptap/react";
5
+ import { useMemo } from "react";
6
+ function useIsEditorEmpty(providedEditor) {
7
+ const { editor: coreEditor } = useCurrentEditor();
8
+ const mainEditor = useMemo(
9
+ () => providedEditor || coreEditor,
10
+ [providedEditor, coreEditor]
11
+ );
12
+ const isEmpty = useEditorState({
13
+ editor: mainEditor,
14
+ selector(context) {
15
+ if (!context.editor) {
16
+ return true;
17
+ }
18
+ if (context.editor.isEmpty) {
19
+ return true;
20
+ }
21
+ const text = context.editor.state.doc.textContent;
22
+ return text.trim().length === 0;
23
+ }
24
+ });
25
+ return isEmpty != null ? isEmpty : true;
26
+ }
27
+
28
+ export {
29
+ useIsEditorEmpty
30
+ };
@@ -0,0 +1,15 @@
1
+ import { Editor } from '@tiptap/react';
2
+
3
+ /**
4
+ * Hook that reactively tracks whether the editor is effectively empty.
5
+ * This considers documents with only whitespace as empty.
6
+ *
7
+ * Unlike a static check, this hook re-renders when the content changes,
8
+ * making it suitable for conditional rendering based on empty state.
9
+ *
10
+ * @param providedEditor - Optional editor instance to use instead of the context editor
11
+ * @returns boolean indicating if the editor is effectively empty
12
+ */
13
+ declare function useIsEditorEmpty(providedEditor?: Editor | null): boolean;
14
+
15
+ export { useIsEditorEmpty };
@@ -0,0 +1,15 @@
1
+ import { Editor } from '@tiptap/react';
2
+
3
+ /**
4
+ * Hook that reactively tracks whether the editor is effectively empty.
5
+ * This considers documents with only whitespace as empty.
6
+ *
7
+ * Unlike a static check, this hook re-renders when the content changes,
8
+ * making it suitable for conditional rendering based on empty state.
9
+ *
10
+ * @param providedEditor - Optional editor instance to use instead of the context editor
11
+ * @returns boolean indicating if the editor is effectively empty
12
+ */
13
+ declare function useIsEditorEmpty(providedEditor?: Editor | null): boolean;
14
+
15
+ export { useIsEditorEmpty };
@@ -0,0 +1,54 @@
1
+ "use client";
2
+ "use strict";
3
+ "use client";
4
+ var __defProp = Object.defineProperty;
5
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
6
+ var __getOwnPropNames = Object.getOwnPropertyNames;
7
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __export = (target, all) => {
9
+ for (var name in all)
10
+ __defProp(target, name, { get: all[name], enumerable: true });
11
+ };
12
+ var __copyProps = (to, from, except, desc) => {
13
+ if (from && typeof from === "object" || typeof from === "function") {
14
+ for (let key of __getOwnPropNames(from))
15
+ if (!__hasOwnProp.call(to, key) && key !== except)
16
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
17
+ }
18
+ return to;
19
+ };
20
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
21
+
22
+ // src/hooks/use-is-editor-empty.ts
23
+ var use_is_editor_empty_exports = {};
24
+ __export(use_is_editor_empty_exports, {
25
+ useIsEditorEmpty: () => useIsEditorEmpty
26
+ });
27
+ module.exports = __toCommonJS(use_is_editor_empty_exports);
28
+ var import_react = require("@tiptap/react");
29
+ var import_react2 = require("react");
30
+ function useIsEditorEmpty(providedEditor) {
31
+ const { editor: coreEditor } = (0, import_react.useCurrentEditor)();
32
+ const mainEditor = (0, import_react2.useMemo)(
33
+ () => providedEditor || coreEditor,
34
+ [providedEditor, coreEditor]
35
+ );
36
+ const isEmpty = (0, import_react.useEditorState)({
37
+ editor: mainEditor,
38
+ selector(context) {
39
+ if (!context.editor) {
40
+ return true;
41
+ }
42
+ if (context.editor.isEmpty) {
43
+ return true;
44
+ }
45
+ const text = context.editor.state.doc.textContent;
46
+ return text.trim().length === 0;
47
+ }
48
+ });
49
+ return isEmpty != null ? isEmpty : true;
50
+ }
51
+ // Annotate the CommonJS export names for ESM import in node:
52
+ 0 && (module.exports = {
53
+ useIsEditorEmpty
54
+ });
@@ -0,0 +1,8 @@
1
+ "use client";
2
+ "use client";
3
+ import {
4
+ useIsEditorEmpty
5
+ } from "../chunk-TZDBVEXH.mjs";
6
+ export {
7
+ useIsEditorEmpty
8
+ };
package/dist/index.d.mts CHANGED
@@ -2,6 +2,7 @@ import * as _tiptap_core from '@tiptap/core';
2
2
  import { Node, Attrs } from '@tiptap/pm/model';
3
3
  import { Selection } from '@tiptap/pm/state';
4
4
  import { Editor } from '@tiptap/react';
5
+ export { useIsEditorEmpty } from './hooks/use-is-editor-empty.mjs';
5
6
  export { useTiptapEditor } from './hooks/use-tiptap-editor.mjs';
6
7
  export { getSelectedBlockNodes, getSelectedNodesOfType, selectionWithinConvertibleTypes } from './selection.mjs';
7
8
  export { updateNodesAttr } from './update-node-attrs.mjs';
@@ -47,6 +48,11 @@ declare function getActiveMarkAttrs(editor: Editor | null, markName: string): At
47
48
  * Checks if a node is empty
48
49
  */
49
50
  declare function isEmptyNode(node?: Node | null): boolean;
51
+ /**
52
+ * Checks if an editor is effectively empty (empty or contains only whitespace).
53
+ * This considers documents with only spaces, tabs, or newlines as empty.
54
+ */
55
+ declare function isEditorEffectivelyEmpty(editor: Editor | null): boolean;
50
56
  /**
51
57
  * Finds the position and instance of a node in the document
52
58
  * @param props Object containing editor, node (optional), and nodePos (optional)
@@ -102,4 +108,4 @@ declare function findSelectionPosition(params: {
102
108
  nodePos?: number | null;
103
109
  }): number | null;
104
110
 
105
- export { type OverflowPosition, findNodePosition, findParentNodeOfType, findSelectionPosition, getActiveMarkAttrs, getEditorExtension, getElementOverflowPosition, hasContentAbove, isEmptyNode, isExtensionAvailable, isMarkInSchema, isNodeInSchema, isNodeTypeSelected, isValidPosition };
111
+ export { type OverflowPosition, findNodePosition, findParentNodeOfType, findSelectionPosition, getActiveMarkAttrs, getEditorExtension, getElementOverflowPosition, hasContentAbove, isEditorEffectivelyEmpty, isEmptyNode, isExtensionAvailable, isMarkInSchema, isNodeInSchema, isNodeTypeSelected, isValidPosition };
package/dist/index.d.ts CHANGED
@@ -2,6 +2,7 @@ import * as _tiptap_core from '@tiptap/core';
2
2
  import { Node, Attrs } from '@tiptap/pm/model';
3
3
  import { Selection } from '@tiptap/pm/state';
4
4
  import { Editor } from '@tiptap/react';
5
+ export { useIsEditorEmpty } from './hooks/use-is-editor-empty.js';
5
6
  export { useTiptapEditor } from './hooks/use-tiptap-editor.js';
6
7
  export { getSelectedBlockNodes, getSelectedNodesOfType, selectionWithinConvertibleTypes } from './selection.js';
7
8
  export { updateNodesAttr } from './update-node-attrs.js';
@@ -47,6 +48,11 @@ declare function getActiveMarkAttrs(editor: Editor | null, markName: string): At
47
48
  * Checks if a node is empty
48
49
  */
49
50
  declare function isEmptyNode(node?: Node | null): boolean;
51
+ /**
52
+ * Checks if an editor is effectively empty (empty or contains only whitespace).
53
+ * This considers documents with only spaces, tabs, or newlines as empty.
54
+ */
55
+ declare function isEditorEffectivelyEmpty(editor: Editor | null): boolean;
50
56
  /**
51
57
  * Finds the position and instance of a node in the document
52
58
  * @param props Object containing editor, node (optional), and nodePos (optional)
@@ -102,4 +108,4 @@ declare function findSelectionPosition(params: {
102
108
  nodePos?: number | null;
103
109
  }): number | null;
104
110
 
105
- export { type OverflowPosition, findNodePosition, findParentNodeOfType, findSelectionPosition, getActiveMarkAttrs, getEditorExtension, getElementOverflowPosition, hasContentAbove, isEmptyNode, isExtensionAvailable, isMarkInSchema, isNodeInSchema, isNodeTypeSelected, isValidPosition };
111
+ export { type OverflowPosition, findNodePosition, findParentNodeOfType, findSelectionPosition, getActiveMarkAttrs, getEditorExtension, getElementOverflowPosition, hasContentAbove, isEditorEffectivelyEmpty, isEmptyNode, isExtensionAvailable, isMarkInSchema, isNodeInSchema, isNodeTypeSelected, isValidPosition };
package/dist/index.js CHANGED
@@ -30,6 +30,7 @@ __export(index_exports, {
30
30
  getSelectedBlockNodes: () => getSelectedBlockNodes,
31
31
  getSelectedNodesOfType: () => getSelectedNodesOfType,
32
32
  hasContentAbove: () => hasContentAbove,
33
+ isEditorEffectivelyEmpty: () => isEditorEffectivelyEmpty,
33
34
  isEmptyNode: () => isEmptyNode,
34
35
  isExtensionAvailable: () => isExtensionAvailable,
35
36
  isMarkInSchema: () => isMarkInSchema,
@@ -38,21 +39,47 @@ __export(index_exports, {
38
39
  isValidPosition: () => isValidPosition,
39
40
  selectionWithinConvertibleTypes: () => selectionWithinConvertibleTypes,
40
41
  updateNodesAttr: () => updateNodesAttr,
42
+ useIsEditorEmpty: () => useIsEditorEmpty,
41
43
  useTiptapEditor: () => useTiptapEditor
42
44
  });
43
45
  module.exports = __toCommonJS(index_exports);
44
46
  var import_state2 = require("@tiptap/pm/state");
45
47
 
46
- // src/hooks/use-tiptap-editor.ts
48
+ // src/hooks/use-is-editor-empty.ts
47
49
  var import_react = require("@tiptap/react");
48
50
  var import_react2 = require("react");
49
- function useTiptapEditor(providedEditor) {
51
+ function useIsEditorEmpty(providedEditor) {
50
52
  const { editor: coreEditor } = (0, import_react.useCurrentEditor)();
51
53
  const mainEditor = (0, import_react2.useMemo)(
52
54
  () => providedEditor || coreEditor,
53
55
  [providedEditor, coreEditor]
54
56
  );
55
- const editorState = (0, import_react.useEditorState)({
57
+ const isEmpty = (0, import_react.useEditorState)({
58
+ editor: mainEditor,
59
+ selector(context) {
60
+ if (!context.editor) {
61
+ return true;
62
+ }
63
+ if (context.editor.isEmpty) {
64
+ return true;
65
+ }
66
+ const text = context.editor.state.doc.textContent;
67
+ return text.trim().length === 0;
68
+ }
69
+ });
70
+ return isEmpty != null ? isEmpty : true;
71
+ }
72
+
73
+ // src/hooks/use-tiptap-editor.ts
74
+ var import_react3 = require("@tiptap/react");
75
+ var import_react4 = require("react");
76
+ function useTiptapEditor(providedEditor) {
77
+ const { editor: coreEditor } = (0, import_react3.useCurrentEditor)();
78
+ const mainEditor = (0, import_react4.useMemo)(
79
+ () => providedEditor || coreEditor,
80
+ [providedEditor, coreEditor]
81
+ );
82
+ const editorState = (0, import_react3.useEditorState)({
56
83
  editor: mainEditor,
57
84
  selector(context) {
58
85
  if (!context.editor) {
@@ -75,7 +102,7 @@ function useTiptapEditor(providedEditor) {
75
102
  // src/selection.ts
76
103
  var import_state = require("@tiptap/pm/state");
77
104
  var import_tables = require("@tiptap/pm/tables");
78
- var import_react3 = require("@tiptap/react");
105
+ var import_react5 = require("@tiptap/react");
79
106
  function getSelectedBlockNodes(editor) {
80
107
  const { doc } = editor.state;
81
108
  const { from, to } = editor.state.selection;
@@ -118,7 +145,7 @@ function getSelectedNodesOfType(selection, allowedNodeTypes) {
118
145
  return results;
119
146
  }
120
147
  }
121
- const parentNode = (0, import_react3.findParentNodeClosestToPos)(
148
+ const parentNode = (0, import_react5.findParentNodeClosestToPos)(
122
149
  $anchor,
123
150
  (node) => allowed.has(node.type.name)
124
151
  );
@@ -217,6 +244,12 @@ function getActiveMarkAttrs(editor, markName) {
217
244
  function isEmptyNode(node) {
218
245
  return !!node && node.content.size === 0;
219
246
  }
247
+ function isEditorEffectivelyEmpty(editor) {
248
+ if (!editor) return true;
249
+ if (editor.isEmpty) return true;
250
+ const text = editor.state.doc.textContent;
251
+ return text.trim().length === 0;
252
+ }
220
253
  function findNodePosition(props) {
221
254
  var _a;
222
255
  const { editor, node, nodePos } = props;
@@ -318,6 +351,7 @@ function findSelectionPosition(params) {
318
351
  getSelectedBlockNodes,
319
352
  getSelectedNodesOfType,
320
353
  hasContentAbove,
354
+ isEditorEffectivelyEmpty,
321
355
  isEmptyNode,
322
356
  isExtensionAvailable,
323
357
  isMarkInSchema,
@@ -326,5 +360,6 @@ function findSelectionPosition(params) {
326
360
  isValidPosition,
327
361
  selectionWithinConvertibleTypes,
328
362
  updateNodesAttr,
363
+ useIsEditorEmpty,
329
364
  useTiptapEditor
330
365
  });
package/dist/index.mjs CHANGED
@@ -7,6 +7,9 @@ import {
7
7
  import {
8
8
  updateNodesAttr
9
9
  } from "./chunk-23NZ6BRW.mjs";
10
+ import {
11
+ useIsEditorEmpty
12
+ } from "./chunk-TZDBVEXH.mjs";
10
13
  import {
11
14
  useTiptapEditor
12
15
  } from "./chunk-P55PLOHR.mjs";
@@ -56,6 +59,12 @@ function getActiveMarkAttrs(editor, markName) {
56
59
  function isEmptyNode(node) {
57
60
  return !!node && node.content.size === 0;
58
61
  }
62
+ function isEditorEffectivelyEmpty(editor) {
63
+ if (!editor) return true;
64
+ if (editor.isEmpty) return true;
65
+ const text = editor.state.doc.textContent;
66
+ return text.trim().length === 0;
67
+ }
59
68
  function findNodePosition(props) {
60
69
  var _a;
61
70
  const { editor, node, nodePos } = props;
@@ -156,6 +165,7 @@ export {
156
165
  getSelectedBlockNodes,
157
166
  getSelectedNodesOfType,
158
167
  hasContentAbove,
168
+ isEditorEffectivelyEmpty,
159
169
  isEmptyNode,
160
170
  isExtensionAvailable,
161
171
  isMarkInSchema,
@@ -164,5 +174,6 @@ export {
164
174
  isValidPosition,
165
175
  selectionWithinConvertibleTypes,
166
176
  updateNodesAttr,
177
+ useIsEditorEmpty,
167
178
  useTiptapEditor
168
179
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kopexa/editor-utils",
3
- "version": "17.1.8",
3
+ "version": "17.2.0",
4
4
  "description": "utility components for our editor",
5
5
  "keywords": [
6
6
  "editor-utils"
@@ -30,11 +30,11 @@
30
30
  "motion": ">=12.23.6",
31
31
  "react": ">=19.0.0-rc.0",
32
32
  "react-dom": ">=19.0.0-rc.0",
33
- "@kopexa/theme": "17.24.5"
33
+ "@kopexa/theme": "17.25.0"
34
34
  },
35
35
  "dependencies": {
36
- "@kopexa/react-utils": "17.0.57",
37
- "@kopexa/shared-utils": "17.0.57"
36
+ "@kopexa/react-utils": "17.1.1",
37
+ "@kopexa/shared-utils": "17.0.59"
38
38
  },
39
39
  "clean-package": "../../../clean-package.config.json",
40
40
  "module": "dist/index.mjs",