@overlap/rte 0.1.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 (75) hide show
  1. package/README.md +269 -0
  2. package/dist/components/Dropdown.d.ts +19 -0
  3. package/dist/components/Dropdown.d.ts.map +1 -0
  4. package/dist/components/Editor.d.ts +4 -0
  5. package/dist/components/Editor.d.ts.map +1 -0
  6. package/dist/components/FloatingToolbar.d.ts +10 -0
  7. package/dist/components/FloatingToolbar.d.ts.map +1 -0
  8. package/dist/components/IconWrapper.d.ts +10 -0
  9. package/dist/components/IconWrapper.d.ts.map +1 -0
  10. package/dist/components/Icons.d.ts +32 -0
  11. package/dist/components/Icons.d.ts.map +1 -0
  12. package/dist/components/Toolbar.d.ts +10 -0
  13. package/dist/components/Toolbar.d.ts.map +1 -0
  14. package/dist/components/index.d.ts +3 -0
  15. package/dist/components/index.d.ts.map +1 -0
  16. package/dist/index.d.ts +208 -0
  17. package/dist/index.d.ts.map +1 -0
  18. package/dist/index.esm.js +2080 -0
  19. package/dist/index.esm.js.map +1 -0
  20. package/dist/index.js +2116 -0
  21. package/dist/index.js.map +1 -0
  22. package/dist/plugins/base.d.ts +10 -0
  23. package/dist/plugins/base.d.ts.map +1 -0
  24. package/dist/plugins/clearFormatting.d.ts +6 -0
  25. package/dist/plugins/clearFormatting.d.ts.map +1 -0
  26. package/dist/plugins/colors.d.ts +4 -0
  27. package/dist/plugins/colors.d.ts.map +1 -0
  28. package/dist/plugins/fontSize.d.ts +3 -0
  29. package/dist/plugins/fontSize.d.ts.map +1 -0
  30. package/dist/plugins/headings.d.ts +3 -0
  31. package/dist/plugins/headings.d.ts.map +1 -0
  32. package/dist/plugins/image.d.ts +6 -0
  33. package/dist/plugins/image.d.ts.map +1 -0
  34. package/dist/plugins/index.d.ts +14 -0
  35. package/dist/plugins/index.d.ts.map +1 -0
  36. package/dist/plugins/optional.d.ts +19 -0
  37. package/dist/plugins/optional.d.ts.map +1 -0
  38. package/dist/styles.css +638 -0
  39. package/dist/types.d.ts +81 -0
  40. package/dist/types.d.ts.map +1 -0
  41. package/dist/utils/clearFormatting.d.ts +21 -0
  42. package/dist/utils/clearFormatting.d.ts.map +1 -0
  43. package/dist/utils/content.d.ts +12 -0
  44. package/dist/utils/content.d.ts.map +1 -0
  45. package/dist/utils/history.d.ts +14 -0
  46. package/dist/utils/history.d.ts.map +1 -0
  47. package/dist/utils/listIndent.d.ts +9 -0
  48. package/dist/utils/listIndent.d.ts.map +1 -0
  49. package/dist/utils/stateReflection.d.ts +18 -0
  50. package/dist/utils/stateReflection.d.ts.map +1 -0
  51. package/package.json +48 -0
  52. package/src/components/Dropdown.tsx +103 -0
  53. package/src/components/Editor.css +2 -0
  54. package/src/components/Editor.tsx +785 -0
  55. package/src/components/FloatingToolbar.tsx +214 -0
  56. package/src/components/IconWrapper.tsx +14 -0
  57. package/src/components/Icons.tsx +145 -0
  58. package/src/components/Toolbar.tsx +137 -0
  59. package/src/components/index.ts +3 -0
  60. package/src/index.ts +19 -0
  61. package/src/plugins/base.tsx +91 -0
  62. package/src/plugins/clearFormatting.tsx +31 -0
  63. package/src/plugins/colors.tsx +122 -0
  64. package/src/plugins/fontSize.tsx +81 -0
  65. package/src/plugins/headings.tsx +76 -0
  66. package/src/plugins/image.tsx +189 -0
  67. package/src/plugins/index.ts +54 -0
  68. package/src/plugins/optional.tsx +221 -0
  69. package/src/styles.css +638 -0
  70. package/src/types.ts +92 -0
  71. package/src/utils/clearFormatting.ts +244 -0
  72. package/src/utils/content.ts +290 -0
  73. package/src/utils/history.ts +59 -0
  74. package/src/utils/listIndent.ts +171 -0
  75. package/src/utils/stateReflection.ts +175 -0
@@ -0,0 +1,21 @@
1
+ /**
2
+ * Entfernt alle Formatierungen aus der aktuellen Selection
3
+ */
4
+ export declare function clearFormatting(selection: Selection): void;
5
+ /**
6
+ * Entfernt nur Textfarbe
7
+ */
8
+ export declare function clearTextColor(selection: Selection): void;
9
+ /**
10
+ * Entfernt nur Hintergrundfarbe
11
+ */
12
+ export declare function clearBackgroundColor(selection: Selection): void;
13
+ /**
14
+ * Entfernt nur Font-Size
15
+ */
16
+ export declare function clearFontSize(selection: Selection): void;
17
+ /**
18
+ * Entfernt Links (behält Text)
19
+ */
20
+ export declare function clearLinks(selection: Selection): void;
21
+ //# sourceMappingURL=clearFormatting.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"clearFormatting.d.ts","sourceRoot":"","sources":["../../src/utils/clearFormatting.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,wBAAgB,eAAe,CAAC,SAAS,EAAE,SAAS,GAAG,IAAI,CAiF1D;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,SAAS,EAAE,SAAS,GAAG,IAAI,CAgCzD;AAED;;GAEG;AACH,wBAAgB,oBAAoB,CAAC,SAAS,EAAE,SAAS,GAAG,IAAI,CAgC/D;AAED;;GAEG;AACH,wBAAgB,aAAa,CAAC,SAAS,EAAE,SAAS,GAAG,IAAI,CAgCxD;AAED;;GAEG;AACH,wBAAgB,UAAU,CAAC,SAAS,EAAE,SAAS,GAAG,IAAI,CA0CrD"}
@@ -0,0 +1,12 @@
1
+ import React from "react";
2
+ import { EditorContent } from "../types";
3
+ export declare function domToContent(element: HTMLElement): EditorContent;
4
+ export declare function contentToDOM(content: EditorContent, container: HTMLElement, customLinkComponent?: React.ComponentType<{
5
+ href: string;
6
+ children: React.ReactNode;
7
+ [key: string]: any;
8
+ }>, customHeadingRenderer?: (level: string, children: React.ReactNode) => React.ReactElement): void;
9
+ export declare function createEmptyContent(): EditorContent;
10
+ export declare function htmlToContent(htmlString: string): EditorContent;
11
+ export declare function contentToHTML(content: EditorContent): string;
12
+ //# sourceMappingURL=content.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"content.d.ts","sourceRoot":"","sources":["../../src/utils/content.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAE,aAAa,EAAc,MAAM,UAAU,CAAC;AAErD,wBAAgB,YAAY,CAAC,OAAO,EAAE,WAAW,GAAG,aAAa,CAsKhE;AAED,wBAAgB,YAAY,CACxB,OAAO,EAAE,aAAa,EACtB,SAAS,EAAE,WAAW,EACtB,mBAAmB,CAAC,EAAE,KAAK,CAAC,aAAa,CAAC;IACtC,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;IAC1B,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,CAAC;CACtB,CAAC,EACF,qBAAqB,CAAC,EAAE,CACpB,KAAK,EAAE,MAAM,EACb,QAAQ,EAAE,KAAK,CAAC,SAAS,KACxB,KAAK,CAAC,YAAY,GACxB,IAAI,CAwFN;AAED,wBAAgB,kBAAkB,IAAI,aAAa,CAIlD;AAED,wBAAgB,aAAa,CAAC,UAAU,EAAE,MAAM,GAAG,aAAa,CAI/D;AAED,wBAAgB,aAAa,CAAC,OAAO,EAAE,aAAa,GAAG,MAAM,CAI5D"}
@@ -0,0 +1,14 @@
1
+ import { EditorContent } from '../types';
2
+ export declare class HistoryManager {
3
+ private history;
4
+ private currentIndex;
5
+ private maxHistorySize;
6
+ push(content: EditorContent): void;
7
+ undo(): EditorContent | null;
8
+ redo(): EditorContent | null;
9
+ canUndo(): boolean;
10
+ canRedo(): boolean;
11
+ getCurrent(): EditorContent | null;
12
+ reset(): void;
13
+ }
14
+ //# sourceMappingURL=history.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"history.d.ts","sourceRoot":"","sources":["../../src/utils/history.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAEzC,qBAAa,cAAc;IACzB,OAAO,CAAC,OAAO,CAAuB;IACtC,OAAO,CAAC,YAAY,CAAc;IAClC,OAAO,CAAC,cAAc,CAAc;IAEpC,IAAI,CAAC,OAAO,EAAE,aAAa,GAAG,IAAI;IAelC,IAAI,IAAI,aAAa,GAAG,IAAI;IAQ5B,IAAI,IAAI,aAAa,GAAG,IAAI;IAQ5B,OAAO,IAAI,OAAO;IAIlB,OAAO,IAAI,OAAO;IAIlB,UAAU,IAAI,aAAa,GAAG,IAAI;IAOlC,KAAK,IAAI,IAAI;CAId"}
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Erhöht den Einrückungs-Level eines List-Items (Tab)
3
+ */
4
+ export declare function indentListItem(selection: Selection): boolean;
5
+ /**
6
+ * Reduziert den Einrückungs-Level eines List-Items (Shift+Tab)
7
+ */
8
+ export declare function outdentListItem(selection: Selection): boolean;
9
+ //# sourceMappingURL=listIndent.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"listIndent.d.ts","sourceRoot":"","sources":["../../src/utils/listIndent.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,wBAAgB,cAAc,CAAC,SAAS,EAAE,SAAS,GAAG,OAAO,CA+F5D;AAED;;GAEG;AACH,wBAAgB,eAAe,CAAC,SAAS,EAAE,SAAS,GAAG,OAAO,CAkE7D"}
@@ -0,0 +1,18 @@
1
+ import { EditorAPI } from '../types';
2
+ /**
3
+ * Liest die aktuelle Font-Size aus dem DOM an der Cursor-Position
4
+ */
5
+ export declare function getCurrentFontSize(editor: EditorAPI): string | undefined;
6
+ /**
7
+ * Liest die aktuelle Textfarbe aus dem DOM an der Cursor-Position
8
+ */
9
+ export declare function getCurrentTextColor(editor: EditorAPI): string | undefined;
10
+ /**
11
+ * Liest die aktuelle Hintergrundfarbe aus dem DOM an der Cursor-Position
12
+ */
13
+ export declare function getCurrentBackgroundColor(editor: EditorAPI): string | undefined;
14
+ /**
15
+ * Liest das aktuelle Heading-Level aus dem DOM an der Cursor-Position
16
+ */
17
+ export declare function getCurrentHeading(editor: EditorAPI, availableHeadings: string[]): string | undefined;
18
+ //# sourceMappingURL=stateReflection.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"stateReflection.d.ts","sourceRoot":"","sources":["../../src/utils/stateReflection.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,UAAU,CAAC;AAErC;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,SAAS,GAAG,MAAM,GAAG,SAAS,CA2BxE;AAED;;GAEG;AACH,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,SAAS,GAAG,MAAM,GAAG,SAAS,CAkDzE;AAED;;GAEG;AACH,wBAAgB,yBAAyB,CAAC,MAAM,EAAE,SAAS,GAAG,MAAM,GAAG,SAAS,CAkD/E;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,SAAS,EAAE,iBAAiB,EAAE,MAAM,EAAE,GAAG,MAAM,GAAG,SAAS,CA0BpG"}
package/package.json ADDED
@@ -0,0 +1,48 @@
1
+ {
2
+ "name": "@overlap/rte",
3
+ "version": "0.1.0",
4
+ "description": "A lightweight, extensible Rich Text Editor for React",
5
+ "main": "dist/index.js",
6
+ "module": "dist/index.esm.js",
7
+ "types": "dist/index.d.ts",
8
+ "files": [
9
+ "dist",
10
+ "src"
11
+ ],
12
+ "type": "module",
13
+ "scripts": {
14
+ "build": "rollup -c",
15
+ "dev": "rollup -c -w",
16
+ "prepublishOnly": "npm run build"
17
+ },
18
+ "keywords": [
19
+ "react",
20
+ "rich-text-editor",
21
+ "rte",
22
+ "contenteditable",
23
+ "editor"
24
+ ],
25
+ "author": "Almir Nakicevic <a.nakicevic@overlap.at>",
26
+ "repository": {
27
+ "type": "git",
28
+ "url": "https://github.com/overlap-dev/hendriks-rte"
29
+ },
30
+ "peerDependencies": {
31
+ "react": ">=18.0.0",
32
+ "react-dom": ">=18.0.0"
33
+ },
34
+ "dependencies": {
35
+ "tslib": "^2.8.1"
36
+ },
37
+ "devDependencies": {
38
+ "@rollup/plugin-commonjs": "^25.0.7",
39
+ "@rollup/plugin-node-resolve": "^15.2.3",
40
+ "@rollup/plugin-typescript": "^11.1.5",
41
+ "@types/react": "^18.2.43",
42
+ "@types/react-dom": "^18.2.17",
43
+ "rollup": "^4.6.1",
44
+ "rollup-plugin-copy": "^3.5.0",
45
+ "rollup-plugin-dts": "^6.1.0",
46
+ "typescript": "^5.3.3"
47
+ }
48
+ }
@@ -0,0 +1,103 @@
1
+ import React, { useState, useRef, useEffect } from 'react';
2
+ import { Icon } from './Icons';
3
+
4
+ interface DropdownProps {
5
+ icon: string;
6
+ label: string;
7
+ options: Array<{ value: string; label: string; icon?: string; color?: string; preview?: string; headingPreview?: string }>;
8
+ onSelect: (value: string) => void;
9
+ currentValue?: string;
10
+ disabled?: boolean;
11
+ }
12
+
13
+ export const Dropdown: React.FC<DropdownProps> = ({
14
+ icon,
15
+ label,
16
+ options,
17
+ onSelect,
18
+ currentValue,
19
+ disabled,
20
+ }) => {
21
+ const [isOpen, setIsOpen] = useState(false);
22
+ const dropdownRef = useRef<HTMLDivElement>(null);
23
+
24
+ useEffect(() => {
25
+ const handleClickOutside = (event: MouseEvent) => {
26
+ if (dropdownRef.current && !dropdownRef.current.contains(event.target as Node)) {
27
+ setIsOpen(false);
28
+ }
29
+ };
30
+
31
+ if (isOpen) {
32
+ document.addEventListener('mousedown', handleClickOutside);
33
+ }
34
+
35
+ return () => {
36
+ document.removeEventListener('mousedown', handleClickOutside);
37
+ };
38
+ }, [isOpen]);
39
+
40
+ const handleSelect = (value: string) => {
41
+ onSelect(value);
42
+ setIsOpen(false);
43
+ };
44
+
45
+ const currentOption = options.find(opt => opt.value === currentValue);
46
+
47
+ return (
48
+ <div className="rte-dropdown" ref={dropdownRef}>
49
+ <button
50
+ type="button"
51
+ onClick={() => !disabled && setIsOpen(!isOpen)}
52
+ disabled={disabled}
53
+ className={`rte-toolbar-button rte-dropdown-button ${currentOption ? 'rte-dropdown-button-has-value' : ''}`}
54
+ title={label}
55
+ aria-label={label}
56
+ >
57
+ <Icon icon={icon} width={18} height={18} />
58
+ {currentOption && (
59
+ <span className="rte-dropdown-value">{currentOption.label}</span>
60
+ )}
61
+ </button>
62
+ {isOpen && (
63
+ <div className="rte-dropdown-menu">
64
+ {options.map((option) => (
65
+ <button
66
+ key={option.value}
67
+ type="button"
68
+ className={`rte-dropdown-item ${currentValue === option.value ? 'rte-dropdown-item-active' : ''}`}
69
+ onClick={() => handleSelect(option.value)}
70
+ >
71
+ {option.color && (
72
+ <span
73
+ className={`rte-dropdown-color-preview ${currentValue === option.value ? 'active' : ''}`}
74
+ style={{ backgroundColor: option.color }}
75
+ />
76
+ )}
77
+ {option.preview && !option.headingPreview && (
78
+ <span
79
+ className="rte-dropdown-fontsize-preview"
80
+ style={{ fontSize: `${option.preview}px` }}
81
+ >
82
+ Aa
83
+ </span>
84
+ )}
85
+ {option.headingPreview && (
86
+ <span
87
+ className={`rte-dropdown-heading-preview ${option.headingPreview}`}
88
+ >
89
+ {option.headingPreview === 'p' ? 'Normal' : option.headingPreview.toUpperCase()}
90
+ </span>
91
+ )}
92
+ {option.icon && <Icon icon={option.icon} width={16} height={16} />}
93
+ <span style={{ flex: 1, fontWeight: currentValue === option.value ? 600 : 400 }}>
94
+ {option.label}
95
+ </span>
96
+ </button>
97
+ ))}
98
+ </div>
99
+ )}
100
+ </div>
101
+ );
102
+ };
103
+
@@ -0,0 +1,2 @@
1
+ @import '../styles.css';
2
+