@veltdev/plate-comments-react 1.0.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.
Files changed (49) hide show
  1. package/README.md +59 -0
  2. package/cjs/index.js +2 -0
  3. package/cjs/index.js.map +1 -0
  4. package/cjs/types/adapters/host/doc.d.ts +69 -0
  5. package/cjs/types/adapters/host/marks.d.ts +51 -0
  6. package/cjs/types/adapters/host/storage.d.ts +36 -0
  7. package/cjs/types/adapters/velt.d.ts +50 -0
  8. package/cjs/types/constants/common.d.ts +62 -0
  9. package/cjs/types/core/ExtensionComponent.d.ts +13 -0
  10. package/cjs/types/core/extension.d.ts +50 -0
  11. package/cjs/types/core/registry.d.ts +52 -0
  12. package/cjs/types/core/state.d.ts +80 -0
  13. package/cjs/types/features/addComment.d.ts +63 -0
  14. package/cjs/types/features/commentRenderer.d.ts +46 -0
  15. package/cjs/types/features/renderComments.d.ts +73 -0
  16. package/cjs/types/features/updateContent.d.ts +20 -0
  17. package/cjs/types/index.d.ts +16 -0
  18. package/cjs/types/types/common.d.ts +54 -0
  19. package/cjs/types/types/host.d.ts +74 -0
  20. package/cjs/types/types/state.d.ts +28 -0
  21. package/cjs/types/types/velt.d.ts +23 -0
  22. package/cjs/types/utils/common.d.ts +80 -0
  23. package/cjs/types/utils/console.d.ts +10 -0
  24. package/cjs/types/utils/serializer.d.ts +20 -0
  25. package/esm/index.js +2 -0
  26. package/esm/index.js.map +1 -0
  27. package/esm/types/adapters/host/doc.d.ts +69 -0
  28. package/esm/types/adapters/host/marks.d.ts +51 -0
  29. package/esm/types/adapters/host/storage.d.ts +36 -0
  30. package/esm/types/adapters/velt.d.ts +50 -0
  31. package/esm/types/constants/common.d.ts +62 -0
  32. package/esm/types/core/ExtensionComponent.d.ts +13 -0
  33. package/esm/types/core/extension.d.ts +50 -0
  34. package/esm/types/core/registry.d.ts +52 -0
  35. package/esm/types/core/state.d.ts +80 -0
  36. package/esm/types/features/addComment.d.ts +63 -0
  37. package/esm/types/features/commentRenderer.d.ts +46 -0
  38. package/esm/types/features/renderComments.d.ts +73 -0
  39. package/esm/types/features/updateContent.d.ts +20 -0
  40. package/esm/types/index.d.ts +16 -0
  41. package/esm/types/types/common.d.ts +54 -0
  42. package/esm/types/types/host.d.ts +74 -0
  43. package/esm/types/types/state.d.ts +28 -0
  44. package/esm/types/types/velt.d.ts +23 -0
  45. package/esm/types/utils/common.d.ts +80 -0
  46. package/esm/types/utils/console.d.ts +10 -0
  47. package/esm/types/utils/serializer.d.ts +20 -0
  48. package/index.d.ts +291 -0
  49. package/package.json +28 -0
@@ -0,0 +1,74 @@
1
+ /**
2
+ * Editor-specific type definitions for Plate.js.
3
+ * This is the ONLY place where editor-specific types may be defined.
4
+ */
5
+ import type { Descendant } from 'slate';
6
+ import type { PlateEditor } from '@platejs/core/react';
7
+ import type { AnnotationData } from '@/types/state';
8
+ /**
9
+ * Extended PlateEditor interface with Velt comments functionality.
10
+ */
11
+ export interface VeltCommentsEditor extends PlateEditor {
12
+ }
13
+ /**
14
+ * Velt comment element type for the editor.
15
+ * This represents a comment annotation node/element in the editor's document model.
16
+ */
17
+ export type VeltCommentsElement = {
18
+ type: 'veltComment';
19
+ children: Descendant[];
20
+ annotationId?: string;
21
+ multiThreadAnnotationId?: string;
22
+ };
23
+ /**
24
+ * Selection context extracted from editor.
25
+ */
26
+ export interface SelectionContext {
27
+ text: string;
28
+ from: number;
29
+ to: number;
30
+ occurrence: number;
31
+ targetTextNodeId?: string;
32
+ locationId?: string;
33
+ }
34
+ /**
35
+ * Occurrence match result.
36
+ */
37
+ export interface OccurrenceMatch {
38
+ index: number;
39
+ start: number;
40
+ end: number;
41
+ text: string;
42
+ }
43
+ /**
44
+ * Represents a detected change to an annotation during document editing.
45
+ */
46
+ export interface AnnotationChange {
47
+ annotationId: string;
48
+ multiThreadAnnotationId?: string;
49
+ originalText: string;
50
+ currentText: string;
51
+ originalOccurrence: number;
52
+ currentOccurrence: number;
53
+ originalTargetTextNodeId: string;
54
+ newTargetTextNodeId: string;
55
+ annotation: AnnotationData;
56
+ contentChanged: boolean;
57
+ occurrenceChanged: boolean;
58
+ targetTextNodeIdChanged: boolean;
59
+ }
60
+ /**
61
+ * Document change event data.
62
+ */
63
+ export interface DocumentChangeEvent {
64
+ editorId: string;
65
+ changes: Map<string, AnnotationChange>;
66
+ }
67
+ /**
68
+ * Plugin configuration options for VeltCommentsPlugin.
69
+ */
70
+ export interface VeltCommentsPluginConfig {
71
+ editorId?: string;
72
+ persistVeltMarks?: boolean;
73
+ HistoryEditor?: unknown;
74
+ }
@@ -0,0 +1,28 @@
1
+ /**
2
+ * State management type definitions.
3
+ * These types represent the internal state structure for managing annotations.
4
+ */
5
+ import type { CommentAnnotationContext } from '@/types/common';
6
+ import type { CommentAnnotation } from '@/types/velt';
7
+ /**
8
+ * Represents a single annotation with its associated data and position.
9
+ */
10
+ export interface AnnotationData {
11
+ annotationId: string;
12
+ multiThreadAnnotationId?: string;
13
+ context: CommentAnnotationContext;
14
+ position?: {
15
+ from: number;
16
+ to: number;
17
+ };
18
+ }
19
+ /**
20
+ * Annotation state per editor instance.
21
+ * Stores both simplified AnnotationData[] for core logic and full CommentAnnotation[] for rendering.
22
+ */
23
+ export interface AnnotationState {
24
+ editorId: string;
25
+ annotations: Map<string, AnnotationData>;
26
+ commentAnnotations: CommentAnnotation[];
27
+ selectedAnnotations: Set<string>;
28
+ }
@@ -0,0 +1,23 @@
1
+ /**
2
+ * Velt SDK type definitions.
3
+ * This is the ONLY place where @veltdev/types may be imported.
4
+ */
5
+ import type { CommentAnnotation, Location, Velt } from '@veltdev/types';
6
+ export type { CommentAnnotation, Location, Velt };
7
+ /**
8
+ * Comment element from Velt SDK.
9
+ */
10
+ export type CommentElement = {
11
+ addManualComment: (params: {
12
+ context: unknown;
13
+ location?: Location;
14
+ }) => Promise<CommentAnnotation | null>;
15
+ updateContext: (annotationId: string, context: unknown) => void;
16
+ getSelectedComments?: () => {
17
+ subscribe: (callback: (comments: CommentAnnotation[]) => void) => () => void;
18
+ };
19
+ };
20
+ /**
21
+ * Unsubscribe function for Velt SDK subscriptions.
22
+ */
23
+ export type UnsubscribeFn = () => void;
@@ -0,0 +1,80 @@
1
+ /**
2
+ * Pure utility functions with zero side effects.
3
+ * These functions contain algorithmic logic extracted from legacy code.
4
+ *
5
+ * IMPORTANT: This module MUST NOT import any external SDKs or have side effects.
6
+ * All functions must be pure: input → output, deterministic, no mutations.
7
+ */
8
+ /**
9
+ * Computes the KMP (Knuth-Morris-Pratt) failure function (LPS array).
10
+ * This is used for efficient pattern matching in text search.
11
+ *
12
+ * @param pattern The pattern string to compute the failure function for
13
+ * @returns Longest proper prefix array (LPS array)
14
+ *
15
+ * @example
16
+ * ```typescript
17
+ * const lps = computeKMPTable("abcabc");
18
+ * // Returns: [0, 0, 0, 1, 2, 3]
19
+ * ```
20
+ */
21
+ export declare const computeKMPTable: (pattern: string) => number[];
22
+ /**
23
+ * Finds all occurrences of a pattern in text using the KMP algorithm.
24
+ *
25
+ * @param text The text to search in
26
+ * @param pattern The pattern to search for
27
+ * @param startPos Starting position offset (default: 0)
28
+ * @param maxOccurrences Maximum number of occurrences to find (optional)
29
+ * @returns Array of start positions (0-based indices in the text)
30
+ *
31
+ * @example
32
+ * ```typescript
33
+ * const positions = kmpSearch("abcabcabc", "abc", 0, 2);
34
+ * // Returns: [0, 3] (first 2 occurrences)
35
+ * ```
36
+ */
37
+ export declare const kmpSearch: (text: string, pattern: string, startPos?: number, maxOccurrences?: number) => number[];
38
+ /**
39
+ * Maps text positions in a combined string back to document positions.
40
+ * Used when searching across multiple text nodes that have been concatenated.
41
+ *
42
+ * @param textNodes Array of text nodes with their document positions
43
+ * @param textPositions Positions in the combined text (from kmpSearch)
44
+ * @param patternLength Length of the pattern being searched for
45
+ * @returns Array of { from, to } ranges in document coordinates
46
+ *
47
+ * @example
48
+ * ```typescript
49
+ * const textNodes = [
50
+ * { text: "Hello ", pos: 0 },
51
+ * { text: "World", pos: 6 }
52
+ * ];
53
+ * const positions = [0]; // Found at start of combined text
54
+ * const ranges = mapTextPositionsToDocument(textNodes, positions, 5);
55
+ * // Returns: [{ from: 0, to: 5 }]
56
+ * ```
57
+ */
58
+ export declare const mapTextPositionsToDocument: (textNodes: Array<{
59
+ text: string;
60
+ pos: number;
61
+ }>, textPositions: number[], patternLength: number) => Array<{
62
+ from: number;
63
+ to: number;
64
+ }>;
65
+ /**
66
+ * Compares two maps for equality.
67
+ * Checks if both maps have the same size and identical key-value pairs.
68
+ *
69
+ * @param map1 First map to compare
70
+ * @param map2 Second map to compare
71
+ * @returns True if maps are equal, false otherwise
72
+ *
73
+ * @example
74
+ * ```typescript
75
+ * const map1 = new Map([['a', true], ['b', false]]);
76
+ * const map2 = new Map([['a', true], ['b', false]]);
77
+ * areMapsEqual(map1, map2); // Returns: true
78
+ * ```
79
+ */
80
+ export declare const areMapsEqual: <K, V>(map1: Map<K, V>, map2: Map<K, V>) => boolean;
@@ -0,0 +1,10 @@
1
+ export declare class Console {
2
+ static log: (...data: any[]) => void;
3
+ static warn: (...data: any[]) => void;
4
+ static error: (...data: any[]) => void;
5
+ static debug: (...data: any[]) => void;
6
+ static info: (...data: any[]) => void;
7
+ static logsEnabled: boolean;
8
+ static catch: (message: string, error?: unknown) => void;
9
+ static showLogs(): boolean;
10
+ }
@@ -0,0 +1,20 @@
1
+ /**
2
+ * Serializer utilities for Plate editor content
3
+ *
4
+ * This module provides utilities for serializing Plate editor content,
5
+ * particularly for removing comment nodes from serialized JSON.
6
+ *
7
+ * Use this when persisting editor content to remove Velt comment elements
8
+ * while preserving the original text content.
9
+ */
10
+ import type { Descendant } from 'slate';
11
+ /**
12
+ * Export JSON without comment nodes.
13
+ *
14
+ * This function takes Plate editor content and removes all comment nodes,
15
+ * unwrapping their children and merging adjacent text nodes with same formatting.
16
+ *
17
+ * @param content - Plate editor content (Descendant[])
18
+ * @returns Serialized content without comment nodes
19
+ */
20
+ export declare const exportJSONWithoutComments: (content: Descendant[]) => Descendant[];
package/esm/index.js ADDED
@@ -0,0 +1,2 @@
1
+ import{createPlatePlugin as t}from"@platejs/core/react";import{NodeApi as e,ElementApi as n,PathApi as o,TextApi as r}from"@platejs/slate";import{Editor as c}from"slate";import{ReactEditor as i}from"slate-react";import a from"react";const s={EDITOR_ID:"data-editor-id",LOCATION_ID:"data-velt-location-id",ANNOTATION_ID:"annotation-id",MULTI_THREAD_ANNOTATION_ID:"multi-thread-annotation-id"},l={VELT_COMMENT:"veltComment"},d="veltComment",u="veltComments",f="plateVeltComments",h="__default__",g="terminal",p="PlateVeltComments: ",m="debugMode",v="forceDebugMode",x=(t,e,n=0,o)=>{const r=[];if(!e||!t||e.length>t.length)return r;const c=(t=>{if(!t||0===t.length)return[];const e=new Array(t.length).fill(0);let n=0,o=1;for(;o<t.length;)t[o]===t[n]?(n++,e[o]=n,o++):0!==n?n=e[n-1]:(e[o]=0,o++);return e})(e);let i=0,a=0;for(;i<t.length;)if(e[a]===t[i]&&(i++,a++),a===e.length){if(r.push(n+i-a),a=c[a-1],o&&r.length>=o)break}else i<t.length&&e[a]!==t[i]&&(0!==a?a=c[a-1]:i++);return r};class y{static showLogs(){try{return!!sessionStorage.getItem(m)||!!sessionStorage.getItem(v)}catch(t){return y.catch("Error in showLogs: ",t),!1}}}y.log=y.showLogs()?console.log:()=>{},y.warn=y.showLogs()?console.warn:()=>{},y.error=y.showLogs()?console.error:()=>{},y.debug=y.showLogs()?console.debug:()=>{},y.info=y.showLogs()?console.info:()=>{},y.logsEnabled=!0,y.catch=(t,e)=>{try{y.logsEnabled&&(void 0!==e?console.warn(p,t,e):console.warn(p,t))}catch(t){}};const E=t=>{var e,n;try{const o=i.toDOMNode(t,t);return o&&(null!==(n=null===(e=null==o?void 0:o.closest(`[${s.EDITOR_ID}]`))||void 0===e?void 0:e.getAttribute(s.EDITOR_ID))&&void 0!==n)?n:null}catch(t){return null}},I=(t,e,n)=>{try{if(!e||!t.selection)return 0;if(n){const o=document.getElementById(n);if(o){const n=t.selection.anchor.offset;return O(o,e,n)}}const r=A(t,e),c=t.selection;if(!c||0===r.length)return 0;const i=o.compare(c.anchor.path,c.focus.path)>0||o.equals(c.anchor.path,c.focus.path)&&c.anchor.offset>c.focus.offset,a=r.findIndex(t=>i?o.equals(t.anchor.path,c.focus.path)&&o.equals(t.focus.path,c.anchor.path)&&t.anchor.offset===c.focus.offset&&t.focus.offset===c.anchor.offset:o.equals(t.anchor.path,c.anchor.path)&&o.equals(t.focus.path,c.focus.path)&&t.anchor.offset===c.anchor.offset&&t.focus.offset===c.focus.offset);return-1!==a?a+1:0}catch(t){return y.catch("[HostAdapter] Error finding occurrence index:",t),0}},w=t=>{try{const{selection:n}=t;if(!n)return null;const{anchor:o}=n,r=e.get(t,o.path);return r?T(t,r,o.path):null}catch(t){return y.catch("[HostAdapter] Error finding parent node with ID:",t),null}},T=(t,e,n,o=100)=>{try{let n=null,r=null;try{n=i.toDOMNode(t,e)}catch(t){return null}try{r=i.toDOMNode(t,t)}catch(t){return null}let c=n,a=0;for(;c&&c!==document.body&&a<o;){if(!r||!r.contains(c))return null;if(c.id)return c;c=c.parentElement,a++}return null}catch(t){return y.catch("[HostAdapter] Error finding parent node:",t),null}},A=(t,n,o=!0)=>{try{const r=[];if(!n)return r;const c=t=>"object"==typeof t&&null!==t&&"text"in t?t.text:"",i=t=>"object"==typeof t&&null!==t&&"text"in t&&"string"==typeof t.text,a=(t,e)=>{if(i(t)){const i=c(t),a=o?n:n.toLowerCase(),s=o?i:i.toLowerCase(),l=x(s,a);for(const t of l){const o={anchor:{path:e,offset:t},focus:{path:e,offset:t+n.length}};r.push(o)}}"children"in t&&Array.isArray(t.children)&&t.children.forEach((t,n)=>{a(t,[...e,n])})};try{const n=e.nodes(t,{pass:()=>!0}),[o]=Array.from(n).slice(0,1);o&&a(o[0],o[1])}catch(t){y.catch("[HostAdapter] Error searching in document:",t)}return r}catch(t){return y.catch("[HostAdapter] Error finding all matches:",t),[]}},O=(t,e,n,o=!0)=>{try{if(!e)return 0;const r=t.textContent||"",c=o?r:r.toLowerCase(),i=o?e:e.toLowerCase(),a=x(c,i);if(0===a.length)return 0;if(void 0!==n){return a.filter(t=>t<n).length+1}return 1}catch(t){return y.catch("[HostAdapter] Error finding occurrence in DOM:",t),0}},N=(t,n,r,i,a)=>{try{if(!n)return 0;const a=e.string(r);if(!a||!a.trim())return 0;const s=A(t,n);if(0===s.length)return 0;for(let e=0;e<s.length;e++){const n=s[e],r=c.start(t,n);if(!r)continue;const a=r.path,l=o.equals(a,i),d=o.isAncestor(i,a);if(l||d)return e+1}return 0}catch(t){return y.catch("[HostAdapter] Error finding occurrence for node:",t),0}},C=(t,e)=>{try{let n=t;return n||(n=E(e)||h),{editorId:n}}catch(e){return y.warn("[ensureEditorSetup] Error setting up editor:",e),{editorId:t||h}}},$=t=>{const{attributes:e,children:n,element:o}=t,r=null==o?void 0:o.annotationId;return a.createElement("velt-comment-text",Object.assign({[s.ANNOTATION_ID]:r},e),n)},b=new Map,M=t=>{const e={annotations:new Map,commentAnnotations:[],selectedAnnotations:new Set,editorId:t};return b.set(t,e),e},k=t=>{let e=b.get(t);return e||(e=M(t)),e},V=(t,e)=>{try{const n=k(t);n.commentAnnotations=e;const o=new Map;for(const t of e){if(!(null==t?void 0:t.annotationId))continue;const e={annotationId:t.annotationId,multiThreadAnnotationId:t.multiThreadAnnotationId,context:t.context};o.set(t.annotationId,e)}n.annotations=o}catch(t){y.catch("Error updating annotations:",t)}},S=(t,e)=>{try{const n=b.get(t);return n&&n.annotations.get(e)||null}catch(t){return y.catch("Error getting annotation:",t),null}},_=new Map;const D=t=>n.isElement(t)&&t.type===l.VELT_COMMENT,L=(t,o,r,c,i,a)=>{const s="[applyAnnotationMarkByText]";try{if(!t||!c)return!1;const d=t;let u=null;if(a){if(u=document.getElementById(a),!u)return y.warn(`${s} Target element not found: ${a}`),!1;if(!H(d,u))return y.warn(`${s} Target element not in editor: ${a}`),!1}else try{const t=document.querySelector('[data-slate-editor="true"]');t&&(u=t)}catch(t){y.warn(`${s} Could not find editor DOM element`,t)}if(!u)return y.warn(`${s} No target element found`),!1;const f=R(d,o,r,u);if(!f)return y.warn(`${s} Could not find text occurrence range for "${o}" occurrence ${r}`),!1;const h=((t,o,r,c)=>{try{return!!c&&(!(Array.from(e.nodes(t,{from:c.anchor.path,to:c.focus.path,pass:([t])=>!!n.isElement(t)&&D(t)})).filter(([t])=>n.isElement(t)&&D(t)).length>0)&&(t.tf.wrapNodes({type:l.VELT_COMMENT,children:[],annotationId:o,multiThreadAnnotationId:r},{at:c,split:!0}),!0))}catch(t){return y.catch("[HostAdapter] Error applying annotation mark:",t),!1}})(d,c,i,f);return h}catch(t){return y.catch(`${s} Error applying annotation mark by text:`,t),!1}},j=(t,o)=>{const r="[removeAnnotationMark]";try{if(!t||!o)return!1;const c=[];for(const[r,i]of e.descendants(t))n.isElement(r)&&D(r)&&r.annotationId===o&&c.push(i);return 0!==c.length&&(c.reverse().forEach(e=>{try{(()=>{t.tf.unwrapNodes({at:e,mode:"lowest"})})()}catch(t){y.catch(`${r} Error unwrapping element at path ${e}:`,t)}}),!0)}catch(t){return y.catch(`${r} Error removing annotation mark:`,t),!1}},H=(t,e)=>{try{const t=document.querySelector('[data-slate-editor="true"]');return!!t&&t.contains(e)}catch(t){return y.catch("[HostAdapter] Error checking element in editor:",t),!1}},R=(t,e,n,o)=>{const r="[findTextOccurrenceRange]";try{let c,a;if(o.hasAttribute("data-slate-editor"))c=t,a=[];else{const e=i.toSlateNode(t,o);if(!e)return y.warn(`${r} Could not convert target element to Slate node`),null;c=e;const n=t.api.findPath(c);if(!n)return y.warn(`${r} Could not find path for node`),null;a=n}const{fullText:s,textNodePositions:l}=P(t,c,a),d=[];let u;const f=new RegExp(e.replace(/[.*+?^${}()|[\]\\]/g,"\\$&"),"g");for(;null!==(u=f.exec(s));)d.push({index:u.index});if(d.length<n)return y.warn(`${r} Not enough occurrences: found ${d.length}, need ${n}`),null;const h=d[n-1].index,g=h+e.length;let p,m;for(const t of l)if(h>=t.start&&h<t.end&&!p&&(p=t),g>t.start&&g<=t.end&&!m&&(m=t),p&&m){return{anchor:{path:p.path,offset:h-p.start},focus:{path:m.path,offset:g-m.start}}}return y.warn(`${r} Could not find anchor/focus nodes for match`),null}catch(t){return y.catch(`${r} Error finding text occurrence range:`,t),null}},P=(t,e,o)=>{const c=[];let i="";const a=(t,e,o,c)=>{try{if(r.isText(t)){const n=c.length,r=(c+=t.text).length;o.push({node:t,path:e,start:n,end:r})}else if(n.isElement(t))for(let n=0;n<t.children.length;n++){const r=[...e,n];c=a(t.children[n],r,o,c)}return c}catch(t){return y.catch("[HostAdapter] Error traversing nodes for text:",t),c}};if(0===o.length)for(let e=0;e<t.children.length;e++){const n=[e];i=a(t.children[e],n,c,i)}else i=a(e,o,c,i);return{fullText:i,textNodePositions:c}};function q(t,e,n,o){return new(n||(n=Promise))(function(r,c){function i(t){try{s(o.next(t))}catch(t){c(t)}}function a(t){try{s(o.throw(t))}catch(t){c(t)}}function s(t){var e;t.done?r(t.value):(e=t.value,e instanceof n?e:new n(function(t){t(e)})).then(i,a)}s((o=o.apply(t,e||[])).next())})}"function"==typeof SuppressedError&&SuppressedError;let B=!1,z=new Map;const F=new Map,J=()=>{try{const t=window.Velt;return(null==t?void 0:t.getCommentElement)?t.getCommentElement():null}catch(t){return y.catch("[VeltAdapter] Error getting comment element:",t),null}},U=(t,e)=>{try{const n=J();if(!n)return;n.updateContext(t,e)}catch(t){y.catch("[VeltAdapter] Error updating context:",t)}},K=()=>{const t=J();if(!(null==t?void 0:t.getSelectedComments))return!1;try{const e=t.getSelectedComments();if(!(null==e?void 0:e.subscribe))return!1;const n=e.subscribe(t=>{const e=new Map;if(null==t||t.forEach(t=>{(null==t?void 0:t.annotationId)&&e.set(t.annotationId,!0)}),!((t,e)=>{if(t.size!==e.size)return!1;for(const[n,o]of Array.from(t))if(e.get(n)!==o)return!1;return!0})(e,z)){z=e;const t=new Set;for(const[n]of e)t.add(n);F.forEach(e=>{if("function"==typeof e)try{e(t)}catch(t){y.catch("[VeltAdapter] Error in subscriber callback:",t)}})}});if(n&&"function"==typeof n.unsubscribe)return B=!0,!0}catch(t){y.catch("[VeltAdapter] Error setting up getSelectedComments subscription:",t)}return!1},G=(t,o,r)=>{var c;const i="[handleContentUpdate]";try{const r=e=>{var n,o,r,c,i,a;const s=S(t,e);if(!s)return null;return{annotation:s,originalText:(null===(o=null===(n=s.context)||void 0===n?void 0:n.textEditorConfig)||void 0===o?void 0:o.text)||"",originalOccurrence:(null===(c=null===(r=s.context)||void 0===r?void 0:r.textEditorConfig)||void 0===c?void 0:c.occurrence)||1,targetTextNodeId:(null===(a=null===(i=s.context)||void 0===i?void 0:i.textEditorConfig)||void 0===a?void 0:a.targetTextNodeId)||""}},a=((t,o,r=d,c)=>{const i="[detectDocumentChanges]",a=new Map;try{const o=Array.from(e.nodes(t,{pass:([t])=>n.isElement(t)&&t.type===l.VELT_COMMENT&&"annotationId"in t})).filter(([t])=>n.isElement(t)&&t.type===l.VELT_COMMENT&&"annotationId"in t);for(const[n,r]of o){const o=n.annotationId;if(!o){y.warn(`${i} Node missing annotationId, skipping`);continue}const s=c(o);if(!s){y.warn(`${i} No stored data found for annotationId: ${o}, skipping`);continue}const l=s.originalText,d=s.originalOccurrence,u=s.targetTextNodeId||"",f=e.string(n);if(!f){y.warn(`${i} Node has no text content, skipping`);continue}const h=T(t,n,r),g=(null==h?void 0:h.id)||"",p=N(t,f,n,r,g),m=f!==l,v=p!==d,x=u!==g;if(m||v||x){const t=s.annotation;a.set(o,{annotationId:o,multiThreadAnnotationId:t.multiThreadAnnotationId,originalText:l,currentText:f,originalOccurrence:d,currentOccurrence:p,originalTargetTextNodeId:u,newTargetTextNodeId:g,annotation:t,contentChanged:m,occurrenceChanged:v,targetTextNodeIdChanged:x})}}}catch(t){y.catch("[HostAdapter] Error detecting document changes:",t)}return a})(o,0,d,r);if(0===a.size)return;y.log(`${i} Detected ${a.size} annotation changes`);for(const[e,n]of Array.from(a.entries())){const o=`${i}[${e}]`,r=S(t,e);if(!r){y.warn(`${o} Annotation not found in state, skipping`);continue}if(!(null===(c=r.context)||void 0===c?void 0:c.textEditorConfig)){y.warn(`${o} No textEditorConfig, skipping`);continue}const a=JSON.parse(JSON.stringify(r.context.textEditorConfig));n.contentChanged&&(y.log(`${o} Content changed: "${a.text}" -> "${n.currentText}"`),a.text=n.currentText),n.occurrenceChanged&&(y.log(`${o} Occurrence changed: ${a.occurrence} -> ${n.currentOccurrence}`),a.occurrence=n.currentOccurrence),n.targetTextNodeIdChanged&&(y.log(`${o} TargetTextNodeId changed: "${a.targetTextNodeId}" -> "${n.newTargetTextNodeId}"`),a.targetTextNodeId=n.newTargetTextNodeId);const s=Object.assign(Object.assign({},r.context),{textEditorConfig:a});y.log(`${o} Updating Velt context`),U(e,s)}((t,e)=>{try{for(const[n]of e)j(t,n)}catch(t){y.catch("[HostAdapter] Error updating marks:",t)}})(o,a)}catch(t){y.catch(`${i} Error handling content update:`,t)}},Q=t({key:u,node:{isElement:!0,isInline:!0,type:l.VELT_COMMENT},render:{node:$},options:{editorId:void 0,persistVeltMarks:!0},handlers:{onChange:({editor:t,getOptions:e})=>{var n;if(null===(n=t.operations)||void 0===n?void 0:n.some(t=>"insert_text"===t.type||"remove_text"===t.type)){const n=e().editorId||E(t)||h;G(n,t)}}}}).overrideEditor(({api:{isInline:t},editor:e,getOptions:o})=>{var r;const c=o(),i=c.editorId||E(e)||h;return((t,e,n)=>{const o=t||"default";M(o);const r={editorId:o,editor:e,config:n||{}};_.set(o,r)})(i,e,{persistVeltMarks:null===(r=c.persistVeltMarks)||void 0===r||r,editorId:i}),{api:{isInline:e=>!(!n.isElement(e)||!(t=>n.isElement(t)&&t.type===l.VELT_COMMENT)(e))||t(e)}}}),W=(t,e=f)=>{var n;try{const e=E(t);if(!e)return!0;const o=(t=>_.get(t)||null)(e);return void 0===(null===(n=null==o?void 0:o.config)||void 0===n?void 0:n.persistVeltMarks)||o.config.persistVeltMarks}catch(t){return y.warn("[getPersistVeltMarks] Error checking persistVeltMarks, defaulting to true:",t),!0}};function X(t){return q(this,arguments,void 0,function*({editorId:t,editor:e,context:n}){const o="[addComment]";var r;if(e)try{if(!J())return void y.warn(`${o} Velt SDK not available, cannot add comment`);const i=(t=>{var e,n,o;try{if(!t.selection)return null;const r=c.string(t,t.selection);if(!r)return null;const i=c.start(t,t.selection),a=c.end(t,t.selection),l=null!==(e=null==i?void 0:i.offset)&&void 0!==e?e:0,d=null!==(n=null==a?void 0:a.offset)&&void 0!==n?n:0,u=w(t),f=null==u?void 0:u.id;let h;return u&&(h=(null===(o=u.closest(`[${s.LOCATION_ID}]`))||void 0===o?void 0:o.getAttribute(s.LOCATION_ID))||void 0),{text:r,from:l,to:d,occurrence:I(t,r,f),targetTextNodeId:f,locationId:h}}catch(t){return y.catch("[HostAdapter] Error getting selection context:",t),null}})(e);if(!i)return void y.warn(`${o} No valid selection found, exiting`);const{editorId:a}=C(t,e),l=void 0!==t||a!==h,d=Object.assign(Object.assign({},n&&"object"==typeof n?n:{}),{textEditorConfig:Object.assign(Object.assign({text:i.text,occurrence:i.occurrence},l&&{editorId:a}),{targetTextNodeId:i.targetTextNodeId})});let u;i.locationId&&(u={id:i.locationId}),yield new Promise(t=>setTimeout(t,200));const g=yield(r={context:d,location:u},q(void 0,void 0,void 0,function*(){try{const t=J();if(!t)return null;const e=yield t.addManualComment({context:r.context,location:r.location});return e?{annotation:e}:null}catch(t){return y.catch("[VeltAdapter] Error adding comment:",t),null}}));if(!g||!g.annotation)return void y.warn(`${o} Failed to create comment via Velt SDK`);const p=g.annotation,m=((t,e=f)=>{try{return!1===W(t,e)}catch(t){return y.warn("[shouldApplyMark] Error checking persistVeltMarks, defaulting to true:",t),!0}})(e,f);m&&p.annotationId&&L(e,i.text,i.occurrence,p.annotationId,p.multiThreadAnnotationId,i.targetTextNodeId),p.annotationId?V(a,[p]):y.warn(`${o} No annotationId, skipping state update`)}catch(t){y.catch(`${o} Error adding comment:`,t)}else y.catch(`${o} ERROR: No editor provided`)})}const Y=new Map,Z=(t,e,n)=>{var o;try{const r=Y.get(t);r?r.editor=e:Y.set(t,{editor:e,previousFilteredAnnotations:[]});const c=(t=>{try{const e=b.get(t);return e?new Set(e.selectedAnnotations):new Set}catch(t){return y.catch("Error getting selected annotations:",t),new Set}})(t),i=((t,e)=>t.filter(t=>{var n;return(null===(n=null==t?void 0:t.status)||void 0===n?void 0:n.type)!==g||e.has(t.annotationId)}))(n,c),a=(null===(o=Y.get(t))||void 0===o?void 0:o.previousFilteredAnnotations)||[],s=new Set(i.map(t=>t.annotationId).filter(Boolean)),l=new Set(a.map(t=>t.annotationId).filter(Boolean)),d=Array.from(l).filter(t=>!s.has(t));for(const t of d)t&&j(e,t);const u=Y.get(t);u&&(u.previousFilteredAnnotations=i),((t,e)=>{var n;for(const o of e){const e=null===(n=null==o?void 0:o.context)||void 0===n?void 0:n.textEditorConfig;if(!(null==e?void 0:e.text)||!o.annotationId)continue;const r=e.text,c=e.occurrence||1,i=e.targetTextNodeId;L(t,r,c,o.annotationId,o.multiThreadAnnotationId,i)}})(e,i)}catch(t){y.catch("[commentRenderer:updateComments] Error updating comments:",t)}},tt=(t,e)=>{const n="[commentRenderer:updateSelection]";try{const e=Y.get(t);if(!e||!e.editor)return void y.warn(`${n} No editor found for editorId: ${t}`);const o=(t=>{try{const e=b.get(t);return e?[...e.commentAnnotations]:[]}catch(t){return y.catch("Error getting comment annotations:",t),[]}})(t);Z(t,e.editor,o)}catch(t){y.catch(`${n} Error updating selection:`,t)}},et=new Map,nt=({editor:t,editorId:e,commentAnnotations:n})=>{const o="[renderComments]";try{if(!t)return void y.warn(`${o} No editor provided`);n&&Array.isArray(n)||(n=[]);const{editorId:r}=C(e,t),c=JSON.parse(JSON.stringify(n)).filter(t=>{var e;if(!(null===(e=null==t?void 0:t.context)||void 0===e?void 0:e.textEditorConfig))return!1;const n=t.context.textEditorConfig.editorId;return r===h?void 0===n||n===h||"default"===n:n===r});if(V(r,c),!et.has(r)){const t=r,e=((t,e)=>{try{return F.set(e,t),B||K(),()=>{F.delete(e)}}catch(t){return y.catch("[VeltAdapter] Error subscribing to selected annotations:",t),()=>{}}})(e=>{((t,e)=>{try{k(t).selectedAnnotations=new Set(e)}catch(t){y.catch("Error setting selected annotations:",t)}})(t,e),tt(t)},t);et.set(r,e)}B||K(),Z(r,t,c)}catch(t){y.catch(`${o} Error rendering comments:`,t)}},ot=t=>{const e=et.get(t);e&&(e(),et.delete(t)),(t=>{Y.delete(t)})(t)},rt=l.VELT_COMMENT,ct=t=>{const e=it(t);return lt(e)},it=t=>at(t),at=t=>{const e=[];for(const n of t){if(ft(n)&&n.type===rt){const t=at(n.children);e.push(...t);continue}e.push(st(n))}return e},st=t=>{if(ft(t)){const e=at(t.children);return Object.assign(Object.assign({},t),{children:e})}return t},lt=t=>{const e=t.map(dt);return ut(e)},dt=t=>{if(ft(t)){const e=t.children.map(dt);return Object.assign(Object.assign({},t),{children:ut(e)})}return t},ut=t=>{var e,n;if(t.length<2)return t;const o=[];let r=0;for(;r<t.length;){const c=t[r];if(ht(c)){if(""===c.text){r++;continue}let i=null!==(e=c.text)&&void 0!==e?e:"",a=r+1;for(;a<t.length;){const e=t[a];if(ht(e)&&""===e.text)a++;else{if(!ht(e)||!gt(c,e))break;i+=null!==(n=e.text)&&void 0!==n?n:"",a++}}o.push(Object.assign(Object.assign({},c),{text:i})),r=a}else o.push(c),r++}return o.length>0?o:[{text:""}]},ft=t=>Object.prototype.hasOwnProperty.call(t,"children")&&Object.prototype.hasOwnProperty.call(t,"type"),ht=t=>Object.prototype.hasOwnProperty.call(t,"text"),gt=(t,e)=>t.bold===e.bold&&t.italic===e.italic&&t.underline===e.underline;export{$ as PlateVeltComment,Q as VeltCommentsPlugin,X as addComment,ot as cleanupRenderComments,ct as exportJSONWithoutComments,nt as renderComments};
2
+ //# sourceMappingURL=index.js.map