@intinyagroup/rich-text 0.1.1-alpha.10

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,19 @@
1
+ type $$ComponentProps = {
2
+ content?: string;
3
+ placeholder?: string;
4
+ editable?: boolean;
5
+ /** Toolbar mode: 'classic' (fixed top toolbar), 'bubble' (Notion-style floating toolbar only), or 'none' */
6
+ mode?: 'classic' | 'bubble' | 'none';
7
+ height?: number;
8
+ class?: string;
9
+ onUpdate?: (html: string) => void;
10
+ /** Called when paste/drop provides an image file. Return a URL to insert. */
11
+ onImageUpload?: (file: File) => Promise<string>;
12
+ onOpenSubPage?: (page: {
13
+ id: string;
14
+ title: string;
15
+ }) => void;
16
+ };
17
+ declare const RichTextEditor: import("svelte").Component<$$ComponentProps, {}, "">;
18
+ type RichTextEditor = ReturnType<typeof RichTextEditor>;
19
+ export default RichTextEditor;
@@ -0,0 +1 @@
1
+ export { default as RichTextEditor } from './components/RichTextEditor.svelte';
package/dist/index.js ADDED
@@ -0,0 +1 @@
1
+ export { default as RichTextEditor } from './components/RichTextEditor.svelte';
@@ -0,0 +1,31 @@
1
+ export type TrackedChange = {
2
+ id: string;
3
+ type: 'insertion' | 'deletion';
4
+ userId: string;
5
+ userName: string;
6
+ timestamp: string;
7
+ content: string;
8
+ accepted: boolean;
9
+ };
10
+ export type TrackedChangeState = {
11
+ enabled: boolean;
12
+ changes: TrackedChange[];
13
+ currentUserId: string;
14
+ currentUserName: string;
15
+ };
16
+ export declare function createTrackedChangeState(userId: string, userName: string): TrackedChangeState;
17
+ export declare function addTrackedChange(state: TrackedChangeState, type: 'insertion' | 'deletion', content: string): TrackedChange;
18
+ export declare function acceptChange(state: TrackedChangeState, changeId: string): TrackedChangeState;
19
+ export declare function rejectChange(state: TrackedChangeState, changeId: string): TrackedChangeState;
20
+ export declare function acceptAllChanges(state: TrackedChangeState): TrackedChangeState;
21
+ export declare function rejectAllChanges(state: TrackedChangeState): TrackedChangeState;
22
+ export declare function getPendingChangesCount(state: TrackedChangeState): number;
23
+ export declare function getChangesByUser(state: TrackedChangeState, userId: string): TrackedChange[];
24
+ /**
25
+ * Render tracked changes as HTML with colored marks
26
+ */
27
+ export declare function renderTrackedChanges(html: string, changes: TrackedChange[]): string;
28
+ /**
29
+ * Extract tracked changes from HTML
30
+ */
31
+ export declare function extractTrackedChanges(html: string): TrackedChange[];
@@ -0,0 +1,106 @@
1
+ // ============================================
2
+ // Tracked Changes utilities — track insertions/deletions
3
+ // ============================================
4
+ export function createTrackedChangeState(userId, userName) {
5
+ return {
6
+ enabled: false,
7
+ changes: [],
8
+ currentUserId: userId,
9
+ currentUserName: userName,
10
+ };
11
+ }
12
+ export function addTrackedChange(state, type, content) {
13
+ const change = {
14
+ id: `tc-${Date.now()}-${Math.random().toString(36).slice(2, 7)}`,
15
+ type,
16
+ userId: state.currentUserId,
17
+ userName: state.currentUserName,
18
+ timestamp: new Date().toISOString(),
19
+ content,
20
+ accepted: false,
21
+ };
22
+ return change;
23
+ }
24
+ export function acceptChange(state, changeId) {
25
+ return {
26
+ ...state,
27
+ changes: state.changes.map((c) => c.id === changeId ? { ...c, accepted: true } : c),
28
+ };
29
+ }
30
+ export function rejectChange(state, changeId) {
31
+ return {
32
+ ...state,
33
+ changes: state.changes.filter((c) => c.id !== changeId),
34
+ };
35
+ }
36
+ export function acceptAllChanges(state) {
37
+ return {
38
+ ...state,
39
+ changes: state.changes.map((c) => ({ ...c, accepted: true })),
40
+ };
41
+ }
42
+ export function rejectAllChanges(state) {
43
+ return {
44
+ ...state,
45
+ changes: [],
46
+ };
47
+ }
48
+ export function getPendingChangesCount(state) {
49
+ return state.changes.filter((c) => !c.accepted).length;
50
+ }
51
+ export function getChangesByUser(state, userId) {
52
+ return state.changes.filter((c) => c.userId === userId);
53
+ }
54
+ /**
55
+ * Render tracked changes as HTML with colored marks
56
+ */
57
+ export function renderTrackedChanges(html, changes) {
58
+ let result = html;
59
+ for (const change of changes) {
60
+ if (change.accepted)
61
+ continue;
62
+ if (change.type === 'insertion') {
63
+ // Mark insertions with green background
64
+ result = result.replace(change.content, `<span class="tracked-insertion" data-change-id="${change.id}" style="background: #dcfce7; text-decoration: none;">${change.content}</span>`);
65
+ }
66
+ else if (change.type === 'deletion') {
67
+ // Mark deletions with red strikethrough
68
+ result = result.replace(change.content, `<span class="tracked-deletion" data-change-id="${change.id}" style="background: #fee2e2; text-decoration: line-through; color: #991b1b;">${change.content}</span>`);
69
+ }
70
+ }
71
+ return result;
72
+ }
73
+ /**
74
+ * Extract tracked changes from HTML
75
+ */
76
+ export function extractTrackedChanges(html) {
77
+ const changes = [];
78
+ // Extract insertions
79
+ const insertionRegex = /<span[^>]*class="tracked-insertion"[^>]*data-change-id="([^"]*)"[^>]*>(.*?)<\/span>/gi;
80
+ let match;
81
+ while ((match = insertionRegex.exec(html)) !== null) {
82
+ changes.push({
83
+ id: match[1],
84
+ type: 'insertion',
85
+ userId: 'unknown',
86
+ userName: 'Unknown',
87
+ timestamp: new Date().toISOString(),
88
+ content: match[2],
89
+ accepted: false,
90
+ });
91
+ }
92
+ // Extract deletions
93
+ const deletionRegex = /<span[^>]*class="tracked-deletion"[^>]*data-change-id="([^"]*)"[^>]*>(.*?)<\/span>/gi;
94
+ while ((match = deletionRegex.exec(html)) !== null) {
95
+ changes.push({
96
+ id: match[1],
97
+ type: 'deletion',
98
+ userId: 'unknown',
99
+ userName: 'Unknown',
100
+ timestamp: new Date().toISOString(),
101
+ content: match[2],
102
+ accepted: false,
103
+ });
104
+ }
105
+ return changes;
106
+ }
package/package.json ADDED
@@ -0,0 +1,54 @@
1
+ {
2
+ "name": "@intinyagroup/rich-text",
3
+ "version": "0.1.1-alpha.10",
4
+ "description": "Rich text editor component powered by TipTap",
5
+ "type": "module",
6
+ "exports": {
7
+ ".": {
8
+ "types": "./dist/index.d.ts",
9
+ "svelte": "./dist/index.js"
10
+ }
11
+ },
12
+ "files": [
13
+ "dist",
14
+ "README.md"
15
+ ],
16
+ "scripts": {
17
+ "build": "svelte-package -o dist",
18
+ "check": "echo 'no check'",
19
+ "dev": "svelte-package -o dist -w"
20
+ },
21
+ "dependencies": {
22
+ "@intinyagroup/grid-core": "0.1.1-alpha.10",
23
+ "@intinyagroup/ui": "0.1.1-alpha.10",
24
+ "@tiptap/core": "^3.22.5",
25
+ "@tiptap/extension-code-block-lowlight": "^3.22.5",
26
+ "@tiptap/extension-image": "^3.22.5",
27
+ "@tiptap/extension-link": "^3.22.5",
28
+ "@tiptap/extension-placeholder": "^3.22.5",
29
+ "@tiptap/extension-task-item": "^3.31.3",
30
+ "@tiptap/extension-task-list": "^3.31.3",
31
+ "@tiptap/extension-text-align": "^3.22.5",
32
+ "@tiptap/extension-underline": "^3.22.5",
33
+ "@tiptap/pm": "^3.22.5",
34
+ "@tiptap/starter-kit": "^3.22.5"
35
+ },
36
+ "devDependencies": {
37
+ "@sveltejs/package": "^2.5.8",
38
+ "@sveltejs/vite-plugin-svelte": "^5.1.1",
39
+ "svelte": "^5.55.2",
40
+ "typescript": "^6.0.2"
41
+ },
42
+ "peerDependencies": {
43
+ "svelte": "^5.0.0"
44
+ },
45
+ "license": "MIT",
46
+ "repository": {
47
+ "type": "git",
48
+ "url": "git+https://github.com/intinyagroup/ui.git",
49
+ "directory": "packages/rich-text"
50
+ },
51
+ "publishConfig": {
52
+ "access": "public"
53
+ }
54
+ }