@overlap/rte 0.1.1 → 0.1.2
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/README.md +62 -68
- package/dist/components/Editor.d.ts.map +1 -1
- package/dist/components/Icons.d.ts +3 -1
- package/dist/components/Icons.d.ts.map +1 -1
- package/dist/index.d.ts +59 -45
- package/dist/index.d.ts.map +1 -1
- package/dist/index.esm.js +470 -197
- package/dist/index.esm.js.map +1 -1
- package/dist/index.js +472 -196
- package/dist/index.js.map +1 -1
- package/dist/plugins/blockFormat.d.ts +7 -0
- package/dist/plugins/blockFormat.d.ts.map +1 -0
- package/dist/plugins/headings.d.ts +1 -1
- package/dist/plugins/headings.d.ts.map +1 -1
- package/dist/plugins/index.d.ts +8 -2
- package/dist/plugins/index.d.ts.map +1 -1
- package/dist/plugins/listIndent.d.ts +10 -0
- package/dist/plugins/listIndent.d.ts.map +1 -0
- package/dist/plugins/optional.d.ts +1 -1
- package/dist/plugins/optional.d.ts.map +1 -1
- package/dist/types.d.ts +2 -0
- package/dist/types.d.ts.map +1 -1
- package/package.json +17 -5
- package/src/components/Editor.tsx +92 -49
- package/src/components/Icons.tsx +306 -77
- package/src/index.ts +18 -18
- package/src/plugins/blockFormat.tsx +194 -0
- package/src/plugins/headings.tsx +39 -28
- package/src/plugins/index.tsx +161 -0
- package/src/plugins/listIndent.tsx +90 -0
- package/src/plugins/optional.tsx +216 -194
- package/src/types.ts +3 -0
- package/src/plugins/index.ts +0 -54
package/src/plugins/optional.tsx
CHANGED
|
@@ -1,221 +1,243 @@
|
|
|
1
|
-
import
|
|
2
|
-
import {
|
|
3
|
-
import { IconWrapper } from '../components/IconWrapper';
|
|
1
|
+
import { IconWrapper } from "../components/IconWrapper";
|
|
2
|
+
import { ButtonProps, EditorAPI, Plugin } from "../types";
|
|
4
3
|
|
|
5
4
|
/**
|
|
6
5
|
* Link-Plugin mit verbesserter Funktionalität
|
|
7
6
|
*/
|
|
8
7
|
export function createLinkPlugin(): Plugin {
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
8
|
+
return {
|
|
9
|
+
name: "link",
|
|
10
|
+
type: "inline",
|
|
11
|
+
command: "createLink",
|
|
12
|
+
renderButton: (props: ButtonProps) => (
|
|
13
|
+
<button
|
|
14
|
+
type="button"
|
|
15
|
+
onClick={props.onClick}
|
|
16
|
+
disabled={props.disabled}
|
|
17
|
+
className={`rte-toolbar-button ${
|
|
18
|
+
props.isActive ? "rte-toolbar-button-active" : ""
|
|
19
|
+
}`}
|
|
20
|
+
title="Link einfügen"
|
|
21
|
+
aria-label="Link einfügen"
|
|
22
|
+
>
|
|
23
|
+
<IconWrapper icon="mdi:link" width={18} height={18} />
|
|
24
|
+
</button>
|
|
25
|
+
),
|
|
26
|
+
execute: (editor: EditorAPI) => {
|
|
27
|
+
const selection = editor.getSelection();
|
|
28
|
+
if (!selection || selection.rangeCount === 0) return;
|
|
29
|
+
|
|
30
|
+
const range = selection.getRangeAt(0);
|
|
31
|
+
const container = range.commonAncestorContainer;
|
|
32
|
+
const element =
|
|
33
|
+
container.nodeType === Node.TEXT_NODE
|
|
34
|
+
? container.parentElement
|
|
35
|
+
: (container as HTMLElement);
|
|
36
|
+
|
|
37
|
+
// Prüfe ob bereits ein Link vorhanden ist
|
|
38
|
+
const existingLink = element?.closest("a") as HTMLAnchorElement;
|
|
39
|
+
|
|
40
|
+
if (existingLink) {
|
|
41
|
+
// Link entfernen
|
|
42
|
+
const parent = existingLink.parentNode;
|
|
43
|
+
if (parent) {
|
|
44
|
+
while (existingLink.firstChild) {
|
|
45
|
+
parent.insertBefore(
|
|
46
|
+
existingLink.firstChild,
|
|
47
|
+
existingLink
|
|
48
|
+
);
|
|
49
|
+
}
|
|
50
|
+
parent.removeChild(existingLink);
|
|
51
|
+
// Content aktualisieren
|
|
52
|
+
const editorEl = editor.getSelection()?.anchorNode;
|
|
53
|
+
if (editorEl) {
|
|
54
|
+
const content = editor.getContent();
|
|
55
|
+
editor.setContent(content);
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
} else {
|
|
59
|
+
// Neuen Link einfügen
|
|
60
|
+
const url = prompt("URL eingeben:");
|
|
61
|
+
if (url) {
|
|
62
|
+
editor.executeCommand("createLink", url);
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
},
|
|
66
|
+
isActive: (editor: EditorAPI) => {
|
|
67
|
+
const selection = editor.getSelection();
|
|
68
|
+
if (!selection || selection.rangeCount === 0) return false;
|
|
69
|
+
|
|
70
|
+
const range = selection.getRangeAt(0);
|
|
71
|
+
const container = range.commonAncestorContainer;
|
|
72
|
+
const element =
|
|
73
|
+
container.nodeType === Node.TEXT_NODE
|
|
74
|
+
? container.parentElement
|
|
75
|
+
: (container as HTMLElement);
|
|
76
|
+
|
|
77
|
+
if (!element) return false;
|
|
78
|
+
|
|
79
|
+
return element.closest("a") !== null;
|
|
80
|
+
},
|
|
81
|
+
getCurrentValue: (editor: EditorAPI) => {
|
|
82
|
+
const selection = editor.getSelection();
|
|
83
|
+
if (!selection || selection.rangeCount === 0) return undefined;
|
|
84
|
+
|
|
85
|
+
const range = selection.getRangeAt(0);
|
|
86
|
+
const container = range.commonAncestorContainer;
|
|
87
|
+
const element =
|
|
88
|
+
container.nodeType === Node.TEXT_NODE
|
|
89
|
+
? container.parentElement
|
|
90
|
+
: (container as HTMLElement);
|
|
91
|
+
|
|
92
|
+
if (!element) return undefined;
|
|
93
|
+
|
|
94
|
+
const link = element.closest("a") as HTMLAnchorElement;
|
|
95
|
+
return link ? link.href : undefined;
|
|
96
|
+
},
|
|
97
|
+
canExecute: (editor: EditorAPI) => {
|
|
98
|
+
const selection = editor.getSelection();
|
|
99
|
+
return selection !== null && selection.rangeCount > 0;
|
|
100
|
+
},
|
|
101
|
+
};
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
export const linkPlugin = createLinkPlugin();
|
|
105
|
+
|
|
106
|
+
/**
|
|
107
|
+
* Blockquote-Plugin
|
|
108
|
+
*/
|
|
109
|
+
export const blockquotePlugin: Plugin = {
|
|
110
|
+
name: "blockquote",
|
|
111
|
+
type: "block",
|
|
112
|
+
command: "formatBlock",
|
|
13
113
|
renderButton: (props: ButtonProps) => (
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
114
|
+
<button
|
|
115
|
+
type="button"
|
|
116
|
+
onClick={props.onClick}
|
|
117
|
+
disabled={props.disabled}
|
|
118
|
+
className={`rte-toolbar-button ${
|
|
119
|
+
props.isActive ? "rte-toolbar-button-active" : ""
|
|
120
|
+
}`}
|
|
121
|
+
title="Zitat"
|
|
122
|
+
aria-label="Zitat"
|
|
123
|
+
>
|
|
124
|
+
<IconWrapper icon="mdi:format-quote-close" width={18} height={18} />
|
|
125
|
+
</button>
|
|
24
126
|
),
|
|
25
127
|
execute: (editor: EditorAPI) => {
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
}
|
|
45
|
-
parent.removeChild(existingLink);
|
|
46
|
-
// Content aktualisieren
|
|
47
|
-
const editorEl = editor.getSelection()?.anchorNode;
|
|
48
|
-
if (editorEl) {
|
|
49
|
-
const content = editor.getContent();
|
|
50
|
-
editor.setContent(content);
|
|
51
|
-
}
|
|
52
|
-
}
|
|
53
|
-
} else {
|
|
54
|
-
// Neuen Link einfügen
|
|
55
|
-
const url = prompt('URL eingeben:');
|
|
56
|
-
if (url) {
|
|
57
|
-
editor.executeCommand('createLink', url);
|
|
128
|
+
const selection = editor.getSelection();
|
|
129
|
+
if (!selection || selection.rangeCount === 0) return;
|
|
130
|
+
|
|
131
|
+
const range = selection.getRangeAt(0);
|
|
132
|
+
const container = range.commonAncestorContainer;
|
|
133
|
+
const element =
|
|
134
|
+
container.nodeType === Node.TEXT_NODE
|
|
135
|
+
? container.parentElement
|
|
136
|
+
: (container as HTMLElement);
|
|
137
|
+
|
|
138
|
+
if (!element) return;
|
|
139
|
+
|
|
140
|
+
const isBlockquote = element.closest("blockquote") !== null;
|
|
141
|
+
|
|
142
|
+
if (isBlockquote) {
|
|
143
|
+
editor.executeCommand("formatBlock", "<p>");
|
|
144
|
+
} else {
|
|
145
|
+
editor.executeCommand("formatBlock", "<blockquote>");
|
|
58
146
|
}
|
|
59
|
-
}
|
|
60
147
|
},
|
|
61
148
|
isActive: (editor: EditorAPI) => {
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
getCurrentValue: (editor: EditorAPI) => {
|
|
76
|
-
const selection = editor.getSelection();
|
|
77
|
-
if (!selection || selection.rangeCount === 0) return undefined;
|
|
78
|
-
|
|
79
|
-
const range = selection.getRangeAt(0);
|
|
80
|
-
const container = range.commonAncestorContainer;
|
|
81
|
-
const element = container.nodeType === Node.TEXT_NODE
|
|
82
|
-
? container.parentElement
|
|
83
|
-
: container as HTMLElement;
|
|
84
|
-
|
|
85
|
-
if (!element) return undefined;
|
|
86
|
-
|
|
87
|
-
const link = element.closest('a') as HTMLAnchorElement;
|
|
88
|
-
return link ? link.href : undefined;
|
|
149
|
+
const selection = editor.getSelection();
|
|
150
|
+
if (!selection || selection.rangeCount === 0) return false;
|
|
151
|
+
|
|
152
|
+
const range = selection.getRangeAt(0);
|
|
153
|
+
const container = range.commonAncestorContainer;
|
|
154
|
+
const element =
|
|
155
|
+
container.nodeType === Node.TEXT_NODE
|
|
156
|
+
? container.parentElement
|
|
157
|
+
: (container as HTMLElement);
|
|
158
|
+
|
|
159
|
+
if (!element) return false;
|
|
160
|
+
|
|
161
|
+
return element.closest("blockquote") !== null;
|
|
89
162
|
},
|
|
90
163
|
canExecute: (editor: EditorAPI) => {
|
|
91
|
-
|
|
92
|
-
|
|
164
|
+
const selection = editor.getSelection();
|
|
165
|
+
return selection !== null && selection.rangeCount > 0;
|
|
93
166
|
},
|
|
94
|
-
};
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
export const linkPlugin = createLinkPlugin();
|
|
98
|
-
|
|
99
|
-
/**
|
|
100
|
-
* Blockquote-Plugin
|
|
101
|
-
*/
|
|
102
|
-
export const blockquotePlugin: Plugin = {
|
|
103
|
-
name: 'blockquote',
|
|
104
|
-
type: 'block',
|
|
105
|
-
command: 'formatBlock',
|
|
106
|
-
renderButton: (props: ButtonProps) => (
|
|
107
|
-
<button
|
|
108
|
-
type="button"
|
|
109
|
-
onClick={props.onClick}
|
|
110
|
-
disabled={props.disabled}
|
|
111
|
-
className={`rte-toolbar-button ${props.isActive ? 'rte-toolbar-button-active' : ''}`}
|
|
112
|
-
title="Zitat"
|
|
113
|
-
aria-label="Zitat"
|
|
114
|
-
>
|
|
115
|
-
<IconWrapper icon="mdi:format-quote-close" width={18} height={18} />
|
|
116
|
-
</button>
|
|
117
|
-
),
|
|
118
|
-
execute: (editor: EditorAPI) => {
|
|
119
|
-
const selection = editor.getSelection();
|
|
120
|
-
if (!selection || selection.rangeCount === 0) return;
|
|
121
|
-
|
|
122
|
-
const range = selection.getRangeAt(0);
|
|
123
|
-
const container = range.commonAncestorContainer;
|
|
124
|
-
const element = container.nodeType === Node.TEXT_NODE
|
|
125
|
-
? container.parentElement
|
|
126
|
-
: container as HTMLElement;
|
|
127
|
-
|
|
128
|
-
if (!element) return;
|
|
129
|
-
|
|
130
|
-
const isBlockquote = element.closest('blockquote') !== null;
|
|
131
|
-
|
|
132
|
-
if (isBlockquote) {
|
|
133
|
-
editor.executeCommand('formatBlock', '<p>');
|
|
134
|
-
} else {
|
|
135
|
-
editor.executeCommand('formatBlock', '<blockquote>');
|
|
136
|
-
}
|
|
137
|
-
},
|
|
138
|
-
isActive: (editor: EditorAPI) => {
|
|
139
|
-
const selection = editor.getSelection();
|
|
140
|
-
if (!selection || selection.rangeCount === 0) return false;
|
|
141
|
-
|
|
142
|
-
const range = selection.getRangeAt(0);
|
|
143
|
-
const container = range.commonAncestorContainer;
|
|
144
|
-
const element = container.nodeType === Node.TEXT_NODE
|
|
145
|
-
? container.parentElement
|
|
146
|
-
: container as HTMLElement;
|
|
147
|
-
|
|
148
|
-
if (!element) return false;
|
|
149
|
-
|
|
150
|
-
return element.closest('blockquote') !== null;
|
|
151
|
-
},
|
|
152
|
-
canExecute: (editor: EditorAPI) => {
|
|
153
|
-
const selection = editor.getSelection();
|
|
154
|
-
return selection !== null && selection.rangeCount > 0;
|
|
155
|
-
},
|
|
156
167
|
};
|
|
157
168
|
|
|
158
169
|
/**
|
|
159
170
|
* Unordered List Plugin
|
|
160
171
|
*/
|
|
161
172
|
export const unorderedListPlugin: Plugin = {
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
173
|
+
name: "unorderedList",
|
|
174
|
+
type: "block",
|
|
175
|
+
command: "insertUnorderedList",
|
|
176
|
+
renderButton: (props: ButtonProps) => (
|
|
177
|
+
<button
|
|
178
|
+
type="button"
|
|
179
|
+
onClick={props.onClick}
|
|
180
|
+
disabled={props.disabled}
|
|
181
|
+
className={`rte-toolbar-button ${
|
|
182
|
+
props.isActive ? "rte-toolbar-button-active" : ""
|
|
183
|
+
}`}
|
|
184
|
+
title="Aufzählungsliste"
|
|
185
|
+
aria-label="Aufzählungsliste"
|
|
186
|
+
>
|
|
187
|
+
<IconWrapper
|
|
188
|
+
icon="mdi:format-list-bulleted"
|
|
189
|
+
width={18}
|
|
190
|
+
height={18}
|
|
191
|
+
/>
|
|
192
|
+
</button>
|
|
193
|
+
),
|
|
194
|
+
execute: (editor: EditorAPI) => {
|
|
195
|
+
editor.executeCommand("insertUnorderedList");
|
|
196
|
+
},
|
|
197
|
+
isActive: (editor: EditorAPI) => {
|
|
198
|
+
if (typeof document === "undefined") return false;
|
|
199
|
+
return document.queryCommandState("insertUnorderedList");
|
|
200
|
+
},
|
|
201
|
+
canExecute: (editor: EditorAPI) => {
|
|
202
|
+
const selection = editor.getSelection();
|
|
203
|
+
return selection !== null && selection.rangeCount > 0;
|
|
204
|
+
},
|
|
188
205
|
};
|
|
189
206
|
|
|
190
207
|
/**
|
|
191
208
|
* Ordered List Plugin
|
|
192
209
|
*/
|
|
193
210
|
export const orderedListPlugin: Plugin = {
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
211
|
+
name: "orderedList",
|
|
212
|
+
type: "block",
|
|
213
|
+
command: "insertOrderedList",
|
|
214
|
+
renderButton: (props: ButtonProps) => (
|
|
215
|
+
<button
|
|
216
|
+
type="button"
|
|
217
|
+
onClick={props.onClick}
|
|
218
|
+
disabled={props.disabled}
|
|
219
|
+
className={`rte-toolbar-button ${
|
|
220
|
+
props.isActive ? "rte-toolbar-button-active" : ""
|
|
221
|
+
}`}
|
|
222
|
+
title="Nummerierte Liste"
|
|
223
|
+
aria-label="Nummerierte Liste"
|
|
224
|
+
>
|
|
225
|
+
<IconWrapper
|
|
226
|
+
icon="mdi:format-list-numbered"
|
|
227
|
+
width={18}
|
|
228
|
+
height={18}
|
|
229
|
+
/>
|
|
230
|
+
</button>
|
|
231
|
+
),
|
|
232
|
+
execute: (editor: EditorAPI) => {
|
|
233
|
+
editor.executeCommand("insertOrderedList");
|
|
234
|
+
},
|
|
235
|
+
isActive: (editor: EditorAPI) => {
|
|
236
|
+
if (typeof document === "undefined") return false;
|
|
237
|
+
return document.queryCommandState("insertOrderedList");
|
|
238
|
+
},
|
|
239
|
+
canExecute: (editor: EditorAPI) => {
|
|
240
|
+
const selection = editor.getSelection();
|
|
241
|
+
return selection !== null && selection.rangeCount > 0;
|
|
242
|
+
},
|
|
220
243
|
};
|
|
221
|
-
|
package/src/types.ts
CHANGED
package/src/plugins/index.ts
DELETED
|
@@ -1,54 +0,0 @@
|
|
|
1
|
-
import { Plugin } from '../types';
|
|
2
|
-
import { createInlinePlugin, createCommandPlugin } from './base';
|
|
3
|
-
import { clearFormattingPlugin } from './clearFormatting';
|
|
4
|
-
|
|
5
|
-
/**
|
|
6
|
-
* Standard-Plugins
|
|
7
|
-
*/
|
|
8
|
-
export const boldPlugin: Plugin = createInlinePlugin(
|
|
9
|
-
'bold',
|
|
10
|
-
'bold',
|
|
11
|
-
'mdi:format-bold',
|
|
12
|
-
'Fett'
|
|
13
|
-
);
|
|
14
|
-
|
|
15
|
-
export const italicPlugin: Plugin = createInlinePlugin(
|
|
16
|
-
'italic',
|
|
17
|
-
'italic',
|
|
18
|
-
'mdi:format-italic',
|
|
19
|
-
'Kursiv'
|
|
20
|
-
);
|
|
21
|
-
|
|
22
|
-
export const underlinePlugin: Plugin = createInlinePlugin(
|
|
23
|
-
'underline',
|
|
24
|
-
'underline',
|
|
25
|
-
'mdi:format-underline',
|
|
26
|
-
'Unterstrichen'
|
|
27
|
-
);
|
|
28
|
-
|
|
29
|
-
export const undoPlugin: Plugin = createCommandPlugin(
|
|
30
|
-
'undo',
|
|
31
|
-
'undo',
|
|
32
|
-
'mdi:undo',
|
|
33
|
-
'Rückgängig'
|
|
34
|
-
);
|
|
35
|
-
|
|
36
|
-
export const redoPlugin: Plugin = createCommandPlugin(
|
|
37
|
-
'redo',
|
|
38
|
-
'redo',
|
|
39
|
-
'mdi:redo',
|
|
40
|
-
'Wiederholen'
|
|
41
|
-
);
|
|
42
|
-
|
|
43
|
-
/**
|
|
44
|
-
* Standard-Plugin-Liste
|
|
45
|
-
*/
|
|
46
|
-
export const defaultPlugins: Plugin[] = [
|
|
47
|
-
undoPlugin,
|
|
48
|
-
redoPlugin,
|
|
49
|
-
boldPlugin,
|
|
50
|
-
italicPlugin,
|
|
51
|
-
underlinePlugin,
|
|
52
|
-
clearFormattingPlugin,
|
|
53
|
-
];
|
|
54
|
-
|