@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
package/src/styles.css ADDED
@@ -0,0 +1,638 @@
1
+ /* CSS Variables für Theme-Support */
2
+ :root {
3
+ /* Colors */
4
+ --rte-border-color: #e5e7eb;
5
+ --rte-border-radius: 8px;
6
+ --rte-toolbar-bg: #f9fafb;
7
+ --rte-button-hover-bg: #f3f4f6;
8
+ --rte-button-active-bg: #e5e7eb;
9
+ --rte-content-bg: #ffffff;
10
+ --rte-text-color: #111827;
11
+ --rte-text-secondary: #6b7280;
12
+ --rte-primary-color: #3b82f6;
13
+ --rte-primary-hover: #2563eb;
14
+
15
+ /* Spacing */
16
+ --rte-padding-xs: 4px;
17
+ --rte-padding-sm: 6px;
18
+ --rte-padding-md: 8px;
19
+ --rte-padding-lg: 12px;
20
+ --rte-padding-xl: 16px;
21
+ --rte-padding-2xl: 20px;
22
+
23
+ /* Shadows */
24
+ --rte-shadow-sm: 0 1px 2px 0 rgba(0, 0, 0, 0.05);
25
+ --rte-shadow-md: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06);
26
+ --rte-shadow-lg: 0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -2px rgba(0, 0, 0, 0.05);
27
+ --rte-shadow-popover: 0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -2px rgba(0, 0, 0, 0.05);
28
+
29
+ /* Typography */
30
+ --rte-font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', sans-serif;
31
+ --rte-line-height: 1.6;
32
+ }
33
+
34
+ /* Container */
35
+ .rte-container {
36
+ display: flex;
37
+ flex-direction: column;
38
+ border: 1px solid var(--rte-border-color);
39
+ border-radius: var(--rte-border-radius);
40
+ background: var(--rte-content-bg);
41
+ font-family: var(--rte-font-family);
42
+ box-shadow: var(--rte-shadow-sm);
43
+ }
44
+
45
+ /* Toolbar */
46
+ .rte-toolbar {
47
+ display: flex;
48
+ justify-content: space-between;
49
+ align-items: center;
50
+ gap: var(--rte-padding-md);
51
+ padding: var(--rte-padding-md);
52
+ background: var(--rte-toolbar-bg);
53
+ border-bottom: 1px solid var(--rte-border-color);
54
+ border-top-left-radius: var(--rte-border-radius);
55
+ border-top-right-radius: var(--rte-border-radius);
56
+ }
57
+
58
+ /* Sticky Toolbar */
59
+ .rte-toolbar-sticky {
60
+ position: sticky;
61
+ top: 0;
62
+ z-index: 10;
63
+ box-shadow: var(--rte-shadow-sm);
64
+ transition: box-shadow 0.2s ease;
65
+ }
66
+
67
+ .rte-toolbar-left {
68
+ display: flex;
69
+ gap: var(--rte-padding-xs);
70
+ flex-wrap: wrap;
71
+ align-items: center;
72
+ flex: 1;
73
+ }
74
+
75
+ .rte-toolbar-right {
76
+ display: flex;
77
+ gap: var(--rte-padding-xs);
78
+ align-items: center;
79
+ flex-shrink: 0;
80
+ }
81
+
82
+ /* Toolbar Divider */
83
+ .rte-toolbar-divider {
84
+ width: 1px;
85
+ height: 24px;
86
+ background: var(--rte-border-color);
87
+ margin: 0 var(--rte-padding-sm);
88
+ flex-shrink: 0;
89
+ }
90
+
91
+ /* Toolbar Buttons - Ghost/Subtle Style */
92
+ .rte-toolbar-button {
93
+ display: flex;
94
+ align-items: center;
95
+ justify-content: center;
96
+ min-width: 32px;
97
+ height: 32px;
98
+ padding: 0 var(--rte-padding-md);
99
+ border: none;
100
+ background: transparent;
101
+ border-radius: 6px;
102
+ cursor: pointer;
103
+ color: var(--rte-text-color);
104
+ transition: all 0.15s ease;
105
+ font-size: 14px;
106
+ }
107
+
108
+ .rte-toolbar-button:hover:not(:disabled) {
109
+ background: var(--rte-button-hover-bg);
110
+ color: var(--rte-text-color);
111
+ }
112
+
113
+ .rte-toolbar-button:active:not(:disabled) {
114
+ background: var(--rte-button-active-bg);
115
+ transform: scale(0.98);
116
+ }
117
+
118
+ .rte-toolbar-button:disabled {
119
+ opacity: 0.4;
120
+ cursor: not-allowed;
121
+ }
122
+
123
+ .rte-toolbar-button-active {
124
+ background: var(--rte-button-active-bg);
125
+ color: var(--rte-primary-color);
126
+ }
127
+
128
+ .rte-toolbar-button-active:hover:not(:disabled) {
129
+ background: var(--rte-button-hover-bg);
130
+ color: var(--rte-primary-hover);
131
+ }
132
+
133
+ /* Editor Content Area */
134
+ .rte-editor {
135
+ min-height: 200px;
136
+ padding: var(--rte-padding-2xl);
137
+ outline: none;
138
+ line-height: var(--rte-line-height);
139
+ color: var(--rte-text-color);
140
+ overflow-y: auto;
141
+ background: var(--rte-content-bg);
142
+ border-bottom-left-radius: var(--rte-border-radius);
143
+ border-bottom-right-radius: var(--rte-border-radius);
144
+ }
145
+
146
+ .rte-editor:focus {
147
+ outline: none;
148
+ }
149
+
150
+ .rte-editor:empty:before {
151
+ content: attr(data-placeholder);
152
+ color: var(--rte-text-secondary);
153
+ pointer-events: none;
154
+ }
155
+
156
+ /* Typography in Editor */
157
+ .rte-editor p {
158
+ margin: 0 0 var(--rte-padding-lg) 0;
159
+ }
160
+
161
+ .rte-editor p:last-child {
162
+ margin-bottom: 0;
163
+ }
164
+
165
+ .rte-editor h1 {
166
+ font-size: 2em;
167
+ font-weight: 700;
168
+ margin: 0 0 var(--rte-padding-lg) 0;
169
+ line-height: 1.2;
170
+ }
171
+
172
+ .rte-editor h2 {
173
+ font-size: 1.5em;
174
+ font-weight: 600;
175
+ margin: 0 0 var(--rte-padding-lg) 0;
176
+ line-height: 1.3;
177
+ }
178
+
179
+ .rte-editor h3 {
180
+ font-size: 1.25em;
181
+ font-weight: 600;
182
+ margin: 0 0 var(--rte-padding-lg) 0;
183
+ line-height: 1.4;
184
+ }
185
+
186
+ .rte-editor h4 {
187
+ font-size: 1.1em;
188
+ font-weight: 600;
189
+ margin: 0 0 var(--rte-padding-lg) 0;
190
+ line-height: 1.4;
191
+ }
192
+
193
+ .rte-editor h5 {
194
+ font-size: 1em;
195
+ font-weight: 600;
196
+ margin: 0 0 var(--rte-padding-lg) 0;
197
+ line-height: 1.5;
198
+ }
199
+
200
+ .rte-editor h6 {
201
+ font-size: 0.9em;
202
+ font-weight: 600;
203
+ margin: 0 0 var(--rte-padding-lg) 0;
204
+ line-height: 1.5;
205
+ }
206
+
207
+ .rte-editor blockquote {
208
+ margin: 0 0 var(--rte-padding-lg) 0;
209
+ padding: var(--rte-padding-lg) var(--rte-padding-xl);
210
+ border-left: 3px solid var(--rte-border-color);
211
+ background: var(--rte-toolbar-bg);
212
+ color: var(--rte-text-secondary);
213
+ border-radius: 0 var(--rte-border-radius) var(--rte-border-radius) 0;
214
+ }
215
+
216
+ .rte-editor ul,
217
+ .rte-editor ol {
218
+ margin: 0 0 var(--rte-padding-lg) 0;
219
+ padding-left: var(--rte-padding-2xl);
220
+ }
221
+
222
+ .rte-editor li {
223
+ margin: var(--rte-padding-sm) 0;
224
+ }
225
+
226
+ .rte-editor a {
227
+ color: var(--rte-primary-color);
228
+ text-decoration: underline;
229
+ text-underline-offset: 2px;
230
+ transition: color 0.15s ease;
231
+ }
232
+
233
+ .rte-editor a:hover {
234
+ color: var(--rte-primary-hover);
235
+ }
236
+
237
+ .rte-editor strong,
238
+ .rte-editor b {
239
+ font-weight: 600;
240
+ }
241
+
242
+ .rte-editor em,
243
+ .rte-editor i {
244
+ font-style: italic;
245
+ }
246
+
247
+ .rte-editor u {
248
+ text-decoration: underline;
249
+ text-underline-offset: 2px;
250
+ }
251
+
252
+ /* Dropdown Styles */
253
+ .rte-dropdown {
254
+ position: relative;
255
+ display: inline-block;
256
+ }
257
+
258
+ .rte-dropdown-button {
259
+ min-width: 32px;
260
+ width: auto;
261
+ padding: 0 var(--rte-padding-md);
262
+ }
263
+
264
+ .rte-dropdown-button-has-value {
265
+ padding: 0 var(--rte-padding-lg);
266
+ }
267
+
268
+ .rte-dropdown-value {
269
+ margin-left: var(--rte-padding-sm);
270
+ font-size: 12px;
271
+ font-weight: 500;
272
+ color: var(--rte-text-color);
273
+ }
274
+
275
+ /* Dropdown Menu - Modern Popover */
276
+ .rte-dropdown-menu {
277
+ position: absolute;
278
+ top: calc(100% + 4px);
279
+ left: 0;
280
+ background: var(--rte-content-bg);
281
+ border: 1px solid var(--rte-border-color);
282
+ border-radius: var(--rte-border-radius);
283
+ box-shadow: var(--rte-shadow-popover);
284
+ z-index: 1000;
285
+ min-width: 180px;
286
+ max-height: 320px;
287
+ overflow-y: auto;
288
+ padding: var(--rte-padding-sm);
289
+ margin-top: var(--rte-padding-xs);
290
+ }
291
+
292
+ .rte-dropdown-item {
293
+ display: flex;
294
+ align-items: center;
295
+ gap: var(--rte-padding-md);
296
+ width: 100%;
297
+ padding: var(--rte-padding-md) var(--rte-padding-lg);
298
+ border: none;
299
+ background: transparent;
300
+ text-align: left;
301
+ cursor: pointer;
302
+ color: var(--rte-text-color);
303
+ font-size: 14px;
304
+ border-radius: 6px;
305
+ transition: all 0.15s ease;
306
+ font-family: var(--rte-font-family);
307
+ position: relative;
308
+ }
309
+
310
+ .rte-dropdown-item:hover {
311
+ background: var(--rte-button-hover-bg);
312
+ }
313
+
314
+ .rte-dropdown-item-active {
315
+ background: var(--rte-button-hover-bg);
316
+ color: var(--rte-text-color);
317
+ font-weight: 500;
318
+ }
319
+
320
+ .rte-dropdown-item-active::before {
321
+ content: '';
322
+ position: absolute;
323
+ left: 0;
324
+ top: 0;
325
+ bottom: 0;
326
+ width: 3px;
327
+ background: var(--rte-primary-color);
328
+ border-radius: 0 2px 2px 0;
329
+ }
330
+
331
+ .rte-dropdown-item-active .rte-dropdown-heading-preview,
332
+ .rte-dropdown-item-active > span:last-child {
333
+ color: var(--rte-primary-color);
334
+ font-weight: 600;
335
+ }
336
+
337
+ .rte-dropdown-color-preview.active {
338
+ border: 2px solid var(--rte-primary-color);
339
+ box-shadow: 0 0 0 2px rgba(59, 130, 246, 0.2);
340
+ }
341
+
342
+ /* Color Preview in Dropdown */
343
+ .rte-dropdown-color-preview {
344
+ display: inline-block;
345
+ width: 20px;
346
+ height: 20px;
347
+ border-radius: 4px;
348
+ border: 1px solid var(--rte-border-color);
349
+ flex-shrink: 0;
350
+ box-shadow: var(--rte-shadow-sm);
351
+ }
352
+
353
+ /* Font Size Preview in Dropdown */
354
+ .rte-dropdown-fontsize-preview {
355
+ display: inline-block;
356
+ min-width: 40px;
357
+ text-align: right;
358
+ font-weight: 500;
359
+ color: var(--rte-text-secondary);
360
+ }
361
+
362
+ /* Heading Preview in Dropdown */
363
+ .rte-dropdown-heading-preview {
364
+ display: inline-flex;
365
+ align-items: center;
366
+ min-width: 60px;
367
+ font-weight: 600;
368
+ color: var(--rte-text-color);
369
+ font-size: 14px;
370
+ line-height: 1.2;
371
+ }
372
+
373
+ .rte-dropdown-heading-preview.h1 {
374
+ font-size: 18px;
375
+ font-weight: 700;
376
+ }
377
+
378
+ .rte-dropdown-heading-preview.h2 {
379
+ font-size: 16px;
380
+ font-weight: 600;
381
+ }
382
+
383
+ .rte-dropdown-heading-preview.h3 {
384
+ font-size: 15px;
385
+ font-weight: 600;
386
+ }
387
+
388
+ .rte-dropdown-heading-preview.h4 {
389
+ font-size: 14px;
390
+ font-weight: 600;
391
+ }
392
+
393
+ .rte-dropdown-heading-preview.h5 {
394
+ font-size: 13px;
395
+ font-weight: 600;
396
+ }
397
+
398
+ .rte-dropdown-heading-preview.h6 {
399
+ font-size: 12px;
400
+ font-weight: 600;
401
+ }
402
+
403
+ .rte-dropdown-heading-preview.p {
404
+ font-size: 14px;
405
+ font-weight: 400;
406
+ }
407
+
408
+ /* Image Styles in Editor */
409
+ .rte-editor img {
410
+ max-width: 100%;
411
+ height: auto;
412
+ display: block;
413
+ margin: var(--rte-padding-xl) 0;
414
+ border-radius: var(--rte-border-radius);
415
+ box-shadow: var(--rte-shadow-sm);
416
+ }
417
+
418
+ .rte-editor img[data-uploading="true"] {
419
+ opacity: 0.6;
420
+ position: relative;
421
+ }
422
+
423
+ .rte-editor img[data-uploading="true"]::after {
424
+ content: '';
425
+ position: absolute;
426
+ top: 50%;
427
+ left: 50%;
428
+ transform: translate(-50%, -50%);
429
+ width: 24px;
430
+ height: 24px;
431
+ border: 2px solid var(--rte-primary-color);
432
+ border-top-color: transparent;
433
+ border-radius: 50%;
434
+ animation: spin 0.8s linear infinite;
435
+ }
436
+
437
+ @keyframes spin {
438
+ to {
439
+ transform: translate(-50%, -50%) rotate(360deg);
440
+ }
441
+ }
442
+
443
+ /* Image Modal */
444
+ .rte-image-modal-overlay {
445
+ position: fixed;
446
+ top: 0;
447
+ left: 0;
448
+ right: 0;
449
+ bottom: 0;
450
+ background: rgba(0, 0, 0, 0.5);
451
+ display: flex;
452
+ align-items: center;
453
+ justify-content: center;
454
+ z-index: 10000;
455
+ padding: var(--rte-padding-xl);
456
+ }
457
+
458
+ .rte-image-modal {
459
+ background: var(--rte-content-bg);
460
+ border-radius: var(--rte-border-radius);
461
+ box-shadow: var(--rte-shadow-lg);
462
+ width: 100%;
463
+ max-width: 500px;
464
+ max-height: 90vh;
465
+ overflow-y: auto;
466
+ display: flex;
467
+ flex-direction: column;
468
+ }
469
+
470
+ .rte-image-modal-header {
471
+ display: flex;
472
+ align-items: center;
473
+ justify-content: space-between;
474
+ padding: var(--rte-padding-xl);
475
+ border-bottom: 1px solid var(--rte-border-color);
476
+ }
477
+
478
+ .rte-image-modal-header h3 {
479
+ margin: 0;
480
+ font-size: 18px;
481
+ font-weight: 600;
482
+ color: var(--rte-text-color);
483
+ }
484
+
485
+ .rte-image-modal-close {
486
+ display: flex;
487
+ align-items: center;
488
+ justify-content: center;
489
+ width: 32px;
490
+ height: 32px;
491
+ border: none;
492
+ background: transparent;
493
+ border-radius: 6px;
494
+ cursor: pointer;
495
+ color: var(--rte-text-secondary);
496
+ transition: all 0.15s ease;
497
+ }
498
+
499
+ .rte-image-modal-close:hover {
500
+ background: var(--rte-button-hover-bg);
501
+ color: var(--rte-text-color);
502
+ }
503
+
504
+ .rte-image-modal-content {
505
+ padding: var(--rte-padding-xl);
506
+ display: flex;
507
+ flex-direction: column;
508
+ gap: var(--rte-padding-xl);
509
+ }
510
+
511
+ .rte-image-upload-section {
512
+ display: flex;
513
+ flex-direction: column;
514
+ gap: var(--rte-padding-md);
515
+ }
516
+
517
+ .rte-image-upload-label {
518
+ display: block;
519
+ cursor: pointer;
520
+ }
521
+
522
+ .rte-image-upload-button {
523
+ display: flex;
524
+ align-items: center;
525
+ justify-content: center;
526
+ gap: var(--rte-padding-md);
527
+ padding: var(--rte-padding-xl);
528
+ border: 2px dashed var(--rte-border-color);
529
+ border-radius: var(--rte-border-radius);
530
+ background: var(--rte-toolbar-bg);
531
+ color: var(--rte-text-color);
532
+ transition: all 0.15s ease;
533
+ font-size: 14px;
534
+ font-weight: 500;
535
+ }
536
+
537
+ .rte-image-upload-button:hover {
538
+ border-color: var(--rte-primary-color);
539
+ background: var(--rte-button-hover-bg);
540
+ }
541
+
542
+ .rte-image-url-section,
543
+ .rte-image-alt-section {
544
+ display: flex;
545
+ flex-direction: column;
546
+ gap: var(--rte-padding-sm);
547
+ }
548
+
549
+ .rte-image-url-section label,
550
+ .rte-image-alt-section label {
551
+ font-size: 14px;
552
+ font-weight: 500;
553
+ color: var(--rte-text-color);
554
+ }
555
+
556
+ .rte-image-url-input,
557
+ .rte-image-alt-input {
558
+ width: 100%;
559
+ padding: var(--rte-padding-md) var(--rte-padding-lg);
560
+ border: 1px solid var(--rte-border-color);
561
+ border-radius: 6px;
562
+ font-size: 14px;
563
+ font-family: var(--rte-font-family);
564
+ color: var(--rte-text-color);
565
+ background: var(--rte-content-bg);
566
+ transition: all 0.15s ease;
567
+ }
568
+
569
+ .rte-image-url-input:focus,
570
+ .rte-image-alt-input:focus {
571
+ outline: none;
572
+ border-color: var(--rte-primary-color);
573
+ box-shadow: 0 0 0 3px rgba(59, 130, 246, 0.1);
574
+ }
575
+
576
+ .rte-image-preview {
577
+ display: flex;
578
+ justify-content: center;
579
+ padding: var(--rte-padding-lg);
580
+ background: var(--rte-toolbar-bg);
581
+ border-radius: var(--rte-border-radius);
582
+ }
583
+
584
+ .rte-image-preview img {
585
+ max-width: 100%;
586
+ max-height: 200px;
587
+ border-radius: var(--rte-border-radius);
588
+ box-shadow: var(--rte-shadow-sm);
589
+ }
590
+
591
+ .rte-image-modal-footer {
592
+ display: flex;
593
+ align-items: center;
594
+ justify-content: flex-end;
595
+ gap: var(--rte-padding-md);
596
+ padding: var(--rte-padding-xl);
597
+ border-top: 1px solid var(--rte-border-color);
598
+ }
599
+
600
+ .rte-image-modal-cancel,
601
+ .rte-image-modal-insert {
602
+ padding: var(--rte-padding-md) var(--rte-padding-xl);
603
+ border: none;
604
+ border-radius: 6px;
605
+ font-size: 14px;
606
+ font-weight: 500;
607
+ cursor: pointer;
608
+ transition: all 0.15s ease;
609
+ font-family: var(--rte-font-family);
610
+ }
611
+
612
+ .rte-image-modal-cancel {
613
+ background: transparent;
614
+ color: var(--rte-text-secondary);
615
+ }
616
+
617
+ .rte-image-modal-cancel:hover {
618
+ background: var(--rte-button-hover-bg);
619
+ color: var(--rte-text-color);
620
+ }
621
+
622
+ .rte-image-modal-insert {
623
+ background: var(--rte-primary-color);
624
+ color: white;
625
+ }
626
+
627
+ .rte-image-modal-insert:hover:not(:disabled) {
628
+ background: var(--rte-primary-hover);
629
+ }
630
+
631
+ .rte-image-modal-insert:disabled {
632
+ opacity: 0.5;
633
+ cursor: not-allowed;
634
+ }
635
+
636
+ .rte-spin {
637
+ animation: spin 0.8s linear infinite;
638
+ }
package/src/types.ts ADDED
@@ -0,0 +1,92 @@
1
+ export interface EditorNode {
2
+ type: string;
3
+ children?: EditorNode[];
4
+ text?: string;
5
+ attributes?: Record<string, string>;
6
+ }
7
+
8
+ export interface EditorContent {
9
+ blocks: EditorNode[];
10
+ }
11
+
12
+ export interface Plugin {
13
+ name: string;
14
+ type: 'inline' | 'block' | 'command';
15
+ command?: string;
16
+ renderButton?: (props: ButtonProps & { [key: string]: any }) => React.ReactElement;
17
+ execute?: (editor: EditorAPI, value?: string) => void;
18
+ isActive?: (editor: EditorAPI) => boolean;
19
+ canExecute?: (editor: EditorAPI) => boolean;
20
+ // State Reflection: Gibt den aktuellen Wert zurück (z.B. "22" für fontSize, "#ff0000" für color, "h1" für heading)
21
+ getCurrentValue?: (editor: EditorAPI) => string | undefined;
22
+ }
23
+
24
+ export interface ButtonProps {
25
+ isActive: boolean;
26
+ onClick: () => void;
27
+ disabled?: boolean;
28
+ icon?: string;
29
+ label?: string;
30
+ }
31
+
32
+ export interface EditorAPI {
33
+ executeCommand: (command: string, value?: string) => boolean;
34
+ getSelection: () => Selection | null;
35
+ getContent: () => EditorContent;
36
+ setContent: (content: EditorContent) => void;
37
+ insertBlock: (type: string, attributes?: Record<string, string>) => void;
38
+ insertInline: (type: string, attributes?: Record<string, string>) => void;
39
+ undo: () => void;
40
+ redo: () => void;
41
+ canUndo: () => boolean;
42
+ canRedo: () => boolean;
43
+ // HTML Import & Export
44
+ importHtml: (htmlString: string) => EditorContent;
45
+ exportHtml: () => string;
46
+ // Clear Formatting
47
+ clearFormatting: () => void;
48
+ clearTextColor: () => void;
49
+ clearBackgroundColor: () => void;
50
+ clearFontSize: () => void;
51
+ clearLinks: () => void;
52
+ }
53
+
54
+ export interface CustomRenderer {
55
+ renderNode?: (node: EditorNode, children: React.ReactNode) => React.ReactElement | null;
56
+ renderMark?: (mark: string, attributes: Record<string, string>, children: React.ReactNode) => React.ReactElement | null;
57
+ }
58
+
59
+ export interface EditorProps {
60
+ initialContent?: EditorContent;
61
+ onChange?: (content: EditorContent) => void;
62
+ plugins?: Plugin[];
63
+ placeholder?: string;
64
+ className?: string;
65
+ toolbarClassName?: string;
66
+ editorClassName?: string;
67
+ // Link System
68
+ customLinkComponent?: React.ComponentType<{ href: string; children: React.ReactNode; [key: string]: any }>;
69
+ // Font Size System
70
+ fontSizes?: number[];
71
+ // Color System
72
+ colors?: string[];
73
+ // Headings System
74
+ headings?: string[];
75
+ customHeadingRenderer?: (level: string, children: React.ReactNode) => React.ReactElement;
76
+ // Custom Renderer
77
+ customRenderer?: CustomRenderer;
78
+ // Editor API Callback
79
+ onEditorAPIReady?: (api: EditorAPI) => void;
80
+ // Theme Configuration
81
+ theme?: {
82
+ borderColor?: string;
83
+ borderRadius?: number;
84
+ toolbarBg?: string;
85
+ buttonHoverBg?: string;
86
+ contentBg?: string;
87
+ primaryColor?: string;
88
+ };
89
+ // Image Upload
90
+ onImageUpload?: (file: File) => Promise<string>;
91
+ }
92
+