@react-email/editor 0.0.0-experimental.2 → 0.0.0-experimental.20

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,750 @@
1
+ /* Default theme for @react-email/editor bubble menu primitives.
2
+ *
3
+ * Opt-in: import '@react-email/editor/themes/default.css';
4
+ *
5
+ * Override any variable on a parent element:
6
+ * .my-editor { --re-bg: #1a1a1a; --re-border: #333; }
7
+ */
8
+
9
+ /* Layer 0: layout (inlined at build time via postcss-import) */
10
+
11
+ /* Minimal functional styles for BubbleMenu compound components.
12
+ * This file handles layout and positioning only - no visual design.
13
+ * Import this optionally: import '@react-email/editor/styles/bubble-menu.css';
14
+ */
15
+
16
+ [data-re-bubble-menu] {
17
+ display: flex;
18
+ align-items: center;
19
+ gap: 0.125rem;
20
+ }
21
+
22
+ [data-re-bubble-menu-group] {
23
+ display: flex;
24
+ align-items: center;
25
+ gap: 0.125rem;
26
+ padding: 0 0.125rem;
27
+ border: none;
28
+ margin: 0;
29
+ min-width: 0;
30
+ }
31
+
32
+ [data-re-bubble-menu-separator] {
33
+ align-self: stretch;
34
+ width: 1px;
35
+ margin: 0.25rem 0;
36
+ }
37
+
38
+ [data-re-bubble-menu-item] {
39
+ display: inline-flex;
40
+ align-items: center;
41
+ justify-content: center;
42
+ cursor: pointer;
43
+ border: none;
44
+ background: none;
45
+ padding: 0.375rem;
46
+ }
47
+
48
+ [data-re-bubble-menu-item] svg {
49
+ width: 0.875rem;
50
+ height: 0.875rem;
51
+ }
52
+
53
+ [data-re-node-selector] {
54
+ position: relative;
55
+ }
56
+
57
+ [data-re-node-selector-trigger] {
58
+ display: flex;
59
+ align-items: center;
60
+ gap: 0.25rem;
61
+ cursor: pointer;
62
+ border: none;
63
+ background: none;
64
+ white-space: nowrap;
65
+ font-size: 0.8125rem;
66
+ padding: 0.375rem 0.5rem;
67
+ }
68
+
69
+ [data-re-node-selector-trigger] svg {
70
+ width: 0.75rem;
71
+ height: 0.75rem;
72
+ opacity: 0.5;
73
+ }
74
+
75
+ [data-re-node-selector-content] {
76
+ display: flex;
77
+ flex-direction: column;
78
+ min-width: 10rem;
79
+ }
80
+
81
+ [data-re-node-selector-item] {
82
+ display: flex;
83
+ align-items: center;
84
+ gap: 0.5rem;
85
+ cursor: pointer;
86
+ border: none;
87
+ background: none;
88
+ padding: 0.375rem 0.5rem;
89
+ font-size: 0.8125rem;
90
+ width: 100%;
91
+ text-align: left;
92
+ }
93
+
94
+ [data-re-node-selector-item] svg {
95
+ width: 0.875rem;
96
+ height: 0.875rem;
97
+ }
98
+
99
+ [data-re-link-selector] {
100
+ display: flex;
101
+ position: relative;
102
+ }
103
+
104
+ [data-re-link-selector-trigger] {
105
+ display: inline-flex;
106
+ align-items: center;
107
+ justify-content: center;
108
+ cursor: pointer;
109
+ border: none;
110
+ background: none;
111
+ padding: 0.375rem;
112
+ }
113
+
114
+ [data-re-link-selector-trigger] svg {
115
+ width: 0.875rem;
116
+ height: 0.875rem;
117
+ }
118
+
119
+ [data-re-link-selector-form] {
120
+ display: flex;
121
+ align-items: center;
122
+ gap: 0.25rem;
123
+ position: absolute;
124
+ top: 100%;
125
+ left: 0;
126
+ margin-top: 0.25rem;
127
+ width: max-content;
128
+ min-width: 16rem;
129
+ padding: 0.25rem;
130
+ }
131
+
132
+ [data-re-link-selector-input] {
133
+ flex: 1;
134
+ border: none;
135
+ outline: none;
136
+ font-size: 0.8125rem;
137
+ padding: 0.25rem;
138
+ background: transparent;
139
+ }
140
+
141
+ [data-re-link-selector-apply],
142
+ [data-re-link-selector-unlink] {
143
+ display: inline-flex;
144
+ align-items: center;
145
+ justify-content: center;
146
+ cursor: pointer;
147
+ border: none;
148
+ background: none;
149
+ padding: 0.25rem;
150
+ }
151
+
152
+ [data-re-link-selector-apply] svg,
153
+ [data-re-link-selector-unlink] svg {
154
+ width: 0.875rem;
155
+ height: 0.875rem;
156
+ }
157
+
158
+ /* Minimal functional styles for LinkBubbleMenu compound components.
159
+ * Layout and positioning only - no visual design.
160
+ * Import optionally: import '@react-email/editor/styles/link-bubble-menu.css';
161
+ */
162
+
163
+ [data-re-link-bm] {
164
+ display: flex;
165
+ align-items: center;
166
+ }
167
+
168
+ [data-re-link-bm-toolbar] {
169
+ display: flex;
170
+ align-items: center;
171
+ }
172
+
173
+ [data-re-link-bm-item] {
174
+ display: inline-flex;
175
+ align-items: center;
176
+ justify-content: center;
177
+ cursor: pointer;
178
+ border: none;
179
+ background: none;
180
+ padding: 0.5rem;
181
+ }
182
+
183
+ [data-re-link-bm-item] svg {
184
+ width: 1rem;
185
+ height: 1rem;
186
+ }
187
+
188
+ a[data-re-link-bm-item] {
189
+ text-decoration: none;
190
+ color: inherit;
191
+ }
192
+
193
+ [data-re-link-bm-form] {
194
+ display: flex;
195
+ align-items: center;
196
+ gap: 0.25rem;
197
+ }
198
+
199
+ [data-re-link-bm-input] {
200
+ flex: 1;
201
+ border: none;
202
+ outline: none;
203
+ font-size: 0.875rem;
204
+ padding: 0.25rem;
205
+ background: transparent;
206
+ }
207
+
208
+ [data-re-link-bm-apply],
209
+ [data-re-link-bm-unlink] {
210
+ display: inline-flex;
211
+ align-items: center;
212
+ justify-content: center;
213
+ cursor: pointer;
214
+ border: none;
215
+ background: none;
216
+ padding: 0.25rem;
217
+ }
218
+
219
+ [data-re-link-bm-apply] svg,
220
+ [data-re-link-bm-unlink] svg {
221
+ width: 1rem;
222
+ height: 1rem;
223
+ }
224
+
225
+ /* Minimal functional styles for ButtonBubbleMenu compound components.
226
+ * Layout and positioning only - no visual design.
227
+ * Import optionally: import '@react-email/editor/styles/button-bubble-menu.css';
228
+ */
229
+
230
+ [data-re-btn-bm] {
231
+ display: flex;
232
+ align-items: center;
233
+ }
234
+
235
+ [data-re-btn-bm-toolbar] {
236
+ display: flex;
237
+ align-items: center;
238
+ }
239
+
240
+ [data-re-btn-bm-item] {
241
+ display: inline-flex;
242
+ align-items: center;
243
+ justify-content: center;
244
+ cursor: pointer;
245
+ border: none;
246
+ background: none;
247
+ padding: 0.5rem;
248
+ }
249
+
250
+ [data-re-btn-bm-item] svg {
251
+ width: 1rem;
252
+ height: 1rem;
253
+ }
254
+
255
+ /* Minimal functional styles for ImageBubbleMenu compound components.
256
+ * Layout and positioning only - no visual design.
257
+ * Import optionally: import '@react-email/editor/styles/image-bubble-menu.css';
258
+ */
259
+
260
+ [data-re-img-bm] {
261
+ display: flex;
262
+ align-items: center;
263
+ }
264
+
265
+ [data-re-img-bm-toolbar] {
266
+ display: flex;
267
+ align-items: center;
268
+ }
269
+
270
+ [data-re-img-bm-item] {
271
+ display: inline-flex;
272
+ align-items: center;
273
+ justify-content: center;
274
+ cursor: pointer;
275
+ border: none;
276
+ background: none;
277
+ padding: 0.5rem;
278
+ }
279
+
280
+ [data-re-img-bm-item] svg {
281
+ width: 1rem;
282
+ height: 1rem;
283
+ }
284
+
285
+ /* Minimal functional styles for SlashCommand components.
286
+ * Layout and positioning only - no visual design.
287
+ * Import optionally: import '@react-email/editor/styles/slash-command.css';
288
+ */
289
+
290
+ [data-re-slash-command] {
291
+ max-height: 330px;
292
+ overflow-y: auto;
293
+ width: 256px;
294
+ padding: 0.25rem;
295
+ }
296
+
297
+ [data-re-slash-command-item] {
298
+ display: flex;
299
+ align-items: center;
300
+ gap: 0.5rem;
301
+ width: 100%;
302
+ padding: 0.375rem 0.5rem;
303
+ border: none;
304
+ border-radius: 0.375rem;
305
+ background: none;
306
+ cursor: pointer;
307
+ font-size: 0.875rem;
308
+ line-height: 1.25rem;
309
+ text-align: left;
310
+ }
311
+
312
+ [data-re-slash-command-item] svg {
313
+ flex-shrink: 0;
314
+ }
315
+
316
+ [data-re-slash-command-category] {
317
+ font-size: 0.6875rem;
318
+ font-weight: 600;
319
+ text-transform: uppercase;
320
+ letter-spacing: 0.05em;
321
+ padding: 0.5rem 0.5rem 0.25rem;
322
+ }
323
+
324
+ [data-re-slash-command-empty] {
325
+ padding: 0.75rem 0.5rem;
326
+ font-size: 0.875rem;
327
+ text-align: center;
328
+ }
329
+
330
+ /* ----------------------------------------------------------------
331
+ * CSS custom properties — light defaults
332
+ * ---------------------------------------------------------------- */
333
+
334
+ :root {
335
+ --re-bg: #fff;
336
+ --re-border: #e5e5e5;
337
+ --re-text: #1c1c1c;
338
+ --re-text-muted: #6b6b6b;
339
+ --re-hover: rgba(0, 0, 0, 0.04);
340
+ --re-active: rgba(0, 0, 0, 0.06);
341
+ --re-pressed: rgba(0, 0, 0, 0.06);
342
+ --re-separator: #e5e5e5;
343
+ --re-radius: 0.75rem;
344
+ --re-radius-sm: 0.5rem;
345
+ --re-shadow:
346
+ 0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -4px rgba(0, 0, 0, 0.1);
347
+ --re-danger: #dc2626;
348
+ --re-danger-hover: rgba(220, 38, 38, 0.1);
349
+ }
350
+
351
+ /* ----------------------------------------------------------------
352
+ * Dark mode — prefers-color-scheme
353
+ * ---------------------------------------------------------------- */
354
+
355
+ @media (prefers-color-scheme: dark) {
356
+ :root {
357
+ --re-bg: #1c1c1c;
358
+ --re-border: #2e2e2e;
359
+ --re-text: #ececec;
360
+ --re-text-muted: #a0a0a0;
361
+ --re-hover: rgba(255, 255, 255, 0.06);
362
+ --re-active: rgba(255, 255, 255, 0.09);
363
+ --re-pressed: rgba(255, 255, 255, 0.09);
364
+ --re-separator: #2e2e2e;
365
+ --re-shadow:
366
+ 0 10px 15px -3px rgba(0, 0, 0, 0.3), 0 4px 6px -4px rgba(0, 0, 0, 0.3);
367
+ --re-danger: #f87171;
368
+ --re-danger-hover: rgba(248, 113, 113, 0.15);
369
+ }
370
+ }
371
+
372
+ /* ----------------------------------------------------------------
373
+ * Dark mode — .dark class override
374
+ * ---------------------------------------------------------------- */
375
+
376
+ .dark {
377
+ --re-bg: #1c1c1c;
378
+ --re-border: #2e2e2e;
379
+ --re-text: #ececec;
380
+ --re-text-muted: #a0a0a0;
381
+ --re-hover: rgba(255, 255, 255, 0.06);
382
+ --re-active: rgba(255, 255, 255, 0.09);
383
+ --re-pressed: rgba(255, 255, 255, 0.09);
384
+ --re-separator: #2e2e2e;
385
+ --re-shadow:
386
+ 0 10px 15px -3px rgba(0, 0, 0, 0.3), 0 4px 6px -4px rgba(0, 0, 0, 0.3);
387
+ --re-danger: #f87171;
388
+ --re-danger-hover: rgba(248, 113, 113, 0.15);
389
+ }
390
+
391
+ /* ----------------------------------------------------------------
392
+ * Root containers
393
+ * ---------------------------------------------------------------- */
394
+
395
+ [data-re-bubble-menu],
396
+ [data-re-link-bm],
397
+ [data-re-btn-bm],
398
+ [data-re-img-bm] {
399
+ background: var(--re-bg);
400
+ border: 1px solid var(--re-border);
401
+ border-radius: var(--re-radius);
402
+ box-shadow: var(--re-shadow);
403
+ z-index: 50;
404
+ padding: 0.125rem;
405
+ font-family: system-ui, -apple-system, sans-serif;
406
+ font-size: 0.8125rem;
407
+ line-height: 1;
408
+ }
409
+
410
+ /* ----------------------------------------------------------------
411
+ * Toolbars (link, button, image bubble menus)
412
+ * ---------------------------------------------------------------- */
413
+
414
+ [data-re-link-bm-toolbar] > * + *,
415
+ [data-re-btn-bm-toolbar] > * + *,
416
+ [data-re-img-bm-toolbar] > * + * {
417
+ border-left: 1px solid var(--re-border);
418
+ }
419
+
420
+ /* ----------------------------------------------------------------
421
+ * Item buttons (all bubble menus)
422
+ * ---------------------------------------------------------------- */
423
+
424
+ [data-re-bubble-menu-item],
425
+ [data-re-link-bm-item],
426
+ [data-re-btn-bm-item],
427
+ [data-re-img-bm-item] {
428
+ color: var(--re-text-muted);
429
+ border-radius: var(--re-radius-sm);
430
+ transition:
431
+ background-color 0.15s,
432
+ color 0.15s;
433
+ }
434
+
435
+ [data-re-bubble-menu-item]:hover,
436
+ [data-re-link-bm-item]:hover,
437
+ [data-re-btn-bm-item]:hover,
438
+ [data-re-img-bm-item]:hover {
439
+ background: var(--re-hover);
440
+ color: var(--re-text);
441
+ }
442
+
443
+ [data-re-bubble-menu-item]:active,
444
+ [data-re-link-bm-item]:active,
445
+ [data-re-btn-bm-item]:active,
446
+ [data-re-img-bm-item]:active {
447
+ background: var(--re-active);
448
+ }
449
+
450
+ /* Active / pressed state */
451
+
452
+ [data-re-bubble-menu-item][data-active],
453
+ [data-re-bubble-menu-item][aria-pressed="true"] {
454
+ background: var(--re-pressed);
455
+ color: var(--re-text);
456
+ }
457
+
458
+ /* ----------------------------------------------------------------
459
+ * Separator (text bubble menu)
460
+ * ---------------------------------------------------------------- */
461
+
462
+ [data-re-bubble-menu-separator] {
463
+ background: var(--re-separator);
464
+ }
465
+
466
+ /* ----------------------------------------------------------------
467
+ * Node Selector
468
+ * ---------------------------------------------------------------- */
469
+
470
+ [data-re-node-selector-trigger] {
471
+ color: var(--re-text);
472
+ border-radius: var(--re-radius-sm);
473
+ transition: background-color 0.15s;
474
+ font-weight: 500;
475
+ }
476
+
477
+ [data-re-node-selector-trigger]:hover {
478
+ background: var(--re-hover);
479
+ }
480
+
481
+ [data-re-node-selector-trigger]:active {
482
+ background: var(--re-active);
483
+ }
484
+
485
+ [data-re-node-selector-content] {
486
+ background: var(--re-bg);
487
+ border: 1px solid var(--re-border);
488
+ border-radius: var(--re-radius);
489
+ box-shadow: var(--re-shadow);
490
+ padding: 0.25rem;
491
+ margin-top: 0.25rem;
492
+ z-index: 50;
493
+ }
494
+
495
+ [data-re-node-selector-item] {
496
+ color: var(--re-text-muted);
497
+ border-radius: var(--re-radius-sm);
498
+ transition:
499
+ background-color 0.15s,
500
+ color 0.15s;
501
+ }
502
+
503
+ [data-re-node-selector-item]:hover {
504
+ background: var(--re-hover);
505
+ color: var(--re-text);
506
+ }
507
+
508
+ [data-re-node-selector-item][data-active] {
509
+ color: var(--re-text);
510
+ }
511
+
512
+ /* ----------------------------------------------------------------
513
+ * Link Selector (text bubble menu)
514
+ * ---------------------------------------------------------------- */
515
+
516
+ [data-re-link-selector-trigger] {
517
+ color: var(--re-text-muted);
518
+ border-radius: var(--re-radius-sm);
519
+ transition:
520
+ background-color 0.15s,
521
+ color 0.15s;
522
+ }
523
+
524
+ [data-re-link-selector-trigger]:hover {
525
+ background: var(--re-hover);
526
+ color: var(--re-text);
527
+ }
528
+
529
+ [data-re-link-selector-trigger][aria-pressed="true"] {
530
+ background: var(--re-pressed);
531
+ }
532
+
533
+ [data-re-link-selector-form] {
534
+ background: var(--re-bg);
535
+ border: 1px solid var(--re-border);
536
+ border-radius: var(--re-radius);
537
+ box-shadow: var(--re-shadow);
538
+ padding: 0.25rem;
539
+ }
540
+
541
+ [data-re-link-selector-input] {
542
+ color: var(--re-text);
543
+ }
544
+
545
+ [data-re-link-selector-input]::placeholder {
546
+ color: var(--re-text-muted);
547
+ }
548
+
549
+ [data-re-link-selector-apply] {
550
+ color: var(--re-text);
551
+ border-radius: var(--re-radius-sm);
552
+ transition: background-color 0.15s;
553
+ }
554
+
555
+ [data-re-link-selector-apply]:hover {
556
+ background: var(--re-hover);
557
+ }
558
+
559
+ [data-re-link-selector-unlink] {
560
+ color: var(--re-danger);
561
+ border-radius: var(--re-radius-sm);
562
+ transition: background-color 0.15s;
563
+ }
564
+
565
+ [data-re-link-selector-unlink]:hover {
566
+ background: var(--re-danger-hover);
567
+ }
568
+
569
+ /* ----------------------------------------------------------------
570
+ * Link Bubble Menu Form
571
+ * ---------------------------------------------------------------- */
572
+
573
+ [data-re-link-bm-form] {
574
+ background: var(--re-bg);
575
+ border: 1px solid var(--re-border);
576
+ border-radius: var(--re-radius);
577
+ box-shadow: var(--re-shadow);
578
+ padding: 0.25rem;
579
+ }
580
+
581
+ [data-re-link-bm-input] {
582
+ color: var(--re-text);
583
+ }
584
+
585
+ [data-re-link-bm-input]::placeholder {
586
+ color: var(--re-text-muted);
587
+ }
588
+
589
+ [data-re-link-bm-apply] {
590
+ color: var(--re-text);
591
+ border-radius: var(--re-radius-sm);
592
+ transition: background-color 0.15s;
593
+ }
594
+
595
+ [data-re-link-bm-apply]:hover {
596
+ background: var(--re-hover);
597
+ }
598
+
599
+ [data-re-link-bm-unlink] {
600
+ color: var(--re-danger);
601
+ border-radius: var(--re-radius-sm);
602
+ transition: background-color 0.15s;
603
+ }
604
+
605
+ [data-re-link-bm-unlink]:hover {
606
+ background: var(--re-danger-hover);
607
+ }
608
+
609
+ /* ----------------------------------------------------------------
610
+ * Slash Command
611
+ * ---------------------------------------------------------------- */
612
+
613
+ [data-re-slash-command] {
614
+ background: var(--re-bg);
615
+ border: 1px solid var(--re-border);
616
+ border-radius: var(--re-radius);
617
+ box-shadow: var(--re-shadow);
618
+ font-family: system-ui, -apple-system, sans-serif;
619
+ }
620
+
621
+ [data-re-slash-command-item] {
622
+ color: var(--re-text);
623
+ border-radius: var(--re-radius-sm);
624
+ transition: background-color 0.15s;
625
+ }
626
+
627
+ [data-re-slash-command-item]:hover {
628
+ background: var(--re-hover);
629
+ }
630
+
631
+ [data-re-slash-command-item][data-selected] {
632
+ background: var(--re-hover);
633
+ }
634
+
635
+ [data-re-slash-command-item]:active {
636
+ background: var(--re-active);
637
+ }
638
+
639
+ [data-re-slash-command-item] svg {
640
+ color: var(--re-text-muted);
641
+ }
642
+
643
+ [data-re-slash-command-category] {
644
+ color: var(--re-text-muted);
645
+ }
646
+
647
+ [data-re-slash-command-empty] {
648
+ color: var(--re-text-muted);
649
+ }
650
+
651
+ /* ----------------------------------------------------------------
652
+ * Editor content — alignment attribute
653
+ * ---------------------------------------------------------------- */
654
+
655
+ .tiptap [alignment="left"] {
656
+ text-align: left;
657
+ }
658
+
659
+ .tiptap [alignment="center"] {
660
+ text-align: center;
661
+ }
662
+
663
+ .tiptap [alignment="right"] {
664
+ text-align: right;
665
+ }
666
+
667
+ .tiptap [alignment="justify"] {
668
+ text-align: justify;
669
+ }
670
+
671
+ /* ----------------------------------------------------------------
672
+ * Editor content — columns
673
+ * ---------------------------------------------------------------- */
674
+
675
+ .tiptap .node-columns {
676
+ display: flex;
677
+ gap: 0.5rem;
678
+ width: 100%;
679
+ }
680
+
681
+ .tiptap .node-column {
682
+ flex: 1;
683
+ min-width: 0;
684
+ }
685
+
686
+ /* ----------------------------------------------------------------
687
+ * Editor content — base typography
688
+ * ---------------------------------------------------------------- */
689
+
690
+ .tiptap {
691
+ outline: none;
692
+ color: var(--re-text);
693
+ }
694
+
695
+ .tiptap p {
696
+ margin: 0.25em 0;
697
+ }
698
+
699
+ .tiptap h1,
700
+ .tiptap h2,
701
+ .tiptap h3 {
702
+ margin: 0.5em 0 0.25em;
703
+ }
704
+
705
+ .tiptap blockquote {
706
+ border-left: 3px solid var(--re-border);
707
+ margin: 0.5em 0;
708
+ padding-left: 1em;
709
+ color: var(--re-text-muted);
710
+ }
711
+
712
+ .tiptap hr {
713
+ border: none;
714
+ border-top: 1px solid var(--re-border);
715
+ margin: 1em 0;
716
+ }
717
+
718
+ .tiptap code {
719
+ background: var(--re-hover);
720
+ border-radius: 0.25rem;
721
+ padding: 0.125rem 0.375rem;
722
+ font-size: 0.875em;
723
+ }
724
+
725
+ .tiptap pre {
726
+ background: var(--re-hover);
727
+ border-radius: var(--re-radius-sm);
728
+ padding: 0.75rem 1rem;
729
+ overflow-x: auto;
730
+ }
731
+
732
+ .tiptap pre code {
733
+ background: none;
734
+ padding: 0;
735
+ border-radius: 0;
736
+ }
737
+
738
+ .tiptap ul,
739
+ .tiptap ol {
740
+ padding-left: 1.5em;
741
+ margin: 0.25em 0;
742
+ }
743
+
744
+ .tiptap .node-placeholder::before {
745
+ color: var(--re-text-muted);
746
+ content: attr(data-placeholder);
747
+ float: left;
748
+ height: 0;
749
+ pointer-events: none;
750
+ }