@kopexa/tiptap 17.8.6 → 17.9.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.d.mts CHANGED
@@ -1,5 +1,5 @@
1
1
  import * as _tiptap_core from '@tiptap/core';
2
- import { Node, JSONContent } from '@tiptap/core';
2
+ import { Node, JSONContent, Content as Content$1 } from '@tiptap/core';
3
3
  export { Content, JSONContent } from '@tiptap/core';
4
4
  import * as react_jsx_runtime from 'react/jsx-runtime';
5
5
  import { HocuspocusProvider } from '@hocuspocus/provider';
@@ -646,6 +646,121 @@ type BasicEditorProps = GetExtensionsOptions & EditorBasicVariants & {
646
646
  };
647
647
  declare const BasicEditor: ({ variant, bordered, content, variables, variableValues, showToolbar, pagesOptions, ...options }: BasicEditorProps) => react_jsx_runtime.JSX.Element;
648
648
 
649
+ type EditorViewProps = EditorBasicVariants & Pick<GetExtensionsOptions, "customExtensions" | "disabled"> & {
650
+ /**
651
+ * The TipTap content to render.
652
+ * Accepts JSON, HTML string, Markdown string, or plain text.
653
+ * Internally parsed via `safeParseContent` — same as the `Editor` component.
654
+ */
655
+ content?: Content$1 | undefined;
656
+ /** Additional CSS class names for the root container. */
657
+ className?: string;
658
+ };
659
+ /**
660
+ * Client-side read-only viewer for TipTap content.
661
+ *
662
+ * Uses a real TipTap editor instance in `editable: false` mode, so all
663
+ * NodeViews (images with file-reference resolution, callouts, code blocks,
664
+ * math, tables, etc.) render exactly as they do in the editor — but
665
+ * without the toolbar, bubble menus, slash commands, or collaboration.
666
+ *
667
+ * **Why not `generateHTML`?** Some node types use React NodeViews that
668
+ * resolve data at render time (e.g., images stored as file references that
669
+ * need a signed URL). `generateHTML` produces static HTML and cannot run
670
+ * these React components, resulting in broken images and missing features.
671
+ *
672
+ * **When to use:**
673
+ * - Detail pages, previews, or anywhere you need to display editor content
674
+ * with full NodeView fidelity (image resolution, interactive blocks).
675
+ * - Must be used inside `EditorFileProvider` if your content contains
676
+ * file-reference images.
677
+ *
678
+ * **For server-side rendering** (RSC, SSR, Node.js) where no React NodeViews
679
+ * are needed, use `EditorStaticView` instead. It uses `@tiptap/html` with
680
+ * a virtual DOM and produces pure HTML — but images must already be resolved.
681
+ *
682
+ * @example
683
+ * ```tsx
684
+ * import { EditorView } from "@kopexa/tiptap";
685
+ *
686
+ * function DocumentPreview({ content }: { content: JSONContent }) {
687
+ * return <EditorView content={content} variant="document" />;
688
+ * }
689
+ * ```
690
+ *
691
+ * @example With file resolution
692
+ * ```tsx
693
+ * import { EditorFileProvider, EditorView } from "@kopexa/tiptap";
694
+ *
695
+ * function DocumentDetail({ content }: { content: JSONContent }) {
696
+ * return (
697
+ * <EditorFileProvider onUpload={upload} onResolve={resolve}>
698
+ * <EditorView content={content} variant="document" />
699
+ * </EditorFileProvider>
700
+ * );
701
+ * }
702
+ * ```
703
+ */
704
+ declare function EditorView({ content, variant, bordered, className, customExtensions, disabled, }: EditorViewProps): react_jsx_runtime.JSX.Element | null;
705
+
706
+ type EditorStaticViewProps = EditorBasicVariants & Pick<GetExtensionsOptions, "customExtensions" | "disabled"> & {
707
+ /**
708
+ * The TipTap content to render.
709
+ * Accepts JSON, HTML string, Markdown string, or plain text.
710
+ * Internally parsed via `safeParseContent` — same as the `Editor` component.
711
+ */
712
+ content?: Content$1 | undefined;
713
+ /** Additional CSS class names for the root container. */
714
+ className?: string;
715
+ };
716
+ /**
717
+ * Static HTML viewer for TipTap content.
718
+ *
719
+ * Converts TipTap `JSONContent` to HTML using `generateHTML` from `@tiptap/html`
720
+ * (virtual DOM — no browser required) and renders it with the same styling as
721
+ * the `Editor` component. Works in **Server Components (RSC)**, SSR, and
722
+ * Node.js environments.
723
+ *
724
+ * Uses the full set of registered extensions to ensure all node/mark types
725
+ * produce correct HTML (tables, callouts, code blocks, math, etc.).
726
+ *
727
+ * **Limitations:**
728
+ * - React NodeViews are NOT rendered. Node types that rely on React components
729
+ * (e.g., images with file-reference resolution) will output their default
730
+ * HTML representation. Images stored as file references will NOT be resolved —
731
+ * ensure image `src` values are already displayable URLs before passing content.
732
+ * - No interactive features (no selection, no cursor, no scroll-to-hash).
733
+ *
734
+ * **When to use:**
735
+ * - Server-rendered pages, email templates, PDF generation, or static exports
736
+ * where you need a lightweight, non-interactive HTML representation.
737
+ * - When all image URLs in the content are already resolved (not file references).
738
+ *
739
+ * **For client-side rendering** with full NodeView fidelity (image resolution,
740
+ * interactive blocks), use `EditorView` instead.
741
+ *
742
+ * @example Server Component
743
+ * ```tsx
744
+ * // app/documents/[id]/page.tsx (RSC)
745
+ * import { EditorStaticView } from "@kopexa/tiptap";
746
+ *
747
+ * export default async function DocumentPage({ params }) {
748
+ * const doc = await fetchDocument(params.id);
749
+ * return <EditorStaticView content={doc.content} variant="document" />;
750
+ * }
751
+ * ```
752
+ *
753
+ * @example Client Component
754
+ * ```tsx
755
+ * import { EditorStaticView } from "@kopexa/tiptap";
756
+ *
757
+ * function LightweightPreview({ content }: { content: JSONContent }) {
758
+ * return <EditorStaticView content={content} variant="inline" />;
759
+ * }
760
+ * ```
761
+ */
762
+ declare function EditorStaticView({ content, variant, bordered, className, customExtensions, disabled, }: EditorStaticViewProps): react_jsx_runtime.JSX.Element | null;
763
+
649
764
  /**
650
765
  * Handles image upload with progress tracking and abort capability
651
766
  * @param file The file to upload
@@ -689,4 +804,4 @@ declare function sanitizeUrl(inputUrl: string, baseUrl: string, protocols?: Prot
689
804
  */
690
805
  declare function generateColorFromId(id: string): string;
691
806
 
692
- export { CalloutNode, type CalloutNodeAttrs, type CalloutVariant, type CollabUser, CollaborationProvider, type CollaborationProviderProps, type CollaborationState, type CollaborationStatus, BasicEditor as Editor, type EditorFileHandler, EditorFileProvider, type EditorFileProviderProps, type GetExtensionsOptions, ImageNode, ImageUploadNode, InlineMath, type InlineMathAttrs, MathBlock, type MathBlockAttrs, type ResolvedCollabUser, TocNode, type VariableDefinition, VariableFillerDialog, type VariableFillerDialogProps, VariableNode, type VariableNodeAttrs, type VariableOptions, VariableProvider, type VariableProviderProps, VariableSuggestion, type VariableSuggestionProps, convertFileToBase64, extractVariablesFromContent, generateColorFromId, getExtensions, handleImageUpload, isAllowedUri, sanitizeUrl, useCollaboration, useCollaborationRequired, useDocumentVisibility, useEditorFile, useEditorFileRequired, useIdle, useVariables, useVariablesWithFallback };
807
+ export { CalloutNode, type CalloutNodeAttrs, type CalloutVariant, type CollabUser, CollaborationProvider, type CollaborationProviderProps, type CollaborationState, type CollaborationStatus, BasicEditor as Editor, type EditorFileHandler, EditorFileProvider, type EditorFileProviderProps, EditorStaticView, type EditorStaticViewProps, EditorView, type EditorViewProps, type GetExtensionsOptions, ImageNode, ImageUploadNode, InlineMath, type InlineMathAttrs, MathBlock, type MathBlockAttrs, type ResolvedCollabUser, TocNode, type VariableDefinition, VariableFillerDialog, type VariableFillerDialogProps, VariableNode, type VariableNodeAttrs, type VariableOptions, VariableProvider, type VariableProviderProps, VariableSuggestion, type VariableSuggestionProps, convertFileToBase64, extractVariablesFromContent, generateColorFromId, getExtensions, handleImageUpload, isAllowedUri, sanitizeUrl, useCollaboration, useCollaborationRequired, useDocumentVisibility, useEditorFile, useEditorFileRequired, useIdle, useVariables, useVariablesWithFallback };
package/dist/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import * as _tiptap_core from '@tiptap/core';
2
- import { Node, JSONContent } from '@tiptap/core';
2
+ import { Node, JSONContent, Content as Content$1 } from '@tiptap/core';
3
3
  export { Content, JSONContent } from '@tiptap/core';
4
4
  import * as react_jsx_runtime from 'react/jsx-runtime';
5
5
  import { HocuspocusProvider } from '@hocuspocus/provider';
@@ -646,6 +646,121 @@ type BasicEditorProps = GetExtensionsOptions & EditorBasicVariants & {
646
646
  };
647
647
  declare const BasicEditor: ({ variant, bordered, content, variables, variableValues, showToolbar, pagesOptions, ...options }: BasicEditorProps) => react_jsx_runtime.JSX.Element;
648
648
 
649
+ type EditorViewProps = EditorBasicVariants & Pick<GetExtensionsOptions, "customExtensions" | "disabled"> & {
650
+ /**
651
+ * The TipTap content to render.
652
+ * Accepts JSON, HTML string, Markdown string, or plain text.
653
+ * Internally parsed via `safeParseContent` — same as the `Editor` component.
654
+ */
655
+ content?: Content$1 | undefined;
656
+ /** Additional CSS class names for the root container. */
657
+ className?: string;
658
+ };
659
+ /**
660
+ * Client-side read-only viewer for TipTap content.
661
+ *
662
+ * Uses a real TipTap editor instance in `editable: false` mode, so all
663
+ * NodeViews (images with file-reference resolution, callouts, code blocks,
664
+ * math, tables, etc.) render exactly as they do in the editor — but
665
+ * without the toolbar, bubble menus, slash commands, or collaboration.
666
+ *
667
+ * **Why not `generateHTML`?** Some node types use React NodeViews that
668
+ * resolve data at render time (e.g., images stored as file references that
669
+ * need a signed URL). `generateHTML` produces static HTML and cannot run
670
+ * these React components, resulting in broken images and missing features.
671
+ *
672
+ * **When to use:**
673
+ * - Detail pages, previews, or anywhere you need to display editor content
674
+ * with full NodeView fidelity (image resolution, interactive blocks).
675
+ * - Must be used inside `EditorFileProvider` if your content contains
676
+ * file-reference images.
677
+ *
678
+ * **For server-side rendering** (RSC, SSR, Node.js) where no React NodeViews
679
+ * are needed, use `EditorStaticView` instead. It uses `@tiptap/html` with
680
+ * a virtual DOM and produces pure HTML — but images must already be resolved.
681
+ *
682
+ * @example
683
+ * ```tsx
684
+ * import { EditorView } from "@kopexa/tiptap";
685
+ *
686
+ * function DocumentPreview({ content }: { content: JSONContent }) {
687
+ * return <EditorView content={content} variant="document" />;
688
+ * }
689
+ * ```
690
+ *
691
+ * @example With file resolution
692
+ * ```tsx
693
+ * import { EditorFileProvider, EditorView } from "@kopexa/tiptap";
694
+ *
695
+ * function DocumentDetail({ content }: { content: JSONContent }) {
696
+ * return (
697
+ * <EditorFileProvider onUpload={upload} onResolve={resolve}>
698
+ * <EditorView content={content} variant="document" />
699
+ * </EditorFileProvider>
700
+ * );
701
+ * }
702
+ * ```
703
+ */
704
+ declare function EditorView({ content, variant, bordered, className, customExtensions, disabled, }: EditorViewProps): react_jsx_runtime.JSX.Element | null;
705
+
706
+ type EditorStaticViewProps = EditorBasicVariants & Pick<GetExtensionsOptions, "customExtensions" | "disabled"> & {
707
+ /**
708
+ * The TipTap content to render.
709
+ * Accepts JSON, HTML string, Markdown string, or plain text.
710
+ * Internally parsed via `safeParseContent` — same as the `Editor` component.
711
+ */
712
+ content?: Content$1 | undefined;
713
+ /** Additional CSS class names for the root container. */
714
+ className?: string;
715
+ };
716
+ /**
717
+ * Static HTML viewer for TipTap content.
718
+ *
719
+ * Converts TipTap `JSONContent` to HTML using `generateHTML` from `@tiptap/html`
720
+ * (virtual DOM — no browser required) and renders it with the same styling as
721
+ * the `Editor` component. Works in **Server Components (RSC)**, SSR, and
722
+ * Node.js environments.
723
+ *
724
+ * Uses the full set of registered extensions to ensure all node/mark types
725
+ * produce correct HTML (tables, callouts, code blocks, math, etc.).
726
+ *
727
+ * **Limitations:**
728
+ * - React NodeViews are NOT rendered. Node types that rely on React components
729
+ * (e.g., images with file-reference resolution) will output their default
730
+ * HTML representation. Images stored as file references will NOT be resolved —
731
+ * ensure image `src` values are already displayable URLs before passing content.
732
+ * - No interactive features (no selection, no cursor, no scroll-to-hash).
733
+ *
734
+ * **When to use:**
735
+ * - Server-rendered pages, email templates, PDF generation, or static exports
736
+ * where you need a lightweight, non-interactive HTML representation.
737
+ * - When all image URLs in the content are already resolved (not file references).
738
+ *
739
+ * **For client-side rendering** with full NodeView fidelity (image resolution,
740
+ * interactive blocks), use `EditorView` instead.
741
+ *
742
+ * @example Server Component
743
+ * ```tsx
744
+ * // app/documents/[id]/page.tsx (RSC)
745
+ * import { EditorStaticView } from "@kopexa/tiptap";
746
+ *
747
+ * export default async function DocumentPage({ params }) {
748
+ * const doc = await fetchDocument(params.id);
749
+ * return <EditorStaticView content={doc.content} variant="document" />;
750
+ * }
751
+ * ```
752
+ *
753
+ * @example Client Component
754
+ * ```tsx
755
+ * import { EditorStaticView } from "@kopexa/tiptap";
756
+ *
757
+ * function LightweightPreview({ content }: { content: JSONContent }) {
758
+ * return <EditorStaticView content={content} variant="inline" />;
759
+ * }
760
+ * ```
761
+ */
762
+ declare function EditorStaticView({ content, variant, bordered, className, customExtensions, disabled, }: EditorStaticViewProps): react_jsx_runtime.JSX.Element | null;
763
+
649
764
  /**
650
765
  * Handles image upload with progress tracking and abort capability
651
766
  * @param file The file to upload
@@ -689,4 +804,4 @@ declare function sanitizeUrl(inputUrl: string, baseUrl: string, protocols?: Prot
689
804
  */
690
805
  declare function generateColorFromId(id: string): string;
691
806
 
692
- export { CalloutNode, type CalloutNodeAttrs, type CalloutVariant, type CollabUser, CollaborationProvider, type CollaborationProviderProps, type CollaborationState, type CollaborationStatus, BasicEditor as Editor, type EditorFileHandler, EditorFileProvider, type EditorFileProviderProps, type GetExtensionsOptions, ImageNode, ImageUploadNode, InlineMath, type InlineMathAttrs, MathBlock, type MathBlockAttrs, type ResolvedCollabUser, TocNode, type VariableDefinition, VariableFillerDialog, type VariableFillerDialogProps, VariableNode, type VariableNodeAttrs, type VariableOptions, VariableProvider, type VariableProviderProps, VariableSuggestion, type VariableSuggestionProps, convertFileToBase64, extractVariablesFromContent, generateColorFromId, getExtensions, handleImageUpload, isAllowedUri, sanitizeUrl, useCollaboration, useCollaborationRequired, useDocumentVisibility, useEditorFile, useEditorFileRequired, useIdle, useVariables, useVariablesWithFallback };
807
+ export { CalloutNode, type CalloutNodeAttrs, type CalloutVariant, type CollabUser, CollaborationProvider, type CollaborationProviderProps, type CollaborationState, type CollaborationStatus, BasicEditor as Editor, type EditorFileHandler, EditorFileProvider, type EditorFileProviderProps, EditorStaticView, type EditorStaticViewProps, EditorView, type EditorViewProps, type GetExtensionsOptions, ImageNode, ImageUploadNode, InlineMath, type InlineMathAttrs, MathBlock, type MathBlockAttrs, type ResolvedCollabUser, TocNode, type VariableDefinition, VariableFillerDialog, type VariableFillerDialogProps, VariableNode, type VariableNodeAttrs, type VariableOptions, VariableProvider, type VariableProviderProps, VariableSuggestion, type VariableSuggestionProps, convertFileToBase64, extractVariablesFromContent, generateColorFromId, getExtensions, handleImageUpload, isAllowedUri, sanitizeUrl, useCollaboration, useCollaborationRequired, useDocumentVisibility, useEditorFile, useEditorFileRequired, useIdle, useVariables, useVariablesWithFallback };
package/dist/index.js CHANGED
@@ -35,6 +35,8 @@ __export(index_exports, {
35
35
  CollaborationProvider: () => CollaborationProvider,
36
36
  Editor: () => BasicEditor,
37
37
  EditorFileProvider: () => EditorFileProvider,
38
+ EditorStaticView: () => EditorStaticView,
39
+ EditorView: () => EditorView,
38
40
  ImageNode: () => ImageNode,
39
41
  ImageUploadNode: () => ImageUploadNode,
40
42
  InlineMath: () => InlineMath,
@@ -4024,6 +4026,7 @@ var useCreateEditor = ({
4024
4026
  const fileHandlerFromContext = useEditorFile();
4025
4027
  const fileHandler = fileHandlerProp != null ? fileHandlerProp : fileHandlerFromContext;
4026
4028
  const collaboration = useCollaboration();
4029
+ const [collabSyncing, setCollabSyncing] = (0, import_react33.useState)(!!collaboration);
4027
4030
  const [extensions] = (0, import_react33.useState)(
4028
4031
  () => getExtensions({
4029
4032
  editable,
@@ -4070,10 +4073,14 @@ var useCreateEditor = ({
4070
4073
  if (ctx.editor.isEmpty && content) {
4071
4074
  ctx.editor.commands.setContent(safeParseContent(content));
4072
4075
  }
4076
+ setCollabSyncing(false);
4073
4077
  }, 0);
4074
4078
  });
4075
- } else if (ctx.editor.isEmpty && content) {
4076
- ctx.editor.commands.setContent(safeParseContent(content));
4079
+ } else {
4080
+ if (ctx.editor.isEmpty && content) {
4081
+ ctx.editor.commands.setContent(safeParseContent(content));
4082
+ }
4083
+ setCollabSyncing(false);
4077
4084
  }
4078
4085
  }
4079
4086
  userOnCreate == null ? void 0 : userOnCreate(ctx);
@@ -4085,7 +4092,7 @@ var useCreateEditor = ({
4085
4092
  editor.setEditable(editable);
4086
4093
  }
4087
4094
  }, [editor, editable]);
4088
- return editor;
4095
+ return { editor, collabSyncing };
4089
4096
  };
4090
4097
  function getExtensions({
4091
4098
  editable,
@@ -8213,7 +8220,7 @@ var BasicEditor = ({
8213
8220
  pagesOptions,
8214
8221
  ...options
8215
8222
  }) => {
8216
- const editor = useCreateEditor({
8223
+ const { editor, collabSyncing } = useCreateEditor({
8217
8224
  content,
8218
8225
  enableVariables: !!(variables == null ? void 0 : variables.length),
8219
8226
  pagesOptions,
@@ -8224,7 +8231,7 @@ var BasicEditor = ({
8224
8231
  (name) => variableValues == null ? void 0 : variableValues[name],
8225
8232
  [variableValues]
8226
8233
  );
8227
- if (!editor) {
8234
+ if (!editor || collabSyncing) {
8228
8235
  return /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(LoadingSpinner, {});
8229
8236
  }
8230
8237
  const isBottomToolbar = variant === "field";
@@ -8361,12 +8368,93 @@ function LoadingSpinner({ text = "Connecting..." }) {
8361
8368
  /* @__PURE__ */ (0, import_jsx_runtime34.jsx)("div", { className: styles.text(), children: text })
8362
8369
  ] }) });
8363
8370
  }
8371
+
8372
+ // src/presets/view/index.tsx
8373
+ var import_theme10 = require("@kopexa/theme");
8374
+ var import_react62 = require("@tiptap/react");
8375
+ var import_jsx_runtime35 = require("react/jsx-runtime");
8376
+ function EditorView({
8377
+ content,
8378
+ variant,
8379
+ bordered,
8380
+ className,
8381
+ customExtensions,
8382
+ disabled
8383
+ }) {
8384
+ const { editor } = useCreateEditor({
8385
+ content,
8386
+ editable: false,
8387
+ customExtensions,
8388
+ disabled
8389
+ });
8390
+ const styles = (0, import_theme10.editorBasic)({ variant, bordered });
8391
+ if (!editor) {
8392
+ return null;
8393
+ }
8394
+ return /* @__PURE__ */ (0, import_jsx_runtime35.jsx)("div", { className: styles.root({ className }), "data-slot": "editor-view", children: /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(import_react62.EditorContext.Provider, { value: { editor }, children: /* @__PURE__ */ (0, import_jsx_runtime35.jsx)("div", { className: styles.wrapper(), children: /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(
8395
+ import_react62.EditorContent,
8396
+ {
8397
+ editor,
8398
+ role: "presentation",
8399
+ className: styles.content()
8400
+ }
8401
+ ) }) }) });
8402
+ }
8403
+
8404
+ // src/presets/view/static.tsx
8405
+ var import_theme11 = require("@kopexa/theme");
8406
+ var import_html = require("@tiptap/html");
8407
+ var import_react63 = require("react");
8408
+ var import_jsx_runtime36 = require("react/jsx-runtime");
8409
+ function EditorStaticView({
8410
+ content,
8411
+ variant,
8412
+ bordered,
8413
+ className,
8414
+ customExtensions,
8415
+ disabled
8416
+ }) {
8417
+ const extensions = (0, import_react63.useMemo)(
8418
+ () => getExtensions({
8419
+ editable: false,
8420
+ customExtensions,
8421
+ disabled
8422
+ }),
8423
+ [customExtensions, disabled]
8424
+ );
8425
+ const html = (0, import_react63.useMemo)(() => {
8426
+ const parsed = safeParseContent(content);
8427
+ if (!parsed) return "";
8428
+ const json = parsed;
8429
+ if (json.content && Array.isArray(json.content) && json.content.length === 0) {
8430
+ return "";
8431
+ }
8432
+ try {
8433
+ return (0, import_html.generateHTML)(json, extensions);
8434
+ } catch {
8435
+ return "";
8436
+ }
8437
+ }, [content, extensions]);
8438
+ const styles = (0, import_theme11.editorBasic)({ variant, bordered });
8439
+ if (!html) {
8440
+ return null;
8441
+ }
8442
+ return /* @__PURE__ */ (0, import_jsx_runtime36.jsx)("div", { className: styles.root({ className }), "data-slot": "editor-static-view", children: /* @__PURE__ */ (0, import_jsx_runtime36.jsx)("div", { className: styles.wrapper(), children: /* @__PURE__ */ (0, import_jsx_runtime36.jsx)("div", { className: styles.content(), children: /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
8443
+ "div",
8444
+ {
8445
+ className: "tiptap ProseMirror",
8446
+ dangerouslySetInnerHTML: { __html: html }
8447
+ }
8448
+ ) }) }) });
8449
+ }
8364
8450
  // Annotate the CommonJS export names for ESM import in node:
8365
8451
  0 && (module.exports = {
8366
8452
  CalloutNode,
8367
8453
  CollaborationProvider,
8368
8454
  Editor,
8369
8455
  EditorFileProvider,
8456
+ EditorStaticView,
8457
+ EditorView,
8370
8458
  ImageNode,
8371
8459
  ImageUploadNode,
8372
8460
  InlineMath,
package/dist/index.mjs CHANGED
@@ -4022,6 +4022,7 @@ var useCreateEditor = ({
4022
4022
  const fileHandlerFromContext = useEditorFile();
4023
4023
  const fileHandler = fileHandlerProp != null ? fileHandlerProp : fileHandlerFromContext;
4024
4024
  const collaboration = useCollaboration();
4025
+ const [collabSyncing, setCollabSyncing] = useState13(!!collaboration);
4025
4026
  const [extensions] = useState13(
4026
4027
  () => getExtensions({
4027
4028
  editable,
@@ -4068,10 +4069,14 @@ var useCreateEditor = ({
4068
4069
  if (ctx.editor.isEmpty && content) {
4069
4070
  ctx.editor.commands.setContent(safeParseContent(content));
4070
4071
  }
4072
+ setCollabSyncing(false);
4071
4073
  }, 0);
4072
4074
  });
4073
- } else if (ctx.editor.isEmpty && content) {
4074
- ctx.editor.commands.setContent(safeParseContent(content));
4075
+ } else {
4076
+ if (ctx.editor.isEmpty && content) {
4077
+ ctx.editor.commands.setContent(safeParseContent(content));
4078
+ }
4079
+ setCollabSyncing(false);
4075
4080
  }
4076
4081
  }
4077
4082
  userOnCreate == null ? void 0 : userOnCreate(ctx);
@@ -4083,7 +4088,7 @@ var useCreateEditor = ({
4083
4088
  editor.setEditable(editable);
4084
4089
  }
4085
4090
  }, [editor, editable]);
4086
- return editor;
4091
+ return { editor, collabSyncing };
4087
4092
  };
4088
4093
  function getExtensions({
4089
4094
  editable,
@@ -8310,7 +8315,7 @@ var BasicEditor = ({
8310
8315
  pagesOptions,
8311
8316
  ...options
8312
8317
  }) => {
8313
- const editor = useCreateEditor({
8318
+ const { editor, collabSyncing } = useCreateEditor({
8314
8319
  content,
8315
8320
  enableVariables: !!(variables == null ? void 0 : variables.length),
8316
8321
  pagesOptions,
@@ -8321,7 +8326,7 @@ var BasicEditor = ({
8321
8326
  (name) => variableValues == null ? void 0 : variableValues[name],
8322
8327
  [variableValues]
8323
8328
  );
8324
- if (!editor) {
8329
+ if (!editor || collabSyncing) {
8325
8330
  return /* @__PURE__ */ jsx34(LoadingSpinner, {});
8326
8331
  }
8327
8332
  const isBottomToolbar = variant === "field";
@@ -8458,11 +8463,92 @@ function LoadingSpinner({ text = "Connecting..." }) {
8458
8463
  /* @__PURE__ */ jsx34("div", { className: styles.text(), children: text })
8459
8464
  ] }) });
8460
8465
  }
8466
+
8467
+ // src/presets/view/index.tsx
8468
+ import { editorBasic as editorBasic2 } from "@kopexa/theme";
8469
+ import { EditorContent as EditorContent2, EditorContext as EditorContext2 } from "@tiptap/react";
8470
+ import { jsx as jsx35 } from "react/jsx-runtime";
8471
+ function EditorView({
8472
+ content,
8473
+ variant,
8474
+ bordered,
8475
+ className,
8476
+ customExtensions,
8477
+ disabled
8478
+ }) {
8479
+ const { editor } = useCreateEditor({
8480
+ content,
8481
+ editable: false,
8482
+ customExtensions,
8483
+ disabled
8484
+ });
8485
+ const styles = editorBasic2({ variant, bordered });
8486
+ if (!editor) {
8487
+ return null;
8488
+ }
8489
+ return /* @__PURE__ */ jsx35("div", { className: styles.root({ className }), "data-slot": "editor-view", children: /* @__PURE__ */ jsx35(EditorContext2.Provider, { value: { editor }, children: /* @__PURE__ */ jsx35("div", { className: styles.wrapper(), children: /* @__PURE__ */ jsx35(
8490
+ EditorContent2,
8491
+ {
8492
+ editor,
8493
+ role: "presentation",
8494
+ className: styles.content()
8495
+ }
8496
+ ) }) }) });
8497
+ }
8498
+
8499
+ // src/presets/view/static.tsx
8500
+ import { editorBasic as editorBasic3 } from "@kopexa/theme";
8501
+ import { generateHTML } from "@tiptap/html";
8502
+ import { useMemo as useMemo20 } from "react";
8503
+ import { jsx as jsx36 } from "react/jsx-runtime";
8504
+ function EditorStaticView({
8505
+ content,
8506
+ variant,
8507
+ bordered,
8508
+ className,
8509
+ customExtensions,
8510
+ disabled
8511
+ }) {
8512
+ const extensions = useMemo20(
8513
+ () => getExtensions({
8514
+ editable: false,
8515
+ customExtensions,
8516
+ disabled
8517
+ }),
8518
+ [customExtensions, disabled]
8519
+ );
8520
+ const html = useMemo20(() => {
8521
+ const parsed = safeParseContent(content);
8522
+ if (!parsed) return "";
8523
+ const json = parsed;
8524
+ if (json.content && Array.isArray(json.content) && json.content.length === 0) {
8525
+ return "";
8526
+ }
8527
+ try {
8528
+ return generateHTML(json, extensions);
8529
+ } catch {
8530
+ return "";
8531
+ }
8532
+ }, [content, extensions]);
8533
+ const styles = editorBasic3({ variant, bordered });
8534
+ if (!html) {
8535
+ return null;
8536
+ }
8537
+ return /* @__PURE__ */ jsx36("div", { className: styles.root({ className }), "data-slot": "editor-static-view", children: /* @__PURE__ */ jsx36("div", { className: styles.wrapper(), children: /* @__PURE__ */ jsx36("div", { className: styles.content(), children: /* @__PURE__ */ jsx36(
8538
+ "div",
8539
+ {
8540
+ className: "tiptap ProseMirror",
8541
+ dangerouslySetInnerHTML: { __html: html }
8542
+ }
8543
+ ) }) }) });
8544
+ }
8461
8545
  export {
8462
8546
  CalloutNode,
8463
8547
  CollaborationProvider,
8464
8548
  BasicEditor as Editor,
8465
8549
  EditorFileProvider,
8550
+ EditorStaticView,
8551
+ EditorView,
8466
8552
  ImageNode,
8467
8553
  ImageUploadNode,
8468
8554
  InlineMath,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kopexa/tiptap",
3
- "version": "17.8.6",
3
+ "version": "17.9.1",
4
4
  "description": "our tiptap components",
5
5
  "keywords": [
6
6
  "tiptap"
@@ -28,7 +28,7 @@
28
28
  "motion": ">=12.23.6",
29
29
  "react": ">=19.0.0-rc.0",
30
30
  "react-dom": ">=19.0.0-rc.0",
31
- "@kopexa/theme": "17.24.3"
31
+ "@kopexa/theme": "17.24.5"
32
32
  },
33
33
  "dependencies": {
34
34
  "@floating-ui/dom": "^1.7.4",
@@ -54,6 +54,7 @@
54
54
  "@tiptap/extension-typography": "^3.20.0",
55
55
  "@tiptap/extension-unique-id": "^3.20.0",
56
56
  "@tiptap/extensions": "^3.20.0",
57
+ "@tiptap/html": "^3.20.0",
57
58
  "@tiptap/pm": "^3.20.0",
58
59
  "@tiptap/react": "^3.20.0",
59
60
  "@tiptap/starter-kit": "^3.20.0",
@@ -66,29 +67,29 @@
66
67
  "react-intl": "^7.1.14",
67
68
  "y-indexeddb": "^9.0.12",
68
69
  "yjs": "^13.6.0",
69
- "@kopexa/button": "17.0.55",
70
- "@kopexa/chip": "17.1.52",
71
- "@kopexa/callout": "17.0.55",
72
- "@kopexa/dialog": "17.2.20",
73
- "@kopexa/dropdown-menu": "17.0.55",
74
- "@kopexa/extension-code": "17.0.55",
70
+ "@kopexa/button": "17.0.57",
71
+ "@kopexa/callout": "17.0.57",
72
+ "@kopexa/chip": "17.1.54",
73
+ "@kopexa/dialog": "17.2.22",
75
74
  "@kopexa/extension-pages": "17.0.45",
76
- "@kopexa/extension-controlref": "17.1.37",
77
- "@kopexa/extension-table": "17.1.7",
78
- "@kopexa/icons": "17.7.20",
79
- "@kopexa/popover": "17.2.20",
80
- "@kopexa/editor-utils": "17.1.6",
81
- "@kopexa/input": "17.0.55",
82
- "@kopexa/label": "17.0.55",
83
- "@kopexa/select": "17.2.20",
84
- "@kopexa/switch": "17.2.20",
85
- "@kopexa/react-utils": "17.0.55",
86
- "@kopexa/shared-utils": "17.0.55",
87
- "@kopexa/separator": "17.0.55",
88
- "@kopexa/tabs": "17.0.55",
89
- "@kopexa/use-is-mobile": "17.0.55",
90
- "@kopexa/use-composed-ref": "17.0.55",
91
- "@kopexa/toolbar": "17.2.20"
75
+ "@kopexa/editor-utils": "17.1.8",
76
+ "@kopexa/dropdown-menu": "17.0.57",
77
+ "@kopexa/extension-code": "17.0.57",
78
+ "@kopexa/extension-controlref": "17.1.39",
79
+ "@kopexa/extension-table": "17.1.9",
80
+ "@kopexa/input": "17.0.57",
81
+ "@kopexa/label": "17.0.57",
82
+ "@kopexa/icons": "17.7.22",
83
+ "@kopexa/popover": "17.2.22",
84
+ "@kopexa/select": "17.2.22",
85
+ "@kopexa/separator": "17.0.57",
86
+ "@kopexa/shared-utils": "17.0.57",
87
+ "@kopexa/switch": "17.2.22",
88
+ "@kopexa/use-is-mobile": "17.0.57",
89
+ "@kopexa/use-composed-ref": "17.0.57",
90
+ "@kopexa/toolbar": "17.2.22",
91
+ "@kopexa/react-utils": "17.0.57",
92
+ "@kopexa/tabs": "17.0.57"
92
93
  },
93
94
  "clean-package": "../../../clean-package.config.json",
94
95
  "module": "dist/index.mjs",