@oix1987/yjd 1.0.2 → 2.0.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 (70) hide show
  1. package/LICENSE +15 -0
  2. package/README.md +146 -142
  3. package/core.js +77 -0
  4. package/dist/core.esm.js +2 -0
  5. package/dist/core.esm.js.map +1 -0
  6. package/dist/rich-editor.esm.js +1 -1
  7. package/dist/rich-editor.esm.js.map +1 -1
  8. package/dist/rich-editor.min.js +1 -1
  9. package/dist/rich-editor.min.js.map +1 -1
  10. package/index.d.ts +134 -103
  11. package/index.js +227 -0
  12. package/lib/core/editor.js +1806 -0
  13. package/lib/core/format.js +540 -0
  14. package/lib/core/module.js +81 -0
  15. package/lib/core/registry.js +158 -0
  16. package/lib/formats/background.js +213 -0
  17. package/lib/formats/bold.js +49 -0
  18. package/lib/formats/capitalization.js +579 -0
  19. package/lib/formats/color.js +183 -0
  20. package/lib/formats/emoji.js +282 -0
  21. package/lib/formats/font-family.js +548 -0
  22. package/lib/formats/heading.js +502 -0
  23. package/lib/formats/image.js +347 -0
  24. package/lib/formats/import.js +385 -0
  25. package/lib/formats/indent.js +297 -0
  26. package/lib/formats/italic.js +27 -0
  27. package/lib/formats/line-height.js +562 -0
  28. package/lib/formats/link.js +251 -0
  29. package/lib/formats/list.js +635 -0
  30. package/lib/formats/strike.js +31 -0
  31. package/lib/formats/subscript.js +40 -0
  32. package/lib/formats/superscript.js +39 -0
  33. package/lib/formats/table.js +293 -0
  34. package/lib/formats/tag.js +304 -0
  35. package/lib/formats/text-align.js +422 -0
  36. package/lib/formats/text-size.js +498 -0
  37. package/lib/formats/underline.js +30 -0
  38. package/lib/formats/video.js +381 -0
  39. package/lib/modules/block-toolbar.js +639 -0
  40. package/lib/modules/code-view.js +447 -0
  41. package/lib/modules/find-replace.js +273 -0
  42. package/lib/modules/history.js +425 -0
  43. package/lib/modules/resize-handles.js +701 -0
  44. package/lib/modules/slash-menu.js +183 -0
  45. package/lib/modules/table-toolbar.js +635 -0
  46. package/lib/modules/toolbar.js +607 -0
  47. package/lib/styles-loader.js +142 -0
  48. package/lib/styles.css +3373 -0
  49. package/lib/styles.css.js +2 -0
  50. package/lib/styles.min.css +1 -0
  51. package/lib/ui/color-picker.js +296 -0
  52. package/lib/ui/customselect.js +351 -0
  53. package/lib/ui/emoji-picker.js +196 -0
  54. package/lib/ui/icons.js +145 -0
  55. package/lib/ui/image-popup.js +435 -0
  56. package/lib/ui/import-popup.js +288 -0
  57. package/lib/ui/link-popup.js +139 -0
  58. package/lib/ui/list-picker.js +307 -0
  59. package/lib/ui/select-button.js +68 -0
  60. package/lib/ui/table-popup.js +171 -0
  61. package/lib/ui/tag-popup.js +249 -0
  62. package/lib/ui/text-align-picker.js +278 -0
  63. package/lib/ui/video-popup.js +413 -0
  64. package/lib/utils/exec-command.js +72 -0
  65. package/lib/utils/history-helper.js +50 -0
  66. package/lib/utils/popup-helper.js +219 -0
  67. package/lib/utils/popup-positioning.js +234 -0
  68. package/lib/utils/sanitize.js +164 -0
  69. package/package.json +51 -31
  70. package/umd-entry.js +18 -0
package/lib/styles.css ADDED
@@ -0,0 +1,3373 @@
1
+ /* ===================================
2
+ Rich Editor - Component Styles
3
+ ===================================*/
4
+
5
+ /* === CORE EDITOR === */
6
+ .yjd-rich-editor {
7
+ position: relative;
8
+ background: #fff;
9
+ border: 1px solid #d1d5db;
10
+ border-radius: 8px;
11
+ overflow: hidden;
12
+ margin: 0 auto;
13
+ font-family: system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
14
+ display: flex;
15
+ flex-direction: column;
16
+ box-sizing: border-box;
17
+ }
18
+ @layer base {
19
+ .yjd-rich-editor .toolbar-container button,
20
+ .yjd-rich-editor .toolbar-container input,
21
+ .yjd-rich-editor .toolbar-container select,
22
+ .yjd-rich-editor .toolbar-container optgroup,
23
+ .yjd-rich-editor .toolbar-container textarea,
24
+ .yjd-rich-editor .toolbar-container ::file-selector-button {
25
+ font: normal 500 14px/1.4 "Inter", Arial, sans-serif !important;
26
+ letter-spacing: normal !important;
27
+ font-feature-settings: normal !important;
28
+ font-variation-settings: normal !important;
29
+ }
30
+ /* Ensure emoji button font size is applied with high specificity */
31
+ .yjd-rich-editor .emoji-picker-popup .emoji-button,
32
+ .yjd-rich-editor .emoji-picker-popup button.emoji-button {
33
+ font-size: 20px !important;
34
+ }
35
+ }
36
+ @layer base {
37
+
38
+ .yjd-rich-editor .rich-editor-popup-container button,
39
+ .yjd-rich-editor .rich-editor-popup-container input,
40
+ .yjd-rich-editor .rich-editor-popup-container select,
41
+ .yjd-rich-editor .rich-editor-popup-container optgroup,
42
+ .yjd-rich-editor .rich-editor-popup-container textarea,
43
+ .yjd-rich-editor .rich-editor-popup-container ::file-selector-button {
44
+ font: normal 500 14px/1.4 "Inter", Arial, sans-serif !important;
45
+ letter-spacing: normal !important;
46
+ font-feature-settings: normal !important;
47
+ font-variation-settings: normal !important;
48
+ }
49
+ /* Ensure emoji button font size is applied with high specificity */
50
+ .yjd-rich-editor .emoji-picker-popup .emoji-button,
51
+ .yjd-rich-editor .emoji-picker-popup button.emoji-button {
52
+ font-size: 20px !important;
53
+ }
54
+ }
55
+
56
+ .yjd-rich-editor .rich-editor-area {
57
+ flex: 1 1 auto;
58
+ min-height: 40px;
59
+ font-size: 16px;
60
+ line-height: 1.7;
61
+ outline: none;
62
+ padding: 20px 20px 20px 20px;
63
+ background: #fff;
64
+ color: #2c3e50;
65
+ font-family: inherit;
66
+ overflow-y: auto;
67
+ box-sizing: border-box;
68
+ border: none;
69
+ text-align: left;
70
+ position: relative;
71
+ }
72
+
73
+ /* Placeholder styles for contentEditable.
74
+ Inherit the editor's padding + font so the placeholder lands exactly on the
75
+ content origin (where the caret/first character sits) at ANY padding/size —
76
+ instead of hardcoded offsets that drifted out of alignment. */
77
+ .yjd-rich-editor .rich-editor-area[data-placeholder]:before {
78
+ content: attr(data-placeholder);
79
+ color: #9ca3af;
80
+ pointer-events: none;
81
+ position: absolute;
82
+ top: 0;
83
+ left: 0;
84
+ right: 0;
85
+ padding: inherit;
86
+ box-sizing: border-box;
87
+ font: inherit;
88
+ font-style: italic;
89
+ line-height: inherit;
90
+ display: none;
91
+ z-index: 1;
92
+ }
93
+
94
+ .yjd-rich-editor .rich-editor-area[data-placeholder].placeholder-visible:before {
95
+ display: block;
96
+ }
97
+
98
+ .yjd-rich-editor .rich-editor-area {
99
+ font-size: 16px;
100
+ line-height: 1.7;
101
+ font-family: inherit;
102
+ color: #2c3e50;
103
+ padding: 20px 20px;
104
+ box-sizing: border-box;
105
+ }
106
+
107
+ /* inline elements */
108
+ .yjd-rich-editor .rich-editor-area b,
109
+ .yjd-rich-editor .rich-editor-area strong {
110
+ font-weight: bold;
111
+ }
112
+
113
+ .yjd-rich-editor .rich-editor-area i,
114
+ .yjd-rich-editor .rich-editor-area em {
115
+ font-style: italic;
116
+ }
117
+
118
+ .yjd-rich-editor .rich-editor-area u {
119
+ text-decoration: underline;
120
+ }
121
+
122
+ .yjd-rich-editor .rich-editor-area a {
123
+ color: #2563eb;
124
+ text-decoration: underline;
125
+ cursor: pointer;
126
+ }
127
+
128
+ /* block text */
129
+ .yjd-rich-editor .rich-editor-area p {
130
+ margin: 0 0 1em;
131
+ }
132
+
133
+ /* headings */
134
+ .yjd-rich-editor .rich-editor-area h1 {
135
+ font-size: 2em;
136
+ font-weight: bold;
137
+ margin: 0.67em 0;
138
+ }
139
+
140
+ .yjd-rich-editor .rich-editor-area h2 {
141
+ font-size: 1.5em;
142
+ font-weight: bold;
143
+ margin: 0.75em 0;
144
+ }
145
+
146
+ .yjd-rich-editor .rich-editor-area h3 {
147
+ font-size: 1.25em;
148
+ font-weight: bold;
149
+ margin: 0.83em 0;
150
+ }
151
+
152
+ .yjd-rich-editor .rich-editor-area h4 {
153
+ font-size: 1.1em;
154
+ font-weight: bold;
155
+ margin: 1em 0;
156
+ }
157
+
158
+ .yjd-rich-editor .rich-editor-area h5 {
159
+ font-size: 1em;
160
+ font-weight: bold;
161
+ margin: 1.25em 0;
162
+ }
163
+
164
+ .yjd-rich-editor .rich-editor-area h6 {
165
+ font-size: 0.875em;
166
+ font-weight: bold;
167
+ margin: 1.5em 0;
168
+ color: #555;
169
+ }
170
+
171
+ /* lists */
172
+ .yjd-rich-editor .rich-editor-area ul,
173
+ .yjd-rich-editor .rich-editor-area ol {
174
+ margin: 0 0 1em 2em;
175
+ padding: 0;
176
+ }
177
+
178
+ .yjd-rich-editor .rich-editor-area li {
179
+ margin: 0.25em 0;
180
+ }
181
+
182
+ /* code & pre */
183
+ .yjd-rich-editor .rich-editor-area pre,
184
+ .yjd-rich-editor .rich-editor-area code {
185
+ font-family: Consolas, Menlo, Monaco, "Courier New", monospace;
186
+ background: #f1f2f3;
187
+ padding: 4px 6px;
188
+ border-radius: 4px;
189
+ overflow-x: auto;
190
+ }
191
+
192
+ .yjd-rich-editor .rich-editor-area pre {
193
+ display: block;
194
+ white-space: pre;
195
+ margin: 1em 0;
196
+ }
197
+
198
+ .yjd-rich-editor .rich-editor-area code {
199
+ display: inline;
200
+ }
201
+
202
+ /* blockquote */
203
+ .yjd-rich-editor .rich-editor-area blockquote {
204
+ border-left: 4px solid #d1d5db;
205
+ margin: 1em 0;
206
+ padding: 4px 12px;
207
+ color: #555;
208
+ font-style: italic;
209
+ background: #f9fafb;
210
+ }
211
+ .yjd-rich-editor .rich-editor-area sub {
212
+ font-size: 0.75em;
213
+ vertical-align: sub;
214
+ line-height: 1;
215
+ }
216
+
217
+ .yjd-rich-editor .rich-editor-area sup {
218
+ font-size: 0.75em;
219
+ vertical-align: super;
220
+ line-height: 1;
221
+ }
222
+ .yjd-rich-editor .rich-editor-area a{
223
+ cursor: pointer;
224
+ }
225
+ .yjd-rich-editor .rich-editor-area pre {
226
+ background-color: #f1f2f3;
227
+ width: 96%;
228
+ padding: 10px 2% 10px 2%;
229
+ font-family: Consolas, Menlo, Monaco, "Courier New", monospace;
230
+ overflow-x: auto;
231
+ white-space: pre;
232
+ word-wrap: normal;
233
+ }
234
+ /* Force contentEditable to create P tags instead of DIV on Enter */
235
+ .yjd-rich-editor .rich-editor-area div {
236
+ display: block;
237
+ }
238
+
239
+ .yjd-rich-editor .rich-editor-area:empty::before {
240
+ content: '';
241
+ display: block;
242
+ }
243
+
244
+ .yjd-rich-editor .rich-editor-statusbar {
245
+ position: relative;
246
+ z-index: 1000;
247
+ padding: 4px 12px;
248
+ border-top: 1px solid #d1d5db;
249
+ background: #f9fafb;
250
+ font-size: 13px;
251
+ color: #6b7280;
252
+ display: flex;
253
+ justify-content: space-between;
254
+ align-items: center;
255
+ font-family: inherit;
256
+ min-height: 32px;
257
+ box-sizing: border-box;
258
+ }
259
+
260
+ /* === TOOLBAR === */
261
+ .yjd-rich-editor .rich-editor-toolbar-container{
262
+ border-bottom: 1px solid #d1d5db;
263
+ position: relative;
264
+ z-index: 1000; /* Ensure toolbars are above resize handles */
265
+ }
266
+ .yjd-rich-editor .rich-editor-toolbar-1{
267
+ padding:8px 16px;
268
+ display:flex;
269
+ justify-content:space-between;
270
+ gap:20px;
271
+ flex-wrap:wrap;
272
+ background:#FCFCFC;
273
+ align-items:center;
274
+ min-height:48px;
275
+ padding-bottom:8px;
276
+ box-sizing:border-box;
277
+ width:100%;
278
+ overflow:hidden;
279
+ z-index: 1000; /* Higher than resize handles */
280
+ position: relative;
281
+ }
282
+ .yjd-rich-editor .rich-editor-toolbar-2{
283
+ display:none;
284
+ padding: 8px 16px;
285
+ justify-content: space-between;
286
+ gap: 20px;
287
+ flex-wrap: wrap;
288
+ background: #FCFCFC;
289
+ align-items: center;
290
+ min-height: 48px;
291
+ padding-bottom: 8px;
292
+ box-sizing: border-box;
293
+ width: 100%;
294
+ overflow: hidden;
295
+ z-index: 1000; /* Higher than resize handles */
296
+ position: relative;
297
+ }
298
+ .yjd-rich-editor .rich-editor-toolbar-2.visible{
299
+ display:flex;
300
+ }
301
+
302
+ /* === TOOLBAR GROUPS === */
303
+ .yjd-rich-editor .toolbar-group {
304
+ display: flex;
305
+ align-items: center;
306
+ gap: 12px;
307
+ }
308
+
309
+ /* === TOOLBAR BUTTONS === */
310
+
311
+ .yjd-rich-editor .rich-editor-toolbar-btn{
312
+ height: 20px;
313
+ min-width: 22px;
314
+ width: 22px;
315
+ display: inline-flex;
316
+ border-radius: 4px;
317
+ font-size: 14px;
318
+ align-items: center;
319
+ background:transparent;
320
+ justify-content: center;
321
+ font-weight: 500;
322
+ border: none;
323
+ }
324
+ .yjd-rich-editor .custom-select-button span{
325
+ justify-content: left !important;
326
+ }
327
+ .yjd-rich-editor .custom-select-button:focus {
328
+ outline: none;
329
+ border-color: #3b82f6;
330
+ box-shadow: 0 0 0 1px rgba(59, 130, 246, 0.1);
331
+
332
+ }
333
+ .yjd-rich-editor .rich-editor-toolbar-btn span{
334
+ display: flex !important;
335
+ align-items: center;
336
+ justify-content: center;
337
+ }
338
+ .yjd-rich-editor .rich-editor-toolbar-btn:hover {
339
+ background: #EEEEEE !important;
340
+ cursor: pointer;
341
+ }
342
+ /* Active toolbar-button + icon colours are owned by the design-system layer
343
+ (accent), and icon sizing/stroke by the outline-icon layer — the old blue
344
+ (#136FDF) / grey (#454545) overrides have been removed. */
345
+
346
+ /*block toolbar*/
347
+ .yjd-rich-editor .block-toolbar-btn{
348
+ border:none;
349
+ border-radius:4px;
350
+ padding:4px;
351
+ background:transparent;
352
+ cursor:pointer;
353
+ font-size:14px;
354
+ font-weight:500;
355
+ align-items:center;
356
+ justify-content:center;
357
+ display:inline-flex;
358
+ }
359
+ .yjd-rich-editor .block-toolbar-btn:hover{
360
+ background:#EEEEEE;
361
+ }
362
+ .yjd-rich-editor .block-toolbar-btn.active{
363
+ background:#CCCCCC;
364
+ color: #136FDF !important;
365
+ }
366
+
367
+ .yjd-rich-editor .block-toolbar-btn.active svg,
368
+ .yjd-rich-editor .block-toolbar-btn.active .icon svg {
369
+ fill: #136FDF !important;
370
+ }
371
+
372
+ .yjd-rich-editor .block-toolbar-btn.active svg path,
373
+ .yjd-rich-editor .block-toolbar-btn.active .icon svg path {
374
+ fill: #136FDF !important;
375
+ }
376
+
377
+ /* Block toolbar container and arrow */
378
+ .yjd-rich-editor .block-toolbar-container {
379
+ display: flex;
380
+ align-items: center;
381
+ gap: 28px;
382
+ padding: 8px;
383
+ background: #fff;
384
+ border-radius: 6.9px;
385
+ box-shadow: 0 4px 24px rgba(0,0,0,0.13);
386
+ }
387
+
388
+ .yjd-rich-editor .block-toolbar-arrow {
389
+ position: absolute;
390
+ bottom: -6px;
391
+ left: 50%;
392
+ transform: translateX(-50%);
393
+ width: 0;
394
+ height: 0;
395
+ border-left: 6px solid transparent;
396
+ border-right: 6px solid transparent;
397
+ border-top: 6px solid #fff;
398
+ filter: drop-shadow(0 2px 4px rgba(0,0,0,0.1));
399
+ }
400
+
401
+ /* Table toolbar container and arrow */
402
+ .yjd-rich-editor .table-toolbar-container {
403
+ display: flex;
404
+ align-items: center;
405
+ gap: 12px;
406
+ padding: 8px;
407
+ background: #fff;
408
+ border-radius: 6px;
409
+ box-shadow: 0 4px 24px rgba(0,0,0,0.13);
410
+ }
411
+
412
+ .yjd-rich-editor .table-toolbar-arrow {
413
+ position: absolute;
414
+ bottom: -6px;
415
+ left: 50%;
416
+ transform: translateX(-50%);
417
+ width: 0;
418
+ height: 0;
419
+ border-left: 6px solid transparent;
420
+ border-right: 6px solid transparent;
421
+ border-top: 6px solid #fff;
422
+ filter: drop-shadow(0 2px 4px rgba(0,0,0,0.1));
423
+ }
424
+
425
+ /* Update block toolbar to use flexbox for proper layout */
426
+ .yjd-rich-editor .block-toolbar {
427
+ display: none;
428
+ position: absolute;
429
+ z-index: 1001;
430
+ background: transparent;
431
+ border: none;
432
+ border-radius: 6.9px;
433
+ box-sizing: border-box;
434
+ padding: 0;
435
+ gap: 0;
436
+ flex-direction: column;
437
+ align-items: center;
438
+ }
439
+
440
+ .yjd-rich-editor .block-toolbar.visible {
441
+ display: flex;
442
+ }
443
+ /* === COLOR PICKER === */
444
+ .yjd-rich-editor .color-picker-popup {
445
+ position: absolute;
446
+ background: #fff;
447
+ display:none;
448
+ border-radius: 6.9px;
449
+ padding: 8px;
450
+ box-shadow: 0 4px 16px rgba(0, 0, 0, 0.1);
451
+ z-index: 1000;
452
+ /* Prevent focus and click on popup container */
453
+ pointer-events: none;
454
+ -webkit-user-select: none;
455
+ -moz-user-select: none;
456
+ -ms-user-select: none;
457
+ user-select: none;
458
+ }
459
+
460
+ .yjd-rich-editor .color-picker-popup.visible{
461
+ display:block !important;
462
+ }
463
+
464
+ /* === CUSTOM SELECT === */
465
+ .yjd-rich-editor .custom-select-popup, .yjd-rich-editor .heading-select-popup, .yjd-rich-editor .capitalization-select-popup, .yjd-rich-editor .font-family-select-popup, .yjd-rich-editor .line-height-select-popup, .yjd-rich-editor .text-size-select-popup {
466
+ position: absolute;
467
+ background: #fff;
468
+ display: none;
469
+ border: 1px solid #d1d5db;
470
+ border-radius: 6.9px;
471
+ padding: 8px;
472
+ box-shadow: 0 4px 16px rgba(0, 0, 0, 0.15);
473
+ z-index: 1002;
474
+ max-height: 200px;
475
+ overflow-y: auto;
476
+ /* Prevent focus and click on popup container */
477
+ pointer-events: none;
478
+ -webkit-user-select: none;
479
+ -moz-user-select: none;
480
+ -ms-user-select: none;
481
+ user-select: none;
482
+ }
483
+
484
+ .yjd-rich-editor .custom-select-popup.visible, .yjd-rich-editor .heading-select-popup.visible, .yjd-rich-editor .font-family-select-popup.visible, .yjd-rich-editor .line-height-select-popup.visible, .yjd-rich-editor .capitalization-select-popup.visible, .yjd-rich-editor .text-size-select-popup.visible {
485
+ display: block !important;
486
+ }
487
+
488
+ .yjd-rich-editor .link-popup ,.yjd-rich-editor .image-popup,.yjd-rich-editor .video-popup, .yjd-rich-editor .tag-popup {
489
+ width: 299px;
490
+ }
491
+ .yjd-rich-editor .item-list {
492
+ display: flex;
493
+ flex-direction: column;
494
+ gap: 2px;
495
+ }
496
+
497
+
498
+ .yjd-rich-editor .heading-select-popup {
499
+ width: 190px;
500
+ max-width: 100vw;
501
+ }
502
+
503
+ .yjd-rich-editor .capitalization-select-popup {
504
+ width: 150px;
505
+ max-width: 100vw;
506
+ }
507
+
508
+ .yjd-rich-editor .font-family-select-popup {
509
+ width: 190px;
510
+ max-width: 100vw;
511
+ }
512
+
513
+ .yjd-rich-editor .line-height-select-popup {
514
+ width: 80px;
515
+ max-width: 100vw;
516
+ }
517
+
518
+ .yjd-rich-editor .text-size-select-popup {
519
+ width: 150px;
520
+ max-width: 100vw;
521
+ }
522
+
523
+ .yjd-rich-editor .custom-select-item-button {
524
+ width: 100%;
525
+ padding: 4px 4px;
526
+ border: none;
527
+ background: transparent;
528
+ border-radius: 6px;
529
+ cursor: pointer;
530
+ text-align: left;
531
+ transition: all 0.2s ease;
532
+ font-size: 14px;
533
+ line-height: 1.4;
534
+ color: #111827;
535
+ display: flex;
536
+ align-items: center;
537
+ justify-content: space-between;
538
+ /* Allow interaction with select item buttons */
539
+ pointer-events: auto;
540
+ }
541
+
542
+ .yjd-rich-editor .custom-select-item-button:hover {
543
+ background: #EEEEEE;
544
+ }
545
+
546
+ .yjd-rich-editor .custom-select-item-button.current {
547
+ font-weight: 500;
548
+ background: #EEEEEE !important;
549
+ }
550
+ .yjd-rich-editor .custom-select-item-button .item-checkmark{
551
+ display:none;
552
+ }
553
+ .yjd-rich-editor .custom-select-item-button.current .item-checkmark{
554
+ display:block;
555
+ }
556
+ .yjd-rich-editor .item-text {
557
+ flex: 1;
558
+ }
559
+ .yjd-rich-editor .dropdown-icon{
560
+ display: inline-flex !important;
561
+ align-items: center ;
562
+ justify-content: center ;
563
+ width: 16px;
564
+ height: 16px;
565
+ flex: 0 0 auto;
566
+ }
567
+ /* The chevron SVG keeps the `dropdown-icon` class (not `.icon`), so size it
568
+ explicitly here — otherwise it has no dimensions and the arrow disappears. */
569
+ .yjd-rich-editor .dropdown-icon svg{
570
+ width: 16px;
571
+ height: 16px;
572
+ display: block;
573
+ stroke: currentColor;
574
+ fill: none;
575
+ }
576
+
577
+
578
+ .yjd-rich-editor .color-grid {
579
+ display: grid;
580
+ grid-template-columns: repeat(6, 1fr);
581
+ gap: 6px 4px;
582
+ margin-bottom: 12px;
583
+ }
584
+
585
+ .yjd-rich-editor .color-button {
586
+ width: 24px;
587
+ height: 24px;
588
+ border:none;
589
+ border-radius: 50%;
590
+ cursor: pointer;
591
+ transition: all 0.2s ease;
592
+ padding: 0;
593
+ margin: 0;
594
+ /* Allow interaction with color buttons */
595
+ pointer-events: auto;
596
+ }
597
+
598
+ .yjd-rich-editor .color-button:hover {
599
+ transform: scale(1.1);
600
+ border-color: #374151;
601
+ box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
602
+ }
603
+
604
+ .yjd-rich-editor .custom-color-container {
605
+ position: relative;
606
+ padding-top: 8px;
607
+ display: flex;
608
+ align-items: center;
609
+ gap: 8px;
610
+ z-index: 0;
611
+ /* đảm bảo ::before không che nội dung */
612
+ }
613
+
614
+ .yjd-rich-editor .custom-color-container::before {
615
+ content: "";
616
+ position: absolute;
617
+ top: 0;
618
+ left: -8px;
619
+ width: calc(100% + 16px);
620
+ /* 8px trái + 8px phải */
621
+ height: 0;
622
+ border-top: 1px solid #e5e7eb;
623
+ z-index: -1;
624
+ /* đặt phía sau nội dung */
625
+ }
626
+
627
+ .yjd-rich-editor .custom-color-label {
628
+ font-size: 12px;
629
+ color: #6b7280;
630
+ margin: 0;
631
+ }
632
+
633
+
634
+ .yjd-rich-editor .yjd-input-title{
635
+ margin: 0;
636
+ color: #252424;
637
+ font-size: 16px;
638
+ font-style: normal;
639
+ font-weight: 700;
640
+ line-height: normal;
641
+ }
642
+ .yjd-rich-editor .yjd-input-label{
643
+ color: #252424;
644
+ margin: 0;
645
+ font-size: 14px;
646
+ font-style: normal;
647
+ font-weight: 700;
648
+ line-height: normal;
649
+ }
650
+ .yjd-rich-editor .yjd-input-group{
651
+ display: flex;
652
+ flex-direction: column;
653
+ gap: 8px;
654
+ }
655
+ .yjd-rich-editor .yjd-input {
656
+ padding: 10px;
657
+ flex: 1 1 auto;
658
+ min-width: 0;
659
+ max-width: 100%;
660
+ max-height: 37px;
661
+ border-radius: 10px;
662
+ border: 1px solid #E1E1E1;
663
+ box-sizing: border-box;
664
+ color: #252424 !important;
665
+ font-size: 14px;
666
+ /* Allow interaction with inputs */
667
+ pointer-events: auto;
668
+ }
669
+ .yjd-rich-editor .yjd-input:focus {
670
+ outline: none;
671
+ border-color: #3b82f6;
672
+ box-shadow: 0 0 0 1px rgba(59, 130, 246, 0.1);
673
+ }
674
+ .yjd-rich-editor .yjd-button-container{
675
+ display: flex ;
676
+ justify-content: flex-end;
677
+ gap: 4px;
678
+ }
679
+ .yjd-rich-editor .yjd-button-confirm{
680
+ padding: 8px 15px;
681
+ align-items: center;
682
+ border-radius: 6px;
683
+ background: #181616;
684
+ box-shadow: 0px 1px 3.3px 0px rgba(0, 0, 0, 0.04);
685
+ /* Allow interaction with buttons */
686
+ pointer-events: auto;
687
+ color: #FFF;
688
+ font-size: 12px;
689
+ font-style: normal;
690
+ font-weight: 700;
691
+ line-height: normal;
692
+ cursor: pointer;
693
+ }
694
+ .yjd-rich-editor .yjd-button-cancel{
695
+ border-radius: 6px;
696
+ align-items: center;
697
+ padding: 8px 15px;
698
+ border: 1px solid #E0E0E0;
699
+ background: #FFFFFF;
700
+ box-shadow: 0px 1px 3.3px 0px rgba(0, 0, 0, 0.04);
701
+ color: #2A2727;
702
+ font-size: 12px;
703
+ font-style: normal;
704
+ font-weight: 700;
705
+ line-height: normal;
706
+ cursor: pointer;
707
+ }
708
+ .yjd-rich-editor .button-disable{
709
+ cursor: not-allowed;
710
+ }
711
+ /* === LINK POPUP === */
712
+ .yjd-rich-editor .link-popup {
713
+ position: absolute;
714
+ background: #fff;
715
+ font-family: 'Lato', sans-serif;
716
+ display: none;
717
+ border: none;
718
+ border-radius: 10px;
719
+ box-shadow: 0px 1px 5px 0px rgba(0, 0, 0, 0.18);
720
+ z-index: 1000;
721
+ margin: 0;
722
+ /* Prevent focus and click on popup container */
723
+ pointer-events: none;
724
+ -webkit-user-select: none;
725
+ -moz-user-select: none;
726
+ -ms-user-select: none;
727
+ user-select: none;
728
+ }
729
+
730
+ .yjd-rich-editor .link-popup.visible {
731
+ display: block !important;
732
+ }
733
+
734
+ .yjd-rich-editor .link-popup-content {
735
+ display: flex;
736
+ flex-direction: column;
737
+ gap: 16px;
738
+ padding: 16px;
739
+ }
740
+ .yjd-rich-editor .yjd-input-upload-group{
741
+ display: flex;
742
+ align-items: center;
743
+ gap: 4px;
744
+ }
745
+ .yjd-rich-editor .yjd-custom-upload-button {
746
+ display: flex !important;
747
+ align-items: center;
748
+ justify-content: center;
749
+ padding: 0;
750
+ border: 1px solid #E1E1E1;
751
+ background: #FFF;
752
+ width: 34px;
753
+ height: 34px;
754
+ border-radius: 10px;
755
+ cursor: pointer;
756
+ }
757
+ .yjd-rich-editor .yjd-suggestions-list {
758
+ display: flex;
759
+ flex-wrap: wrap;
760
+ gap: 8px;
761
+ flex: 1 1 auto;
762
+ min-width: 0;
763
+ max-width: 100%;
764
+ }
765
+ .yjd-rich-editor .yjd-suggestion-button{
766
+ border: none;
767
+ display: flex;
768
+ padding: 4px 10px;
769
+ justify-content: center;
770
+ align-items: center;
771
+ border-radius: 30px;
772
+ background: #F5F5F5;
773
+ cursor: pointer;
774
+ font-size: 14px;
775
+ color: #252424 !important;
776
+ }
777
+ .yjd-rich-editor .yjd-select-input{
778
+ -webkit-appearance: none;
779
+ -moz-appearance: none;
780
+ appearance: none;
781
+ cursor: pointer;
782
+ padding: 10px 10px 10px 10px;
783
+ border-radius: 10px;
784
+ border: 1px solid #E1E1E1;
785
+ max-height: 37px;
786
+ align-items: center;
787
+ background-image: url('data:image/svg+xml;utf8,%3Csvg xmlns="http://www.w3.org/2000/svg" width="10" height="10" viewBox="0 0 10 10" fill="none"%3E%3Cpath d="M4.55859 7.94141C4.80273 8.18555 5.19922 8.18555 5.44336 7.94141L9.19336 4.19141C9.4375 3.94727 9.4375 3.55078 9.19336 3.30664C8.94922 3.0625 8.55274 3.0625 8.30859 3.30664L5 6.61523L1.69141 3.30859C1.44727 3.06445 1.05078 3.06445 0.806641 3.30859C0.5625 3.55273 0.5625 3.94922 0.806641 4.19336L4.55664 7.94336L4.55859 7.94141Z" fill="%23A4A7AE" /%3E%3C/svg%3E');
788
+ background-repeat: no-repeat;
789
+ background-position: right 10px center;
790
+ background-size: 10px;
791
+ font-size: 14px;
792
+ color: #252424 !important;
793
+ }
794
+ .yjd-rich-editor .yjd-select-input:focus {
795
+ outline: none;
796
+ border-color: #3b82f6;
797
+ box-shadow: 0 0 0 1px rgba(59, 130, 246, 0.1);
798
+ }
799
+
800
+
801
+ /* === TABLE POPUP === */
802
+ .yjd-rich-editor .table-popup {
803
+ position: absolute;
804
+ background: #fff;
805
+ font-family: 'Lato', sans-serif;
806
+ display: none;
807
+ border: 1px solid #d1d5db;
808
+ border-radius: 6.9px;
809
+ box-shadow: 0 4px 16px rgba(0, 0, 0, 0.1);
810
+ z-index: 1000;
811
+ /* Prevent focus and click on popup container */
812
+ pointer-events: none;
813
+ -webkit-user-select: none;
814
+ -moz-user-select: none;
815
+ -ms-user-select: none;
816
+ user-select: none;
817
+ }
818
+
819
+ .yjd-rich-editor .table-popup.visible {
820
+ display: block !important;
821
+ }
822
+
823
+ .yjd-rich-editor .table-popup-content {
824
+ padding: 8px;
825
+ display: flex;
826
+ flex-direction: column;
827
+ align-items: center;
828
+ gap: 12px;
829
+ position: relative;
830
+ }
831
+
832
+ .yjd-rich-editor .table-popup-content>* {
833
+ position: relative;
834
+ width: 100%;
835
+ }
836
+
837
+ /* Kẻ đường phân cách giữa các phần tử, kéo dài vượt padding */
838
+ .yjd-rich-editor .table-popup-content>*:not(:last-child)::after {
839
+ content: "";
840
+ position: absolute;
841
+ bottom: -8px;
842
+ /* nửa khoảng cách của gap: 12px */
843
+ left: -8px;
844
+ /* tràn ra ngoài padding 8px */
845
+ right: -8px;
846
+ height: 1px;
847
+ background-color: #e5e7eb;
848
+ }
849
+
850
+ .yjd-rich-editor .table-grid-selector {
851
+ display: grid;
852
+ grid-template-columns: repeat(8, 1fr);
853
+ gap: 1px;
854
+ border-bottom: 1px solid rgb(238, 238, 238);
855
+ }
856
+
857
+ .yjd-rich-editor .table-size-display{
858
+ display: flex;
859
+ align-items: center;
860
+ justify-content: center;
861
+ font-family: 'Lato', sans-serif;
862
+ color: #252424 !important;
863
+ font-size: 12px;
864
+ font-style: normal;
865
+ font-weight: 400;
866
+ line-height: normal;
867
+ }
868
+ .yjd-rich-editor .table-grid-cell {
869
+ width: 20px;
870
+ height: 20px;
871
+ background: #fff;
872
+ border: 1px solid rgb(238, 238, 238);
873
+ cursor: pointer;
874
+ transition: background-color 0.1s ease;
875
+ border-radius: 2px;
876
+ }
877
+
878
+ .yjd-rich-editor .table-grid-cell:hover,
879
+ .yjd-rich-editor .table-grid-cell.highlighted {
880
+ background: #EEEEEE;
881
+ }
882
+
883
+ /* === TABLE STYLES === */
884
+ .yjd-rich-editor .rich-editor-table {
885
+ border-collapse: collapse;
886
+ width: 100%;
887
+ /* Never exceed the editor's content width, even mid-resize. */
888
+ max-width: 100%;
889
+ box-sizing: border-box;
890
+ margin: 16px 0;
891
+ font-size: 14px;
892
+ line-height: 1.5;
893
+ position: relative;
894
+ display: table;
895
+ table-layout: fixed;
896
+ }
897
+
898
+ .yjd-rich-editor .rich-editor-table td {
899
+ /* border-box so a cell's min-width includes its padding+border — otherwise
900
+ padding/borders push the table past the width set during resize. */
901
+ box-sizing: border-box;
902
+ border: 1px solid #d1d5db;
903
+ padding: 8px 12px;
904
+ min-height: 28px;
905
+ vertical-align: top;
906
+ background: #fff;
907
+ overflow-wrap: break-word;
908
+ }
909
+
910
+ .yjd-rich-editor .rich-editor-table td:focus {
911
+ outline: 2px solid #3b82f6;
912
+ outline-offset: -2px;
913
+ background: #fefefe;
914
+ }
915
+
916
+ /* === TABLE TOOLBAR === */
917
+ .yjd-rich-editor .table-toolbar {
918
+ position: absolute;
919
+ display: none;
920
+ z-index: 1002;
921
+ background: transparent;
922
+ border: none;
923
+ border-radius: 6.9px;
924
+ opacity: 0;
925
+ pointer-events: none;
926
+ }
927
+
928
+ .yjd-rich-editor .table-toolbar-group {
929
+ display: flex;
930
+ gap: 8px;
931
+ align-items: center;
932
+ }
933
+
934
+ .yjd-rich-editor .table-toolbar.visible {
935
+ display: block;
936
+ opacity: 1;
937
+ pointer-events: auto;
938
+ transform: translateY(0);
939
+ }
940
+
941
+ .yjd-rich-editor .table-toolbar-btn {
942
+ padding: 4px;
943
+ display: inline-flex;
944
+ align-items: center;
945
+ justify-content: center;
946
+ border-radius: 4px;
947
+ color: #374151;
948
+ border:none;
949
+ background:transparent;
950
+ font-size: 12px;
951
+ font-weight: 500;
952
+ cursor: pointer;
953
+ transition: all 0.15s ease;
954
+ white-space: nowrap;
955
+ }
956
+
957
+ .yjd-rich-editor .table-toolbar-btn:hover {
958
+ background: #f3f4f6;
959
+ color: #111827;
960
+ }
961
+
962
+ .yjd-rich-editor .table-toolbar-btn:active {
963
+ background: #e5e7eb;
964
+ border-color: #9ca3af;
965
+ color: #136FDF !important;
966
+ }
967
+
968
+ /* Responsive table toolbar */
969
+ @media (max-width: 768px) {
970
+ .yjd-rich-editor .table-toolbar-container {
971
+ flex-wrap: wrap;
972
+ max-width: 200px;
973
+ gap: 2px;
974
+ }
975
+
976
+ .yjd-rich-editor .table-toolbar-btn {
977
+ height: 24px;
978
+ min-width: 24px;
979
+ font-size: 10px;
980
+ padding: 2px 4px;
981
+ }
982
+ }
983
+
984
+ /* === TEXT ALIGN PICKER === */
985
+ .yjd-rich-editor .text-align-picker-popup {
986
+ position: absolute;
987
+ background: #fff;
988
+ display: none;
989
+ border: 1px solid #d1d5db;
990
+ border-radius: 6.9px;
991
+ padding: 8px 4px 0 4px;
992
+ box-shadow: 0 4px 16px rgba(0, 0, 0, 0.1);
993
+ z-index: 1000;
994
+ /* Prevent focus and click on popup container */
995
+ pointer-events: none;
996
+ -webkit-user-select: none;
997
+ -moz-user-select: none;
998
+ -ms-user-select: none;
999
+ user-select: none;
1000
+ }
1001
+
1002
+ .yjd-rich-editor .text-align-picker-popup.visible {
1003
+ display: block !important;
1004
+ }
1005
+
1006
+ .yjd-rich-editor .align-button-container {
1007
+ display: flex;
1008
+ flex-direction: column;
1009
+ gap: 2px;
1010
+ width: 98px;
1011
+ height: 115px;
1012
+
1013
+ }
1014
+ .yjd-rich-editor .align-button .icon-wrapper{
1015
+ display: flex;
1016
+ margin-left: 8px;
1017
+ align-items: center;
1018
+ justify-content: center;
1019
+ }
1020
+ .yjd-rich-editor .align-button .label-text{
1021
+ color: #252424;
1022
+ font-size: 12px;
1023
+ font-style: normal;
1024
+ font-weight: 400;
1025
+ line-height: normal;
1026
+ }
1027
+
1028
+ .yjd-rich-editor .align-button {
1029
+ height: 24px;
1030
+ border-radius: 3.456px;
1031
+ background: #fff;
1032
+ border: none;
1033
+ align-items: center;
1034
+ display: flex;
1035
+ width: 100%;
1036
+ cursor: pointer;
1037
+ padding: 0;
1038
+ gap: 4px;
1039
+ /* Allow interaction with align buttons */
1040
+ pointer-events: auto;
1041
+ }
1042
+
1043
+ .yjd-rich-editor .align-button:hover {
1044
+ background: #f3f4f6;
1045
+ border-color: #9ca3af;
1046
+ }
1047
+
1048
+ .yjd-rich-editor .align-button.active {
1049
+ background: #e5e7eb;
1050
+ border-color: #6b7280;
1051
+ }
1052
+
1053
+ .yjd-rich-editor .align-button svg {
1054
+ width: 16px;
1055
+ height: 16px;
1056
+ color: #374151;
1057
+ }
1058
+
1059
+ .yjd-rich-editor .align-button.active svg {
1060
+ color: #1f2937;
1061
+ }
1062
+
1063
+ /* === LIST PICKER === */
1064
+ .yjd-rich-editor .list-picker-popup {
1065
+ position: absolute;
1066
+ background: #fff;
1067
+ display: none;
1068
+ border-radius: 6.9px;
1069
+ padding: 12px;
1070
+ box-shadow: 0 4px 16px rgba(0, 0, 0, 0.1);
1071
+ z-index: 1000;
1072
+ /* Prevent focus and click on popup container */
1073
+ pointer-events: none;
1074
+ -webkit-user-select: none;
1075
+ -moz-user-select: none;
1076
+ -ms-user-select: none;
1077
+ user-select: none;
1078
+ }
1079
+
1080
+ .yjd-rich-editor .list-picker-popup.visible {
1081
+ display: block !important;
1082
+ }
1083
+
1084
+ .yjd-rich-editor .list-button-container {
1085
+ display: grid;
1086
+ grid-template-columns: repeat(3, 1fr);
1087
+ align-items: center;
1088
+ gap: 12px 8px;
1089
+ }
1090
+
1091
+ .yjd-rich-editor .list-button {
1092
+
1093
+ border: none;
1094
+ border-radius: 3.46px;
1095
+ display: flex;
1096
+ align-items: center;
1097
+ justify-content: center;
1098
+ cursor: pointer;
1099
+ background: transparent;
1100
+ padding: 4px;
1101
+ }
1102
+
1103
+ .yjd-rich-editor .list-button:hover {
1104
+ background: #f3f4f6;
1105
+ }
1106
+
1107
+ .yjd-rich-editor .list-button.active {
1108
+ background: #eeeeee;
1109
+ }
1110
+
1111
+ .yjd-rich-editor .list-button svg {
1112
+ height: 16px;
1113
+ color: #374151;
1114
+ }
1115
+
1116
+ .yjd-rich-editor .list-button.active svg {
1117
+ color: #fff;
1118
+ }
1119
+
1120
+ /* === LIST FORMATTING === */
1121
+ .yjd-rich-editor .rich-editor-area ul.checklist {
1122
+ list-style: none;
1123
+ padding-left: 0;
1124
+ }
1125
+
1126
+ .yjd-rich-editor .rich-editor-area ul.checklist li {
1127
+ position: relative;
1128
+ padding-left: 25px;
1129
+ margin-bottom: 4px;
1130
+ }
1131
+
1132
+ .yjd-rich-editor .rich-editor-area ul.checklist li input[type="checkbox"] {
1133
+ position: absolute;
1134
+ left: 0;
1135
+ top: 2px;
1136
+ margin: 0;
1137
+ cursor: pointer;
1138
+ }
1139
+
1140
+ .yjd-rich-editor .rich-editor-area ul {
1141
+ margin: 12px 0;
1142
+ padding-left: 20px;
1143
+ }
1144
+
1145
+ .yjd-rich-editor .rich-editor-area ol {
1146
+ margin: 12px 0;
1147
+ padding-left: 20px;
1148
+ }
1149
+
1150
+ .yjd-rich-editor .rich-editor-area li {
1151
+ margin-bottom: 4px;
1152
+ line-height: 1.6;
1153
+ }
1154
+
1155
+ /* === INDENT FORMATTING === */
1156
+ .yjd-rich-editor .rich-editor-area .indented {
1157
+ transition: padding-left 0.2s ease;
1158
+ }
1159
+
1160
+ .yjd-rich-editor .rich-editor-area [style*="padding-left"] {
1161
+ transition: padding-left 0.2s ease;
1162
+ }
1163
+
1164
+ /* Indent button styles */
1165
+ .yjd-rich-editor .indent-increase-btn svg,
1166
+ .yjd-rich-editor .indent-decrease-btn svg {
1167
+ width: 16px;
1168
+ height: 16px;
1169
+ fill: #454545;
1170
+ }
1171
+
1172
+ .yjd-rich-editor .indent-increase-btn:hover svg,
1173
+ .yjd-rich-editor .indent-decrease-btn:hover svg {
1174
+ fill: #454545;
1175
+ }
1176
+
1177
+ .yjd-rich-editor .indent-increase-btn:disabled,
1178
+ .yjd-rich-editor .indent-decrease-btn:disabled {
1179
+ opacity: 0.5;
1180
+ cursor: not-allowed;
1181
+ }
1182
+
1183
+ .yjd-rich-editor .indent-increase-btn:disabled svg,
1184
+ .yjd-rich-editor .indent-decrease-btn:disabled svg {
1185
+ fill: #9ca3af;
1186
+ }
1187
+
1188
+ /* === EMOJI PICKER === */
1189
+ .yjd-rich-editor .emoji-picker-popup {
1190
+ position: absolute;
1191
+ z-index: 10000;
1192
+ background: #fff;
1193
+ border-radius: 8px;
1194
+ padding: 8px;
1195
+ box-shadow: 0 4px 16px rgba(0, 0, 0, 0.15);
1196
+ display: none;
1197
+ overflow-y: auto;
1198
+ /* Prevent focus and click on popup container */
1199
+ pointer-events: none;
1200
+ -webkit-user-select: none;
1201
+ -moz-user-select: none;
1202
+ -ms-user-select: none;
1203
+ user-select: none;
1204
+ }
1205
+
1206
+ .yjd-rich-editor .emoji-picker-popup.visible {
1207
+ display: block;
1208
+ }
1209
+
1210
+ .yjd-rich-editor .emoji-grid {
1211
+ display: grid;
1212
+ grid-template-columns: repeat(10, 1fr);
1213
+ gap: 4px;
1214
+ max-height: 240px;
1215
+ overflow-y: auto;
1216
+ }
1217
+ .yjd-rich-editor .emoji-text-message{
1218
+ margin-top: 4px;
1219
+ color: #71787C;
1220
+ text-align: center;
1221
+ font-family: 'Segoe UI', Arial, sans-serif;
1222
+ font-size: 12px;
1223
+ font-style: normal;
1224
+ font-weight: 400;
1225
+ line-height: normal;
1226
+ }
1227
+ .yjd-rich-editor .emoji-button {
1228
+ width: 28px;
1229
+ height: 28px;
1230
+ border: none;
1231
+ background: none;
1232
+ padding: 0;
1233
+ border-radius: 4px;
1234
+ cursor: pointer;
1235
+ font-size: 20px !important;
1236
+ display: flex;
1237
+ align-items: center;
1238
+ justify-content: center;
1239
+ transition: background-color 0.2s ease;
1240
+ /* Allow interaction with buttons */
1241
+ pointer-events: auto;
1242
+ }
1243
+
1244
+ .yjd-rich-editor .emoji-button:hover {
1245
+ background-color: #f3f4f6;
1246
+ }
1247
+
1248
+ .yjd-rich-editor .emoji {
1249
+ font-size: 1.1em;
1250
+ line-height: 1;
1251
+ }
1252
+
1253
+ /* === IMAGE POPUP === */
1254
+ .yjd-rich-editor .image-popup {
1255
+ position: absolute;
1256
+ z-index: 10000;
1257
+ background: #fff;
1258
+ font-family: 'Lato', sans-serif;
1259
+ border-radius: 10px;
1260
+ box-shadow: 0 4px 16px rgba(0, 0, 0, 0.15);
1261
+ display: none;
1262
+ margin: 0;
1263
+ box-shadow: 0px 1px 5px 0px rgba(0, 0, 0, 0.18);
1264
+ /* Prevent focus and click on popup container */
1265
+ pointer-events: none;
1266
+ -webkit-user-select: none;
1267
+ -moz-user-select: none;
1268
+ -ms-user-select: none;
1269
+ user-select: none;
1270
+ }
1271
+
1272
+ .yjd-rich-editor .image-popup.visible {
1273
+ display: block;
1274
+ }
1275
+
1276
+ .yjd-rich-editor .image-popup-content {
1277
+ display: flex;
1278
+ flex-direction: column;
1279
+ gap: 16px;
1280
+ padding: 16px;
1281
+ }
1282
+
1283
+
1284
+
1285
+ .yjd-rich-editor .image-input-container {
1286
+ gap: 8px;
1287
+ display: flex;
1288
+ flex-direction: column;
1289
+ }
1290
+
1291
+ .yjd-rich-editor .image-input-hidden{
1292
+ display: none;
1293
+ }
1294
+
1295
+
1296
+ /* === VIDEO POPUP === */
1297
+ .yjd-rich-editor .video-popup {
1298
+ position: absolute;
1299
+ z-index: 10000;
1300
+ background: #fff;
1301
+ font-family: 'Lato', sans-serif;
1302
+ border-radius: 10px;
1303
+ box-shadow: 0 4px 16px rgba(0, 0, 0, 0.15);
1304
+ display: none;
1305
+ margin: 0;
1306
+ box-shadow: 0px 1px 5px 0px rgba(0, 0, 0, 0.18);
1307
+ /* Prevent focus and click on popup container */
1308
+ pointer-events: none;
1309
+ -webkit-user-select: none;
1310
+ -moz-user-select: none;
1311
+ -ms-user-select: none;
1312
+ user-select: none;
1313
+ }
1314
+
1315
+ .yjd-rich-editor .video-popup.visible {
1316
+ display: block;
1317
+ }
1318
+
1319
+ .yjd-rich-editor .video-popup-content {
1320
+ display: flex;
1321
+ flex-direction: column;
1322
+ gap: 16px;
1323
+ padding: 16px;
1324
+ }
1325
+
1326
+ .yjd-rich-editor .video-input-container {
1327
+ gap: 8px;
1328
+ display: flex;
1329
+ flex-direction: column;
1330
+ }
1331
+
1332
+ /* === INSERTED MEDIA === */
1333
+ .yjd-rich-editor .inserted-image,
1334
+ .yjd-rich-editor .inserted-video {
1335
+ max-width: 100%;
1336
+ height: auto;
1337
+ margin: 4px 0;
1338
+ border-radius: 4px;
1339
+ display: block;
1340
+ }
1341
+
1342
+ .yjd-rich-editor .inserted-video {
1343
+ background: #000;
1344
+ }
1345
+
1346
+ /* === TAG POPUP === */
1347
+ .yjd-rich-editor .tag-popup {
1348
+ position: absolute;
1349
+ z-index: 10000;
1350
+ background: #fff;
1351
+ font-family: 'Lato', sans-serif;
1352
+ border-radius: 10px;
1353
+ box-shadow: 0 4px 16px rgba(0, 0, 0, 0.15);
1354
+ display: none;
1355
+ margin: 0;
1356
+ box-shadow: 0px 1px 5px 0px rgba(0, 0, 0, 0.18);
1357
+ /* Prevent focus and click on popup container */
1358
+ pointer-events: none;
1359
+ -webkit-user-select: none;
1360
+ -moz-user-select: none;
1361
+ -ms-user-select: none;
1362
+ user-select: none;
1363
+ }
1364
+ .tag-popup {
1365
+ max-height: 80vh;
1366
+ /* không vượt quá 80% chiều cao viewport */
1367
+ overflow-y: auto;
1368
+ /* chỉ cuộn khi cần */
1369
+ }
1370
+
1371
+ .tag-suggestions-container {
1372
+ max-height: 200px;
1373
+ /* nếu nhiều gợi ý thì chỉ cho hiển thị tối đa 200px */
1374
+ overflow-y: auto;
1375
+ }
1376
+ .yjd-rich-editor .tag-popup.visible {
1377
+ display: block;
1378
+ }
1379
+
1380
+ .yjd-rich-editor .tag-popup-content {
1381
+ display: flex;
1382
+ flex-direction: column;
1383
+ gap: 16px;
1384
+ padding: 16px;
1385
+ }
1386
+
1387
+
1388
+ .yjd-rich-editor .tag-type-container{
1389
+ gap: 8px;
1390
+ display: flex;
1391
+ flex-direction: column;
1392
+ }
1393
+
1394
+ /* === CUSTOM TAGS === */
1395
+ .yjd-rich-editor .custom-tag {
1396
+ display: inline-block;
1397
+ padding: 2px 6px;
1398
+ border-radius: 12px;
1399
+ font-size: 0.85em;
1400
+ font-weight: 500;
1401
+ cursor: pointer;
1402
+ margin: 0 2px;
1403
+ }
1404
+
1405
+ .yjd-rich-editor .custom-tag.tag-mention {
1406
+ background: #dbeafe;
1407
+ color: #1d4ed8;
1408
+ }
1409
+
1410
+ .yjd-rich-editor .custom-tag.tag-hashtag {
1411
+ background: #dcfce7;
1412
+ color: #166534;
1413
+ }
1414
+
1415
+ .yjd-rich-editor .custom-tag.tag-custom {
1416
+ background: #fef3c7;
1417
+ color: #92400e;
1418
+ }
1419
+
1420
+ .yjd-rich-editor .custom-tag:hover {
1421
+ opacity: 0.8;
1422
+ }
1423
+
1424
+ /* === IMPORT POPUP === */
1425
+ .yjd-rich-editor .import-popup {
1426
+ position: absolute;
1427
+ z-index: 10000;
1428
+ background: #fff;
1429
+ border: 1px solid #d1d5db;
1430
+ border-radius: 8px;
1431
+ box-shadow: 0 4px 16px rgba(0, 0, 0, 0.15);
1432
+ display: none;
1433
+ width: 400px;
1434
+ max-width: 90vw;
1435
+ /* Prevent focus and click on popup container */
1436
+ pointer-events: none;
1437
+ -webkit-user-select: none;
1438
+ -moz-user-select: none;
1439
+ -ms-user-select: none;
1440
+ user-select: none;
1441
+ }
1442
+
1443
+ .yjd-rich-editor .import-popup.visible {
1444
+ display: block;
1445
+ }
1446
+
1447
+ .yjd-rich-editor .import-popup-content {
1448
+ padding: 20px;
1449
+ }
1450
+
1451
+ .yjd-rich-editor .import-popup-title {
1452
+ margin: 0 0 20px 0;
1453
+ font-size: 18px;
1454
+ font-weight: 600;
1455
+ color: #1f2937;
1456
+ }
1457
+
1458
+ .yjd-rich-editor .import-type-container {
1459
+ margin-bottom: 20px;
1460
+ }
1461
+
1462
+ .yjd-rich-editor .import-input-label {
1463
+ display: block;
1464
+ margin-bottom: 8px;
1465
+ font-size: 14px;
1466
+ font-weight: 500;
1467
+ color: #374151;
1468
+ }
1469
+
1470
+ .yjd-rich-editor .import-type-select {
1471
+ width: 100%;
1472
+ padding: 10px 12px;
1473
+ border: 1px solid #d1d5db;
1474
+ border-radius: 6px;
1475
+ font-size: 14px;
1476
+ background: white;
1477
+ color: #374151;
1478
+ cursor: pointer;
1479
+ box-sizing: border-box;
1480
+ }
1481
+
1482
+ .yjd-rich-editor .import-type-select:focus {
1483
+ outline: none;
1484
+ border-color: #3b82f6;
1485
+ box-shadow: 0 0 0 1px rgba(59, 130, 246, 0.1);
1486
+ }
1487
+
1488
+ .yjd-rich-editor .import-file-input {
1489
+ width: 100%;
1490
+ padding: 10px 12px;
1491
+ border: 1px solid #d1d5db;
1492
+ border-radius: 6px;
1493
+ font-size: 14px;
1494
+ background: white;
1495
+ color: #374151;
1496
+ margin-bottom: 16px;
1497
+ cursor: pointer;
1498
+ box-sizing: border-box;
1499
+ }
1500
+
1501
+ .yjd-rich-editor .import-file-input:disabled {
1502
+ background-color: #f3f4f6;
1503
+ cursor: not-allowed;
1504
+ opacity: 0.5;
1505
+ }
1506
+
1507
+ .yjd-rich-editor .import-file-input:focus {
1508
+ outline: none;
1509
+ border-color: #3b82f6;
1510
+ box-shadow: 0 0 0 1px rgba(59, 130, 246, 0.1);
1511
+ }
1512
+
1513
+ .yjd-rich-editor .import-file-info {
1514
+ padding: 12px;
1515
+ background-color: #f9fafb;
1516
+ border: 1px solid #e5e7eb;
1517
+ border-radius: 6px;
1518
+ margin-bottom: 16px;
1519
+ font-size: 14px;
1520
+ color: #374151;
1521
+ }
1522
+
1523
+ .yjd-rich-editor .import-file-info div {
1524
+ margin-bottom: 4px;
1525
+ }
1526
+
1527
+ .yjd-rich-editor .import-file-info div:last-child {
1528
+ margin-bottom: 0;
1529
+ }
1530
+
1531
+ .yjd-rich-editor .import-button-container {
1532
+ display: flex;
1533
+ justify-content: flex-end;
1534
+ gap: 10px;
1535
+ margin-top: 20px;
1536
+ }
1537
+
1538
+ .yjd-rich-editor .import-button {
1539
+ padding: 10px 20px;
1540
+ border: 1px solid #d1d5db;
1541
+ border-radius: 6px;
1542
+ font-size: 14px;
1543
+ font-weight: 500;
1544
+ cursor: pointer;
1545
+ transition: all 0.2s;
1546
+ }
1547
+
1548
+ .yjd-rich-editor .import-button:hover {
1549
+ background-color: #f3f4f6;
1550
+ }
1551
+
1552
+ .yjd-rich-editor .import-button.import-button-main {
1553
+ background-color: #3b82f6;
1554
+ color: white;
1555
+ border-color: #3b82f6;
1556
+ }
1557
+
1558
+ .yjd-rich-editor .import-button.import-button-main:hover {
1559
+ background-color: #2563eb;
1560
+ }
1561
+
1562
+ .yjd-rich-editor .import-button.import-button-main:disabled {
1563
+ background-color: #9ca3af;
1564
+ border-color: #9ca3af;
1565
+ cursor: not-allowed;
1566
+ }
1567
+
1568
+ .yjd-rich-editor .import-button.cancel-button {
1569
+ background-color: white;
1570
+ color: #6b7280;
1571
+ }
1572
+
1573
+ .yjd-rich-editor .import-button.cancel-button:hover {
1574
+ background-color: #f9fafb;
1575
+ }
1576
+
1577
+ /* === IMPORTED CONTENT === */
1578
+ .yjd-rich-editor .imported-content {
1579
+ margin: 16px 0;
1580
+ padding: 16px;
1581
+ border: 1px dashed #d1d5db;
1582
+ border-radius: 6px;
1583
+ background-color: #f9fafb;
1584
+ }
1585
+
1586
+ .yjd-rich-editor .imported-content.html-content {
1587
+ border-color: #3b82f6;
1588
+ background-color: #eff6ff;
1589
+ }
1590
+
1591
+ .yjd-rich-editor .imported-content.excel-content {
1592
+ border-color: #10b981;
1593
+ background-color: #f0fdf4;
1594
+ }
1595
+
1596
+ .yjd-rich-editor .imported-content.text-content {
1597
+ border-color: #f59e0b;
1598
+ background-color: #fffbeb;
1599
+ }
1600
+
1601
+ .yjd-rich-editor .imported-table {
1602
+ width: 100%;
1603
+ border-collapse: collapse;
1604
+ font-size: 14px;
1605
+ background: white;
1606
+ border-radius: 4px;
1607
+ overflow: hidden;
1608
+ box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
1609
+ }
1610
+
1611
+ .yjd-rich-editor .imported-table th,
1612
+ .yjd-rich-editor .imported-table td {
1613
+ padding: 12px;
1614
+ text-align: left;
1615
+ border-bottom: 1px solid #e5e7eb;
1616
+ }
1617
+
1618
+ .yjd-rich-editor .imported-table th {
1619
+ background-color: #f3f4f6;
1620
+ font-weight: 600;
1621
+ color: #374151;
1622
+ }
1623
+
1624
+ .yjd-rich-editor .imported-table tr:hover {
1625
+ background-color: #f9fafb;
1626
+ }
1627
+
1628
+ .yjd-rich-editor .imported-content p {
1629
+ margin: 8px 0;
1630
+ line-height: 1.6;
1631
+ color: #374151;
1632
+ }
1633
+
1634
+ .yjd-rich-editor .imported-content p:first-child {
1635
+ margin-top: 0;
1636
+ }
1637
+
1638
+ .yjd-rich-editor .imported-content p:last-child {
1639
+ margin-bottom: 0;
1640
+ }
1641
+
1642
+ /* === CODE VIEW === */
1643
+ .yjd-rich-editor .code-view-textarea {
1644
+ width: 100%;
1645
+ height: 500px;
1646
+ font-family: 'Consolas', 'Monaco', 'Courier New', monospace;
1647
+ font-size: 14px;
1648
+ line-height: 1.5;
1649
+ padding: 16px;
1650
+ background-color: #f8fafc;
1651
+ color: #374151;
1652
+ resize: vertical;
1653
+ border: none;
1654
+ outline: none;
1655
+ white-space: pre;
1656
+ word-wrap: break-word;
1657
+ tab-size: 2;
1658
+ box-sizing: border-box;
1659
+ }
1660
+
1661
+ /* Responsive adjustments */
1662
+ @media (max-width: 768px) {
1663
+ .yjd-rich-editor .code-view-textarea {
1664
+ font-size: 13px;
1665
+ padding: 12px;
1666
+ }
1667
+
1668
+ .yjd-rich-editor.code-view-active::after {
1669
+ top: 5px;
1670
+ right: 5px;
1671
+ font-size: 11px;
1672
+ padding: 3px 6px;
1673
+ }
1674
+ }
1675
+
1676
+ /* === RESIZE HANDLES === */
1677
+ .yjd-rich-editor .resize-handles-container {
1678
+ position: absolute;
1679
+ pointer-events: none;
1680
+ z-index: 997; /* Lower than all toolbar elements */
1681
+ display: none;
1682
+ }
1683
+
1684
+ .yjd-rich-editor .resize-handles-container.active {
1685
+ display: block;
1686
+ }
1687
+
1688
+ .yjd-rich-editor .resize-handle {
1689
+ position: absolute;
1690
+ width: 8px;
1691
+ height: 8px;
1692
+ background-color: #3b82f6;
1693
+ border: 1px solid #fff;
1694
+ border-radius: 50%;
1695
+ pointer-events: auto;
1696
+ box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);
1697
+ transition: all 0.2s ease;
1698
+ z-index: 999; /* Higher than container but lower than toolbars */
1699
+ }
1700
+
1701
+ .yjd-rich-editor .resize-handle:hover {
1702
+ background-color: #2563eb;
1703
+ transform: scale(1.2);
1704
+ box-shadow: 0 2px 6px rgba(0, 0, 0, 0.3);
1705
+ }
1706
+
1707
+ .yjd-rich-editor .resize-handle-nw {
1708
+ top: -4px;
1709
+ left: -4px;
1710
+ cursor: nw-resize;
1711
+ }
1712
+
1713
+ .yjd-rich-editor .resize-handle-ne {
1714
+ top: -4px;
1715
+ right: -4px;
1716
+ cursor: ne-resize;
1717
+ }
1718
+
1719
+ .yjd-rich-editor .resize-handle-sw {
1720
+ bottom: -4px;
1721
+ left: -4px;
1722
+ cursor: sw-resize;
1723
+ }
1724
+
1725
+ .yjd-rich-editor .resize-handle-se {
1726
+ bottom: -4px;
1727
+ right: -4px;
1728
+ cursor: se-resize;
1729
+ }
1730
+
1731
+ /* Resizing state styles */
1732
+ .yjd-rich-editor .inserted-image.resizing,
1733
+ .yjd-rich-editor .inserted-video.resizing,
1734
+ .yjd-rich-editor .rich-editor-table.resizing {
1735
+ outline: 2px solid #3b82f6;
1736
+ outline-offset: 2px;
1737
+ opacity: 0.8;
1738
+ }
1739
+
1740
+ .yjd-rich-editor .inserted-image.resizing {
1741
+ -webkit-user-select: none;
1742
+ user-select: none;
1743
+ pointer-events: none;
1744
+ }
1745
+
1746
+ .yjd-rich-editor .inserted-video.resizing {
1747
+ -webkit-user-select: none;
1748
+ user-select: none;
1749
+ pointer-events: none;
1750
+ }
1751
+
1752
+ .yjd-rich-editor .rich-editor-table.resizing {
1753
+ -webkit-user-select: none;
1754
+ user-select: none;
1755
+ }
1756
+
1757
+ .yjd-rich-editor .rich-editor-table.resizing td {
1758
+ pointer-events: none;
1759
+ }
1760
+
1761
+ /* Selection indicator for resizable elements */
1762
+ .yjd-rich-editor .inserted-image:hover,
1763
+ .yjd-rich-editor .inserted-video:hover,
1764
+ .yjd-rich-editor .rich-editor-table:hover {
1765
+ outline: 1px solid #3b82f6;
1766
+ outline-offset: 1px;
1767
+ cursor: pointer;
1768
+ }
1769
+
1770
+
1771
+
1772
+ /* Responsive resize handles */
1773
+ @media (max-width: 768px) {
1774
+ .yjd-rich-editor .resize-handle {
1775
+ width: 12px;
1776
+ height: 12px;
1777
+ }
1778
+
1779
+ .yjd-rich-editor .resize-handle-nw {
1780
+ top: -6px;
1781
+ left: -6px;
1782
+ }
1783
+
1784
+ .yjd-rich-editor .resize-handle-ne {
1785
+ top: -6px;
1786
+ right: -6px;
1787
+ }
1788
+
1789
+ .yjd-rich-editor .resize-handle-sw {
1790
+ bottom: -6px;
1791
+ left: -6px;
1792
+ }
1793
+
1794
+ .yjd-rich-editor .resize-handle-se {
1795
+ bottom: -6px;
1796
+ right: -6px;
1797
+ }
1798
+ }
1799
+
1800
+
1801
+
1802
+ /* === RESPONSIVE DESIGN === */
1803
+ /* Mobile and Tablet Styles - Screens smaller than 850px */
1804
+ @media (max-width: 849px) {
1805
+ /* Editor wrapper adjustments */
1806
+ .yjd-rich-editor {
1807
+ margin: 0;
1808
+ width: 100% !important;
1809
+ max-width: 100% !important;
1810
+ }
1811
+ .yjd-rich-editor .link-popup,
1812
+ .yjd-rich-editor .image-popup,
1813
+ .yjd-rich-editor .video-popup,
1814
+ .yjd-rich-editor .tag-popup {
1815
+ width: unset !important;
1816
+ }
1817
+ /* Editor area adjustments */
1818
+ .yjd-rich-editor .rich-editor-area {
1819
+ padding: 12px;
1820
+ min-height: 150px;
1821
+ font-size: 14px;
1822
+ line-height: 1.4;
1823
+ }
1824
+
1825
+ /* Status bar adjustments */
1826
+ .yjd-rich-editor .rich-editor-statusbar {
1827
+ padding: 6px 8px;
1828
+ font-size: 11px;
1829
+ flex-wrap: wrap;
1830
+ gap: 8px;
1831
+ }
1832
+
1833
+
1834
+ /* Popup and dropdown adjustments */
1835
+ .yjd-rich-editor .editor-popup,
1836
+ .yjd-rich-editor .editor-dropdown {
1837
+ position: fixed !important;
1838
+ top: 50% !important;
1839
+ left: 50% !important;
1840
+ transform: translate(-50%, -50%) !important;
1841
+ width: 90% !important;
1842
+ max-width: 320px !important;
1843
+ max-height: 80vh !important;
1844
+ overflow-y: auto;
1845
+ z-index: 10000;
1846
+ }
1847
+
1848
+ .yjd-rich-editor .editor-popup::before {
1849
+ content: '';
1850
+ position: fixed;
1851
+ top: 0;
1852
+ left: 0;
1853
+ width: 100%;
1854
+ height: 100%;
1855
+ background: rgba(0, 0, 0, 0.5);
1856
+ z-index: -1;
1857
+ }
1858
+
1859
+ /* Color picker adjustments */
1860
+ .yjd-rich-editor .color-picker {
1861
+ width: 100% !important;
1862
+ max-width: 280px !important;
1863
+ }
1864
+
1865
+ .yjd-rich-editor .color-picker-grid {
1866
+ grid-template-columns: repeat(6, 1fr) !important;
1867
+ gap: 8px !important;
1868
+ }
1869
+
1870
+ .yjd-rich-editor .color-picker-item {
1871
+ width: 32px !important;
1872
+ height: 32px !important;
1873
+ }
1874
+
1875
+ /* Table popup adjustments */
1876
+ .yjd-rich-editor .table-popup {
1877
+ max-width: 300px !important;
1878
+ }
1879
+
1880
+ .yjd-rich-editor .table-size-grid {
1881
+ grid-template-columns: repeat(8, 1fr) !important;
1882
+ gap: 2px !important;
1883
+ }
1884
+
1885
+ .yjd-rich-editor .table-size-cell {
1886
+ width: 24px !important;
1887
+ height: 24px !important;
1888
+ }
1889
+
1890
+ /* List picker adjustments */
1891
+ .yjd-rich-editor .list-picker {
1892
+ width: 100% !important;
1893
+ max-width: 250px !important;
1894
+ }
1895
+
1896
+ .yjd-rich-editor .list-picker-btn {
1897
+ padding: 12px !important;
1898
+ font-size: 14px !important;
1899
+ }
1900
+
1901
+ /* Text align picker adjustments */
1902
+ .yjd-rich-editor .text-align-picker {
1903
+ width: 100% !important;
1904
+ max-width: 200px !important;
1905
+ }
1906
+
1907
+ /* Media popups adjustments */
1908
+ .yjd-rich-editor .image-popup,
1909
+ .yjd-rich-editor .video-popup,
1910
+ .yjd-rich-editor .link-popup,
1911
+ .yjd-rich-editor .import-popup {
1912
+ width: 90% !important;
1913
+ max-width: 350px !important;
1914
+ }
1915
+
1916
+ .yjd-rich-editor .media-upload-area {
1917
+ min-height: 100px !important;
1918
+ padding: 20px !important;
1919
+ }
1920
+
1921
+ /* Tag popup */
1922
+ .yjd-rich-editor .tag-popup {
1923
+ width: 90% !important;
1924
+ max-width: 320px !important;
1925
+ }
1926
+
1927
+
1928
+
1929
+ /* Emoji picker adjustments */
1930
+ .yjd-rich-editor .emoji-picker {
1931
+ width: 100% !important;
1932
+ max-width: 300px !important;
1933
+ max-height: 350px !important;
1934
+ }
1935
+
1936
+ .yjd-rich-editor .emoji-grid {
1937
+ grid-template-columns: repeat(8, 1fr) !important;
1938
+ gap: 4px !important;
1939
+ }
1940
+
1941
+ .yjd-rich-editor .emoji-item {
1942
+ width: 32px !important;
1943
+ height: 32px !important;
1944
+ font-size: 18px !important;
1945
+ }
1946
+
1947
+ /* Code view adjustments */
1948
+ .yjd-rich-editor .code-view-textarea {
1949
+ font-size: 12px !important;
1950
+ padding: 8px !important;
1951
+ line-height: 1.3 !important;
1952
+ }
1953
+
1954
+ /* Content formatting adjustments */
1955
+ .yjd-rich-editor .rich-editor-area h1 {
1956
+ font-size: 1.5em !important;
1957
+ margin: 0.5em 0 !important;
1958
+ }
1959
+
1960
+ .yjd-rich-editor .rich-editor-area h2 {
1961
+ font-size: 1.3em !important;
1962
+ margin: 0.5em 0 !important;
1963
+ }
1964
+
1965
+ .yjd-rich-editor .rich-editor-area h3 {
1966
+ font-size: 1.1em !important;
1967
+ margin: 0.5em 0 !important;
1968
+ }
1969
+
1970
+ .yjd-rich-editor .rich-editor-area p {
1971
+ margin: 0.8em 0 !important;
1972
+ }
1973
+
1974
+ .yjd-rich-editor .rich-editor-area ul,
1975
+ .yjd-rich-editor .rich-editor-area ol {
1976
+ padding-left: 20px !important;
1977
+ margin: 0.8em 0 !important;
1978
+ }
1979
+
1980
+ .yjd-rich-editor .rich-editor-area blockquote {
1981
+ padding-left: 12px !important;
1982
+ margin: 0.8em 0 !important;
1983
+ font-size: 14px !important;
1984
+ }
1985
+
1986
+ .yjd-rich-editor .rich-editor-area table {
1987
+ font-size: 13px !important;
1988
+ overflow-x: auto !important;
1989
+ display: block !important;
1990
+ white-space: nowrap !important;
1991
+ }
1992
+
1993
+ .yjd-rich-editor .rich-editor-area th,
1994
+ .yjd-rich-editor .rich-editor-area td {
1995
+ padding: 6px 8px !important;
1996
+ min-width: 60px !important;
1997
+ }
1998
+
1999
+
2000
+ }
2001
+
2002
+ @media (max-width: 290px) {
2003
+ .yjd-rich-editor .emoji-picker {
2004
+ max-width: calc(100vw - 20px) !important;
2005
+ }
2006
+
2007
+ .yjd-rich-editor .emoji-grid {
2008
+ grid-template-columns: repeat(auto-fit, minmax(30px, 1fr)) !important;
2009
+ }
2010
+ }
2011
+
2012
+ /* Print styles */
2013
+ @media print {
2014
+ .yjd-rich-editor .rich-editor-toolbar-1,
2015
+ .yjd-rich-editor .rich-editor-toolbar-2,
2016
+ .yjd-rich-editor .rich-editor-statusbar {
2017
+ display: none !important;
2018
+ }
2019
+
2020
+ .yjd-rich-editor {
2021
+ border: none !important;
2022
+ box-shadow: none !important;
2023
+ }
2024
+
2025
+ .yjd-rich-editor .rich-editor-area {
2026
+ padding: 0 !important;
2027
+ background: white !important;
2028
+ color: black !important;
2029
+ }
2030
+ }
2031
+
2032
+ /* === POPUP CONTAINER === */
2033
+ .yjd-rich-editor .rich-editor-popup-container {
2034
+ position: absolute;
2035
+ top: 0;
2036
+ left: 0;
2037
+ width: 100%;
2038
+ height: 100%;
2039
+ pointer-events: none;
2040
+ z-index: 1005;
2041
+ overflow: visible;
2042
+ max-height: 90%;
2043
+ /* không vượt quá chiều cao editor */
2044
+ overflow-y: auto;
2045
+ /* chỉ cuộn khi nội dung vượt quá */
2046
+ }
2047
+
2048
+ /* Allow interaction with interactive elements inside popups */
2049
+ .yjd-rich-editor .emoji-picker-popup button,
2050
+ .yjd-rich-editor .color-picker-popup button,
2051
+ .yjd-rich-editor .custom-select-popup button,
2052
+ .yjd-rich-editor .heading-select-popup button,
2053
+ .yjd-rich-editor .capitalization-select-popup button,
2054
+ .yjd-rich-editor .font-family-select-popup button,
2055
+ .yjd-rich-editor .line-height-select-popup button,
2056
+ .yjd-rich-editor .text-size-select-popup button,
2057
+ .yjd-rich-editor .link-popup button,
2058
+ .yjd-rich-editor .link-popup input,
2059
+ .yjd-rich-editor .link-popup select,
2060
+ .yjd-rich-editor .image-popup button,
2061
+ .yjd-rich-editor .image-popup input,
2062
+ .yjd-rich-editor .image-popup select,
2063
+ .yjd-rich-editor .video-popup button,
2064
+ .yjd-rich-editor .video-popup input,
2065
+ .yjd-rich-editor .video-popup select,
2066
+ .yjd-rich-editor .tag-popup button,
2067
+ .yjd-rich-editor .tag-popup input,
2068
+ .yjd-rich-editor .tag-popup select,
2069
+ .yjd-rich-editor .table-popup button,
2070
+ .yjd-rich-editor .table-popup input,
2071
+ .yjd-rich-editor .text-align-picker-popup button,
2072
+ .yjd-rich-editor .list-picker-popup button,
2073
+ .yjd-rich-editor .import-popup button,
2074
+ .yjd-rich-editor .import-popup input,
2075
+ .yjd-rich-editor .import-popup select,
2076
+ .yjd-rich-editor .yjd-button-confirm,
2077
+ .yjd-rich-editor .yjd-button-cancel,
2078
+ .yjd-rich-editor .yjd-input,
2079
+ .yjd-rich-editor .yjd-select-input,
2080
+ .yjd-rich-editor .yjd-custom-upload-button,
2081
+ .yjd-rich-editor .yjd-suggestion-button,
2082
+ .yjd-rich-editor .list-button,
2083
+ .yjd-rich-editor .table-toolbar-btn,
2084
+ .yjd-rich-editor .custom-color-input,
2085
+ .yjd-rich-editor .import-type-select,
2086
+ .yjd-rich-editor .custom-tag,
2087
+ .yjd-rich-editor .image-input-hidden,
2088
+ .yjd-rich-editor .video-input-hidden,
2089
+ .yjd-rich-editor .tag-type-select,
2090
+ .yjd-rich-editor .tag-value-input,
2091
+ .yjd-rich-editor .import-input,
2092
+ .yjd-rich-editor .import-file-input,
2093
+ .yjd-rich-editor .import-url-input,
2094
+ .yjd-rich-editor .import-text-input,
2095
+ .yjd-rich-editor .import-html-input,
2096
+ .yjd-rich-editor .import-json-input,
2097
+ .yjd-rich-editor .import-markdown-input,
2098
+ .yjd-rich-editor .import-csv-input,
2099
+ .yjd-rich-editor .import-xml-input,
2100
+ .yjd-rich-editor .import-yaml-input,
2101
+ .yjd-rich-editor .import-toml-input {
2102
+ pointer-events: auto !important;
2103
+ }
2104
+
2105
+ .yjd-rich-editor .rich-editor-popup-container > * {
2106
+ pointer-events: auto;
2107
+ }
2108
+
2109
+ /* Ensure popups in container have proper positioning */
2110
+ .yjd-rich-editor .rich-editor-popup-container .link-popup,
2111
+ .yjd-rich-editor .rich-editor-popup-container .color-picker-popup,
2112
+ .yjd-rich-editor .rich-editor-popup-container .emoji-picker-popup,
2113
+ .yjd-rich-editor .rich-editor-popup-container .image-popup,
2114
+ .yjd-rich-editor .rich-editor-popup-container .video-popup,
2115
+ .yjd-rich-editor .rich-editor-popup-container .table-popup,
2116
+ .yjd-rich-editor .rich-editor-popup-container .tag-popup,
2117
+ .yjd-rich-editor .rich-editor-popup-container .import-popup,
2118
+ .yjd-rich-editor .rich-editor-popup-container .text-align-picker-popup,
2119
+ .yjd-rich-editor .rich-editor-popup-container .list-picker-popup,
2120
+ .yjd-rich-editor .rich-editor-popup-container .custom-select-popup {
2121
+ position: absolute !important;
2122
+ z-index: 1001 !important;
2123
+ }
2124
+ /* =====================================================================
2125
+ DESIGN SYSTEM v2 — "Calm writing studio"
2126
+ A friendly, cohesive theme. Everything below is driven by tokens so
2127
+ every surface (toolbar, popups, find/replace, tables, floating tools)
2128
+ shares the same palette, radius, shadow and motion.
2129
+ This block is appended last so it themes the components above.
2130
+ ===================================================================== */
2131
+
2132
+ .yjd-rich-editor {
2133
+ /* Palette */
2134
+ --rte-bg: #ffffff;
2135
+ --rte-chrome: #fbfbfd;
2136
+ --rte-chrome-2: #f2f2f7;
2137
+ --rte-border: #e9e9f1;
2138
+ --rte-border-strong: #dadae6;
2139
+ --rte-ink: #20242f;
2140
+ --rte-muted: #767c8e;
2141
+ --rte-accent: #6d5efc;
2142
+ --rte-accent-ink: #5a48ee;
2143
+ --rte-accent-weak: #efedff;
2144
+ --rte-accent-ring: rgba(109, 94, 252, 0.28);
2145
+ --rte-danger: #e5484d;
2146
+ /* Shape & depth */
2147
+ --rte-radius: 14px;
2148
+ --rte-radius-md: 11px;
2149
+ --rte-radius-sm: 8px;
2150
+ --rte-shadow-sm: 0 1px 2px rgba(20, 24, 46, 0.06);
2151
+ --rte-shadow: 0 12px 32px -8px rgba(20, 24, 46, 0.20), 0 4px 10px -4px rgba(20, 24, 46, 0.10);
2152
+ --rte-t: 140ms cubic-bezier(0.4, 0, 0.2, 1);
2153
+
2154
+ border: 1px solid var(--rte-border) !important;
2155
+ border-radius: var(--rte-radius) !important;
2156
+ background: var(--rte-bg);
2157
+ color: var(--rte-ink);
2158
+ box-shadow: var(--rte-shadow-sm);
2159
+ font-family: system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
2160
+ }
2161
+
2162
+ /* Use a friendly system stack everywhere (overrides the forced "Inter") */
2163
+ .yjd-rich-editor .toolbar-container button,
2164
+ .yjd-rich-editor .toolbar-container input,
2165
+ .yjd-rich-editor .toolbar-container select,
2166
+ .yjd-rich-editor .toolbar-container textarea,
2167
+ .yjd-rich-editor .rich-editor-popup-container button,
2168
+ .yjd-rich-editor .rich-editor-popup-container input,
2169
+ .yjd-rich-editor .rich-editor-popup-container select,
2170
+ .yjd-rich-editor .rich-editor-popup-container textarea {
2171
+ font-family: system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif !important;
2172
+ }
2173
+
2174
+ /* ---------- Toolbar ---------- */
2175
+ .yjd-rich-editor .rich-editor-toolbar-container {
2176
+ background: var(--rte-chrome);
2177
+ border-bottom: 1px solid var(--rte-border);
2178
+ }
2179
+ .yjd-rich-editor .rich-editor-toolbar-1,
2180
+ .yjd-rich-editor .rich-editor-toolbar-2 {
2181
+ display: flex;
2182
+ flex-wrap: wrap;
2183
+ align-items: center;
2184
+ justify-content: flex-start; /* pack left; override legacy space-between */
2185
+ column-gap: 0;
2186
+ row-gap: 4px;
2187
+ padding: 8px 12px;
2188
+ }
2189
+ .yjd-rich-editor .rich-editor-toolbar-2.visible {
2190
+ border-top: 1px solid var(--rte-border);
2191
+ }
2192
+ /* Group by spacing, not dividers: tight within a group, airy between groups. */
2193
+ .yjd-rich-editor .toolbar-group {
2194
+ display: flex;
2195
+ align-items: center;
2196
+ gap: 2px;
2197
+ border-right: none;
2198
+ margin: 0;
2199
+ padding: 0;
2200
+ }
2201
+ .yjd-rich-editor .toolbar-group + .toolbar-group {
2202
+ margin-left: 12px;
2203
+ }
2204
+
2205
+ /* ---------- Buttons (toolbar + dropdown triggers) ---------- */
2206
+ .yjd-rich-editor .rich-editor-toolbar-btn,
2207
+ .yjd-rich-editor .custom-select-button {
2208
+ display: inline-flex;
2209
+ align-items: center;
2210
+ justify-content: center;
2211
+ gap: 6px;
2212
+ min-width: 32px;
2213
+ height: 32px;
2214
+ padding: 0 8px;
2215
+ border: 1px solid transparent;
2216
+ border-radius: var(--rte-radius-sm);
2217
+ background: transparent;
2218
+ color: var(--rte-ink);
2219
+ cursor: pointer;
2220
+ box-shadow: none;
2221
+ transition: background var(--rte-t), color var(--rte-t),
2222
+ box-shadow var(--rte-t), border-color var(--rte-t);
2223
+ }
2224
+ .yjd-rich-editor .rich-editor-toolbar-btn:hover,
2225
+ .yjd-rich-editor .custom-select-button:hover {
2226
+ background: var(--rte-chrome-2);
2227
+ color: var(--rte-ink);
2228
+ }
2229
+ .yjd-rich-editor .rich-editor-toolbar-btn.active {
2230
+ background: var(--rte-accent-weak);
2231
+ color: var(--rte-accent-ink);
2232
+ border-color: transparent;
2233
+ }
2234
+ .yjd-rich-editor .rich-editor-toolbar-btn.active .icon svg,
2235
+ .yjd-rich-editor .rich-editor-toolbar-btn.active .icon svg path {
2236
+ fill: var(--rte-accent-ink);
2237
+ color: var(--rte-accent-ink);
2238
+ }
2239
+ .yjd-rich-editor .rich-editor-toolbar-btn:disabled,
2240
+ .yjd-rich-editor .rich-editor-toolbar-btn[disabled] {
2241
+ opacity: 0.38 !important;
2242
+ cursor: not-allowed !important;
2243
+ }
2244
+ .yjd-rich-editor .rich-editor-toolbar-btn:focus-visible,
2245
+ .yjd-rich-editor .custom-select-button:focus-visible {
2246
+ outline: none;
2247
+ border-color: var(--rte-accent);
2248
+ box-shadow: 0 0 0 3px var(--rte-accent-ring);
2249
+ }
2250
+
2251
+ /* ---------- Status bar ---------- */
2252
+ .yjd-rich-editor .rich-editor-statusbar {
2253
+ display: flex;
2254
+ align-items: center;
2255
+ justify-content: space-between;
2256
+ gap: 12px;
2257
+ padding: 7px 14px;
2258
+ background: var(--rte-chrome);
2259
+ border-top: 1px solid var(--rte-border);
2260
+ }
2261
+ .yjd-rich-editor .rich-editor-breadcrumb,
2262
+ .yjd-rich-editor .wordcount {
2263
+ color: var(--rte-muted);
2264
+ font-size: 12px;
2265
+ letter-spacing: 0.01em;
2266
+ }
2267
+
2268
+ /* ---------- Editor surface ---------- */
2269
+ .yjd-rich-editor .rich-editor-area {
2270
+ color: var(--rte-ink);
2271
+ font-size: 16px;
2272
+ line-height: 1.75;
2273
+ padding: 22px 24px;
2274
+ }
2275
+ .yjd-rich-editor .rich-editor-area a {
2276
+ color: var(--rte-accent-ink);
2277
+ text-decoration-color: var(--rte-accent-ring);
2278
+ text-underline-offset: 2px;
2279
+ }
2280
+ .yjd-rich-editor .rich-editor-area[data-placeholder].placeholder-visible:before {
2281
+ color: var(--rte-muted);
2282
+ opacity: 0.55;
2283
+ }
2284
+ .yjd-rich-editor .rich-editor-area blockquote {
2285
+ border-left: 3px solid var(--rte-accent);
2286
+ background: var(--rte-accent-weak);
2287
+ border-radius: 0 var(--rte-radius-sm) var(--rte-radius-sm) 0;
2288
+ padding: 8px 16px;
2289
+ color: var(--rte-ink);
2290
+ margin: 12px 0;
2291
+ }
2292
+ .yjd-rich-editor .rich-editor-area code {
2293
+ background: var(--rte-chrome-2);
2294
+ border-radius: 6px;
2295
+ padding: 2px 6px;
2296
+ font-size: 0.9em;
2297
+ }
2298
+ .yjd-rich-editor .rich-editor-area pre {
2299
+ background: #20242f;
2300
+ color: #ececf5;
2301
+ border-radius: var(--rte-radius-md);
2302
+ padding: 14px 16px;
2303
+ border: none;
2304
+ }
2305
+ .yjd-rich-editor .rich-editor-area pre code {
2306
+ background: transparent;
2307
+ color: inherit;
2308
+ padding: 0;
2309
+ }
2310
+
2311
+ /* ---------- Popups (shared shell) ---------- */
2312
+ .yjd-rich-editor .color-picker-popup,
2313
+ .yjd-rich-editor .custom-select-popup,
2314
+ .yjd-rich-editor .heading-select-popup,
2315
+ .yjd-rich-editor .capitalization-select-popup,
2316
+ .yjd-rich-editor .font-family-select-popup,
2317
+ .yjd-rich-editor .line-height-select-popup,
2318
+ .yjd-rich-editor .text-size-select-popup,
2319
+ .yjd-rich-editor .link-popup,
2320
+ .yjd-rich-editor .image-popup,
2321
+ .yjd-rich-editor .video-popup,
2322
+ .yjd-rich-editor .tag-popup,
2323
+ .yjd-rich-editor .import-popup,
2324
+ .yjd-rich-editor .table-popup,
2325
+ .yjd-rich-editor .text-align-picker-popup,
2326
+ .yjd-rich-editor .emoji-picker-popup {
2327
+ background: var(--rte-bg);
2328
+ border: 1px solid var(--rte-border);
2329
+ border-radius: var(--rte-radius-md);
2330
+ box-shadow: var(--rte-shadow);
2331
+ }
2332
+
2333
+ /* Dropdown list items */
2334
+ .yjd-rich-editor .custom-select-item-button {
2335
+ border-radius: var(--rte-radius-sm);
2336
+ color: var(--rte-ink);
2337
+ transition: background var(--rte-t), color var(--rte-t);
2338
+ }
2339
+ .yjd-rich-editor .custom-select-item-button:hover {
2340
+ background: var(--rte-chrome-2);
2341
+ }
2342
+ .yjd-rich-editor .custom-select-item-button.current {
2343
+ background: var(--rte-accent-weak);
2344
+ color: var(--rte-accent-ink);
2345
+ }
2346
+ .yjd-rich-editor .custom-select-item-button.current .item-checkmark {
2347
+ color: var(--rte-accent-ink);
2348
+ }
2349
+
2350
+ /* ---------- Forms inside popups ---------- */
2351
+ .yjd-rich-editor .yjd-input,
2352
+ .yjd-rich-editor .yjd-select-input {
2353
+ border: 1px solid var(--rte-border-strong);
2354
+ border-radius: var(--rte-radius-sm);
2355
+ color: var(--rte-ink);
2356
+ transition: border-color var(--rte-t), box-shadow var(--rte-t);
2357
+ }
2358
+ .yjd-rich-editor .yjd-input:focus,
2359
+ .yjd-rich-editor .yjd-select-input:focus {
2360
+ outline: none;
2361
+ border-color: var(--rte-accent);
2362
+ box-shadow: 0 0 0 3px var(--rte-accent-ring);
2363
+ }
2364
+ .yjd-rich-editor .yjd-input-title {
2365
+ color: var(--rte-ink);
2366
+ font-weight: 600;
2367
+ }
2368
+ .yjd-rich-editor .yjd-input-label {
2369
+ color: var(--rte-muted);
2370
+ }
2371
+ .yjd-rich-editor .yjd-button-confirm {
2372
+ background: var(--rte-accent);
2373
+ color: #fff;
2374
+ border: none;
2375
+ border-radius: var(--rte-radius-sm);
2376
+ transition: background var(--rte-t);
2377
+ }
2378
+ .yjd-rich-editor .yjd-button-confirm:hover {
2379
+ background: var(--rte-accent-ink);
2380
+ }
2381
+ .yjd-rich-editor .yjd-button-cancel {
2382
+ background: var(--rte-chrome-2);
2383
+ color: var(--rte-ink);
2384
+ border: 1px solid var(--rte-border);
2385
+ border-radius: var(--rte-radius-sm);
2386
+ transition: background var(--rte-t);
2387
+ }
2388
+ .yjd-rich-editor .yjd-button-cancel:hover {
2389
+ background: #e9e9f2;
2390
+ }
2391
+ .yjd-rich-editor .yjd-custom-upload-button {
2392
+ border-radius: var(--rte-radius-sm);
2393
+ border: 1px dashed var(--rte-border-strong);
2394
+ color: var(--rte-accent-ink);
2395
+ background: var(--rte-accent-weak);
2396
+ transition: background var(--rte-t), border-color var(--rte-t);
2397
+ }
2398
+ .yjd-rich-editor .yjd-custom-upload-button:hover {
2399
+ border-color: var(--rte-accent);
2400
+ }
2401
+
2402
+ /* ---------- Floating toolbars (block + table) ---------- */
2403
+ .yjd-rich-editor .block-toolbar-container,
2404
+ .yjd-rich-editor .table-toolbar-container {
2405
+ background: var(--rte-bg);
2406
+ border: 1px solid var(--rte-border);
2407
+ border-radius: var(--rte-radius-md);
2408
+ box-shadow: var(--rte-shadow);
2409
+ padding: 4px;
2410
+ gap: 2px;
2411
+ }
2412
+ .yjd-rich-editor .block-toolbar-btn,
2413
+ .yjd-rich-editor .table-toolbar-btn {
2414
+ border: 1px solid transparent;
2415
+ border-radius: var(--rte-radius-sm);
2416
+ background: transparent;
2417
+ color: var(--rte-ink);
2418
+ transition: background var(--rte-t), color var(--rte-t);
2419
+ }
2420
+ .yjd-rich-editor .block-toolbar-btn:hover,
2421
+ .yjd-rich-editor .table-toolbar-btn:hover {
2422
+ background: var(--rte-chrome-2);
2423
+ }
2424
+ .yjd-rich-editor .block-toolbar-btn.active {
2425
+ background: var(--rte-accent-weak);
2426
+ color: var(--rte-accent-ink);
2427
+ }
2428
+ .yjd-rich-editor .block-toolbar-btn.active .icon svg,
2429
+ .yjd-rich-editor .block-toolbar-btn.active .icon svg path {
2430
+ fill: var(--rte-accent-ink);
2431
+ }
2432
+
2433
+ /* ---------- Tables ---------- */
2434
+ .yjd-rich-editor .rich-editor-table td {
2435
+ border: 1px solid var(--rte-border-strong) !important;
2436
+ }
2437
+ .yjd-rich-editor .rich-editor-table td:focus {
2438
+ outline: none;
2439
+ box-shadow: inset 0 0 0 2px var(--rte-accent);
2440
+ background: var(--rte-accent-weak);
2441
+ }
2442
+ .yjd-rich-editor .table-grid-cell.highlighted {
2443
+ background: var(--rte-accent);
2444
+ border-color: var(--rte-accent);
2445
+ }
2446
+
2447
+ /* ---------- Resize handles ---------- */
2448
+ .yjd-rich-editor .resize-handle {
2449
+ background: var(--rte-accent) !important;
2450
+ border: 2px solid #fff !important;
2451
+ border-radius: 50% !important;
2452
+ box-shadow: var(--rte-shadow-sm) !important;
2453
+ }
2454
+
2455
+ /* ---------- Find & Replace panel ---------- */
2456
+ .yjd-rich-editor .yjd-find-replace {
2457
+ position: absolute;
2458
+ top: 10px;
2459
+ right: 10px;
2460
+ z-index: 1100;
2461
+ display: none;
2462
+ flex-direction: column;
2463
+ gap: 8px;
2464
+ padding: 10px;
2465
+ background: var(--rte-bg);
2466
+ border: 1px solid var(--rte-border);
2467
+ border-radius: var(--rte-radius-md);
2468
+ box-shadow: var(--rte-shadow);
2469
+ font: 13px/1.4 system-ui, -apple-system, sans-serif;
2470
+ max-width: calc(100% - 20px);
2471
+ }
2472
+ .yjd-rich-editor .yjd-find-replace.open {
2473
+ display: flex;
2474
+ }
2475
+ .yjd-rich-editor .yjd-find-row {
2476
+ display: flex;
2477
+ align-items: center;
2478
+ gap: 6px;
2479
+ }
2480
+ .yjd-rich-editor .yjd-find-input {
2481
+ flex: 1 1 auto;
2482
+ min-width: 150px;
2483
+ height: 30px;
2484
+ padding: 0 9px;
2485
+ border: 1px solid var(--rte-border-strong);
2486
+ border-radius: var(--rte-radius-sm);
2487
+ color: var(--rte-ink);
2488
+ background: var(--rte-bg);
2489
+ transition: border-color var(--rte-t), box-shadow var(--rte-t);
2490
+ }
2491
+ .yjd-rich-editor .yjd-find-input:focus {
2492
+ outline: none;
2493
+ border-color: var(--rte-accent);
2494
+ box-shadow: 0 0 0 3px var(--rte-accent-ring);
2495
+ }
2496
+ .yjd-rich-editor .yjd-find-count {
2497
+ min-width: 46px;
2498
+ text-align: center;
2499
+ color: var(--rte-muted);
2500
+ font-variant-numeric: tabular-nums;
2501
+ }
2502
+ .yjd-rich-editor .yjd-find-btn {
2503
+ height: 30px;
2504
+ padding: 0 12px;
2505
+ border: 1px solid var(--rte-border);
2506
+ border-radius: var(--rte-radius-sm);
2507
+ background: var(--rte-chrome);
2508
+ color: var(--rte-ink);
2509
+ cursor: pointer;
2510
+ transition: background var(--rte-t), color var(--rte-t), border-color var(--rte-t),
2511
+ box-shadow var(--rte-t);
2512
+ }
2513
+ .yjd-rich-editor .yjd-find-btn:hover {
2514
+ background: var(--rte-chrome-2);
2515
+ }
2516
+ .yjd-rich-editor .yjd-find-btn:focus-visible {
2517
+ outline: none;
2518
+ border-color: var(--rte-accent);
2519
+ box-shadow: 0 0 0 3px var(--rte-accent-ring);
2520
+ }
2521
+ .yjd-rich-editor .yjd-find-icon {
2522
+ width: 30px;
2523
+ padding: 0;
2524
+ font-size: 15px;
2525
+ line-height: 1;
2526
+ }
2527
+ .yjd-rich-editor .yjd-find-toggle.active {
2528
+ background: var(--rte-accent-weak);
2529
+ color: var(--rte-accent-ink);
2530
+ border-color: transparent;
2531
+ }
2532
+ .yjd-rich-editor .yjd-find-replace .yjd-find-btn.yjd-find-close:hover {
2533
+ background: #fdecec;
2534
+ color: var(--rte-danger);
2535
+ border-color: #f6caca;
2536
+ }
2537
+ .yjd-rich-editor .yjd-find-replace-input {
2538
+ flex: 1 1 auto;
2539
+ }
2540
+ .yjd-rich-editor .yjd-find-row .yjd-find-btn:not(.yjd-find-icon) {
2541
+ flex: 0 0 auto;
2542
+ }
2543
+
2544
+ /* Match highlights */
2545
+ .yjd-rich-editor mark.yjd-find-hit {
2546
+ background: #fff1b8;
2547
+ color: inherit;
2548
+ border-radius: 3px;
2549
+ }
2550
+ .yjd-rich-editor mark.yjd-find-hit.active {
2551
+ background: var(--rte-accent);
2552
+ color: #fff;
2553
+ }
2554
+
2555
+ /* ---------- Accessibility: respect reduced motion ---------- */
2556
+ @media (prefers-reduced-motion: reduce) {
2557
+ .yjd-rich-editor * {
2558
+ transition-duration: 0.01ms !important;
2559
+ animation-duration: 0.01ms !important;
2560
+ }
2561
+ }
2562
+
2563
+ /* =====================================================================
2564
+ DESIGN SYSTEM v2.1 — minimal & light refinements
2565
+ Icon unification, friendlier popovers, lighter inputs & buttons.
2566
+ ===================================================================== */
2567
+
2568
+ /* ---------- Icons: one size, one color ---------- */
2569
+ /* Convert the hard-coded greys to currentColor so every icon follows the
2570
+ button's text colour (and the accent on active). Outline icons (stroke)
2571
+ and the deliberately-coloured "no colour" swatch are left untouched. */
2572
+ .yjd-rich-editor .icon svg [fill="#454545"],
2573
+ .yjd-rich-editor .icon svg [fill="#231F20"],
2574
+ .yjd-rich-editor .icon svg [fill="#010101"],
2575
+ .yjd-rich-editor .icon svg[fill="#454545"],
2576
+ .yjd-rich-editor .block-toolbar-btn svg [fill="#454545"],
2577
+ .yjd-rich-editor .table-toolbar-btn svg [fill="#454545"] {
2578
+ fill: currentColor;
2579
+ }
2580
+
2581
+ /* Consistent icon footprint — equal height, centered, never distorted. */
2582
+ .yjd-rich-editor .rich-editor-toolbar-btn .icon,
2583
+ .yjd-rich-editor .block-toolbar-btn .icon,
2584
+ .yjd-rich-editor .table-toolbar-btn .icon {
2585
+ display: inline-flex;
2586
+ align-items: center;
2587
+ justify-content: center;
2588
+ width: 18px;
2589
+ height: 18px;
2590
+ color: inherit;
2591
+ }
2592
+ .yjd-rich-editor .rich-editor-toolbar-btn .icon svg,
2593
+ .yjd-rich-editor .block-toolbar-btn .icon svg,
2594
+ .yjd-rich-editor .table-toolbar-btn .icon svg {
2595
+ width: auto !important;
2596
+ height: 16px !important;
2597
+ max-width: 18px;
2598
+ display: block;
2599
+ }
2600
+
2601
+ /* Default icon colour = quiet ink; active = accent (overrides legacy blue). */
2602
+ .yjd-rich-editor .rich-editor-toolbar-btn .icon svg,
2603
+ .yjd-rich-editor .rich-editor-toolbar-btn .icon svg path {
2604
+ fill: currentColor;
2605
+ }
2606
+ .yjd-rich-editor .rich-editor-toolbar-btn { color: #4b5060; }
2607
+ .yjd-rich-editor .rich-editor-toolbar-btn:hover { color: var(--rte-ink); }
2608
+ .yjd-rich-editor .rich-editor-toolbar-btn.active,
2609
+ .yjd-rich-editor .rich-editor-toolbar-btn.active .icon svg,
2610
+ .yjd-rich-editor .rich-editor-toolbar-btn.active .icon svg path,
2611
+ .yjd-rich-editor .rich-editor-toolbar-btn.active .icon svg [fill] {
2612
+ color: var(--rte-accent-ink) !important;
2613
+ fill: var(--rte-accent-ink) !important;
2614
+ }
2615
+
2616
+ /* ---------- Toolbar: lighter weight ---------- */
2617
+ .yjd-rich-editor .rich-editor-toolbar-btn,
2618
+ .yjd-rich-editor .custom-select-button {
2619
+ box-shadow: none;
2620
+ }
2621
+ .yjd-rich-editor .custom-select-button {
2622
+ border-color: var(--rte-border);
2623
+ background: var(--rte-bg);
2624
+ color: var(--rte-ink);
2625
+ font-weight: 500;
2626
+ }
2627
+ .yjd-rich-editor .custom-select-button:hover {
2628
+ border-color: var(--rte-border-strong);
2629
+ background: var(--rte-bg);
2630
+ }
2631
+ .yjd-rich-editor .dropdown-icon { color: var(--rte-muted); }
2632
+
2633
+ /* ---------- Popovers: friendly & airy ---------- */
2634
+ .yjd-rich-editor .color-picker-popup,
2635
+ .yjd-rich-editor .custom-select-popup,
2636
+ .yjd-rich-editor .heading-select-popup,
2637
+ .yjd-rich-editor .capitalization-select-popup,
2638
+ .yjd-rich-editor .font-family-select-popup,
2639
+ .yjd-rich-editor .line-height-select-popup,
2640
+ .yjd-rich-editor .text-size-select-popup,
2641
+ .yjd-rich-editor .link-popup,
2642
+ .yjd-rich-editor .image-popup,
2643
+ .yjd-rich-editor .video-popup,
2644
+ .yjd-rich-editor .tag-popup,
2645
+ .yjd-rich-editor .import-popup,
2646
+ .yjd-rich-editor .table-popup,
2647
+ .yjd-rich-editor .text-align-picker-popup,
2648
+ .yjd-rich-editor .emoji-picker-popup {
2649
+ border-color: var(--rte-border);
2650
+ border-radius: var(--rte-radius-md);
2651
+ box-shadow: 0 10px 30px -10px rgba(20, 24, 46, 0.18), 0 2px 6px -2px rgba(20, 24, 46, 0.08);
2652
+ }
2653
+
2654
+ /* roomier dropdown lists */
2655
+ .yjd-rich-editor .custom-select-popup,
2656
+ .yjd-rich-editor .heading-select-popup,
2657
+ .yjd-rich-editor .capitalization-select-popup,
2658
+ .yjd-rich-editor .font-family-select-popup,
2659
+ .yjd-rich-editor .line-height-select-popup,
2660
+ .yjd-rich-editor .text-size-select-popup {
2661
+ padding: 6px;
2662
+ }
2663
+ .yjd-rich-editor .custom-select-item-button {
2664
+ padding: 8px 10px;
2665
+ }
2666
+
2667
+ /* gentle entrance for popovers (respects reduced motion below) */
2668
+ .yjd-rich-editor .color-picker-popup.visible,
2669
+ .yjd-rich-editor .custom-select-popup.visible,
2670
+ .yjd-rich-editor .heading-select-popup.visible,
2671
+ .yjd-rich-editor .font-family-select-popup.visible,
2672
+ .yjd-rich-editor .line-height-select-popup.visible,
2673
+ .yjd-rich-editor .capitalization-select-popup.visible,
2674
+ .yjd-rich-editor .text-size-select-popup.visible,
2675
+ .yjd-rich-editor .link-popup.visible,
2676
+ .yjd-rich-editor .image-popup.visible,
2677
+ .yjd-rich-editor .video-popup.visible,
2678
+ .yjd-rich-editor .tag-popup.visible,
2679
+ .yjd-rich-editor .table-popup.visible,
2680
+ .yjd-rich-editor .text-align-picker-popup.visible,
2681
+ .yjd-rich-editor .yjd-find-replace.open {
2682
+ animation: rte-pop-in 90ms ease-out;
2683
+ }
2684
+ @keyframes rte-pop-in {
2685
+ from { opacity: 0; transform: translateY(-2px); }
2686
+ to { opacity: 1; transform: none; }
2687
+ }
2688
+
2689
+ /* ---------- Inputs: minimal & light ---------- */
2690
+ .yjd-rich-editor .yjd-input,
2691
+ .yjd-rich-editor .yjd-select-input,
2692
+ .yjd-rich-editor .yjd-find-input {
2693
+ height: 36px;
2694
+ padding: 0 12px;
2695
+ border: 1px solid var(--rte-border);
2696
+ border-radius: var(--rte-radius-sm);
2697
+ background: var(--rte-bg);
2698
+ color: var(--rte-ink);
2699
+ font-size: 14px;
2700
+ }
2701
+ .yjd-rich-editor .yjd-input::placeholder,
2702
+ .yjd-rich-editor .yjd-select-input::placeholder,
2703
+ .yjd-rich-editor .yjd-find-input::placeholder {
2704
+ color: var(--rte-muted);
2705
+ opacity: 0.7;
2706
+ }
2707
+ .yjd-rich-editor .yjd-input:focus,
2708
+ .yjd-rich-editor .yjd-select-input:focus,
2709
+ .yjd-rich-editor .yjd-find-input:focus {
2710
+ border-color: var(--rte-accent);
2711
+ box-shadow: 0 0 0 3px var(--rte-accent-ring);
2712
+ }
2713
+
2714
+ /* ---------- Buttons: minimal & light ---------- */
2715
+ .yjd-rich-editor .yjd-button-confirm,
2716
+ .yjd-rich-editor .yjd-button-cancel,
2717
+ .yjd-rich-editor .yjd-find-btn {
2718
+ height: 36px;
2719
+ padding: 0 16px;
2720
+ font-size: 14px;
2721
+ font-weight: 500;
2722
+ border-radius: var(--rte-radius-sm);
2723
+ box-shadow: none;
2724
+ transition: background var(--rte-t), color var(--rte-t), border-color var(--rte-t);
2725
+ }
2726
+ .yjd-rich-editor .yjd-button-confirm {
2727
+ background: var(--rte-accent);
2728
+ border: 1px solid var(--rte-accent);
2729
+ color: #fff;
2730
+ }
2731
+ .yjd-rich-editor .yjd-button-confirm:hover {
2732
+ background: var(--rte-accent-ink);
2733
+ border-color: var(--rte-accent-ink);
2734
+ }
2735
+ /* Cancel & secondary find buttons → quiet, text-like */
2736
+ .yjd-rich-editor .yjd-button-cancel {
2737
+ background: transparent;
2738
+ border: 1px solid var(--rte-border);
2739
+ color: var(--rte-muted);
2740
+ }
2741
+ .yjd-rich-editor .yjd-button-cancel:hover {
2742
+ background: var(--rte-chrome-2);
2743
+ color: var(--rte-ink);
2744
+ }
2745
+ .yjd-rich-editor .yjd-find-btn:not(.yjd-find-icon) {
2746
+ background: transparent;
2747
+ border: 1px solid var(--rte-border);
2748
+ color: var(--rte-ink);
2749
+ }
2750
+ .yjd-rich-editor .yjd-find-btn:not(.yjd-find-icon):hover {
2751
+ background: var(--rte-chrome-2);
2752
+ }
2753
+ .yjd-rich-editor .yjd-find-btn.yjd-find-icon {
2754
+ height: 32px;
2755
+ width: 32px;
2756
+ color: var(--rte-muted);
2757
+ background: transparent;
2758
+ border: 1px solid transparent;
2759
+ }
2760
+ .yjd-rich-editor .yjd-find-btn.yjd-find-icon:hover {
2761
+ background: var(--rte-chrome-2);
2762
+ color: var(--rte-ink);
2763
+ }
2764
+
2765
+ /* ---------- Reduced motion ---------- */
2766
+ @media (prefers-reduced-motion: reduce) {
2767
+ .yjd-rich-editor .color-picker-popup.visible,
2768
+ .yjd-rich-editor [class*="select-popup"].visible,
2769
+ .yjd-rich-editor [class$="-popup"].visible,
2770
+ .yjd-rich-editor .yjd-find-replace.open {
2771
+ animation: none !important;
2772
+ }
2773
+ }
2774
+
2775
+ /* =====================================================================
2776
+ DESIGN SYSTEM v2.2 — outline icon set rendering
2777
+ Icons are now stroke-based (Lucide-style). Render them as outlines and
2778
+ neutralise the legacy fill-based rules above.
2779
+ ===================================================================== */
2780
+ .yjd-rich-editor .icon svg {
2781
+ width: auto !important;
2782
+ height: 16px !important;
2783
+ max-width: 20px;
2784
+ display: block;
2785
+ fill: none !important;
2786
+ stroke: currentColor;
2787
+ stroke-width: 2;
2788
+ stroke-linecap: round;
2789
+ stroke-linejoin: round;
2790
+ overflow: visible;
2791
+ }
2792
+ /* outline paths never fill */
2793
+ .yjd-rich-editor .icon svg path,
2794
+ .yjd-rich-editor .icon svg line,
2795
+ .yjd-rich-editor .icon svg polyline,
2796
+ .yjd-rich-editor .icon svg rect {
2797
+ fill: none !important;
2798
+ stroke: currentColor;
2799
+ }
2800
+ /* solid accents (dots) keep their fill, no stroke */
2801
+ .yjd-rich-editor .icon svg [fill="currentColor"] {
2802
+ fill: currentColor !important;
2803
+ stroke: none !important;
2804
+ }
2805
+
2806
+ /* quiet default colour, accent on active */
2807
+ .yjd-rich-editor .rich-editor-toolbar-btn .icon svg { color: #565b6b; }
2808
+ .yjd-rich-editor .rich-editor-toolbar-btn:hover .icon svg { color: var(--rte-ink); }
2809
+ .yjd-rich-editor .rich-editor-toolbar-btn.active .icon svg,
2810
+ .yjd-rich-editor .rich-editor-toolbar-btn.active .icon svg path,
2811
+ .yjd-rich-editor .rich-editor-toolbar-btn.active .icon svg line,
2812
+ .yjd-rich-editor .rich-editor-toolbar-btn.active .icon svg polyline,
2813
+ .yjd-rich-editor .rich-editor-toolbar-btn.active .icon svg rect {
2814
+ color: var(--rte-accent-ink) !important;
2815
+ stroke: var(--rte-accent-ink) !important;
2816
+ fill: none !important;
2817
+ }
2818
+ .yjd-rich-editor .rich-editor-toolbar-btn.active .icon svg [fill="currentColor"] {
2819
+ fill: var(--rte-accent-ink) !important;
2820
+ stroke: none !important;
2821
+ }
2822
+ .yjd-rich-editor .block-toolbar-btn.active .icon svg,
2823
+ .yjd-rich-editor .block-toolbar-btn.active .icon svg path {
2824
+ stroke: var(--rte-accent-ink) !important;
2825
+ fill: none !important;
2826
+ }
2827
+
2828
+ /* =====================================================================
2829
+ DESIGN SYSTEM v2.4 — sync the list-picker popover with the others
2830
+ ===================================================================== */
2831
+ .yjd-rich-editor .list-picker-popup {
2832
+ background: var(--rte-bg);
2833
+ border: 1px solid var(--rte-border);
2834
+ border-radius: var(--rte-radius-md);
2835
+ box-shadow: var(--rte-shadow);
2836
+ padding: 6px;
2837
+ }
2838
+ .yjd-rich-editor .list-picker-popup.visible {
2839
+ animation: rte-pop-in 90ms ease-out;
2840
+ }
2841
+ .yjd-rich-editor .list-button-container {
2842
+ display: flex;
2843
+ align-items: center;
2844
+ gap: 2px;
2845
+ }
2846
+ .yjd-rich-editor .list-button {
2847
+ display: inline-flex;
2848
+ align-items: center;
2849
+ justify-content: center;
2850
+ width: 34px;
2851
+ height: 32px;
2852
+ padding: 0;
2853
+ border: 1px solid transparent;
2854
+ border-radius: var(--rte-radius-sm);
2855
+ background: transparent;
2856
+ color: #565b6b;
2857
+ cursor: pointer;
2858
+ transition: background var(--rte-t), color var(--rte-t);
2859
+ }
2860
+ .yjd-rich-editor .list-button:hover {
2861
+ background: var(--rte-chrome-2);
2862
+ color: var(--rte-ink);
2863
+ }
2864
+ .yjd-rich-editor .list-button.active {
2865
+ background: var(--rte-accent-weak);
2866
+ color: var(--rte-accent-ink);
2867
+ }
2868
+ .yjd-rich-editor .list-button svg {
2869
+ width: auto !important;
2870
+ height: 16px !important;
2871
+ max-width: 20px;
2872
+ fill: none !important;
2873
+ stroke: currentColor;
2874
+ stroke-width: 2;
2875
+ stroke-linecap: round;
2876
+ stroke-linejoin: round;
2877
+ }
2878
+ .yjd-rich-editor .list-button svg [fill="currentColor"] {
2879
+ fill: currentColor !important;
2880
+ stroke: none !important;
2881
+ }
2882
+
2883
+ /* =====================================================================
2884
+ DESIGN SYSTEM v2.5 — table-toolbar icons
2885
+ These buttons inject the SVG directly (no .icon wrapper), so size/stroke
2886
+ them here too. Outline icons only carry a viewBox, so without this the SVG
2887
+ blows up to its default size and gets clipped (icons appeared "missing").
2888
+ ===================================================================== */
2889
+ .yjd-rich-editor .table-toolbar-btn svg {
2890
+ width: auto !important;
2891
+ height: 16px !important;
2892
+ max-width: 20px;
2893
+ display: block;
2894
+ fill: none !important;
2895
+ stroke: currentColor;
2896
+ stroke-width: 2;
2897
+ stroke-linecap: round;
2898
+ stroke-linejoin: round;
2899
+ }
2900
+ .yjd-rich-editor .table-toolbar-btn svg [fill="currentColor"] {
2901
+ fill: currentColor !important;
2902
+ stroke: none !important;
2903
+ }
2904
+ .yjd-rich-editor .table-toolbar-btn { color: #565b6b; }
2905
+ .yjd-rich-editor .table-toolbar-btn:hover { color: var(--rte-ink); }
2906
+
2907
+ /* =====================================================================
2908
+ DESIGN SYSTEM v2.6 — final popover consistency pass
2909
+ ===================================================================== */
2910
+ /* Text-align picker items: match the other dropdown lists */
2911
+ .yjd-rich-editor .align-button {
2912
+ height: auto;
2913
+ min-height: 32px;
2914
+ padding: 6px 10px;
2915
+ gap: 8px;
2916
+ border-radius: var(--rte-radius-sm);
2917
+ background: transparent;
2918
+ color: var(--rte-ink);
2919
+ transition: background var(--rte-t), color var(--rte-t);
2920
+ }
2921
+ .yjd-rich-editor .align-button:hover {
2922
+ background: var(--rte-chrome-2);
2923
+ border-color: transparent;
2924
+ }
2925
+ .yjd-rich-editor .align-button.active {
2926
+ background: var(--rte-accent-weak);
2927
+ color: var(--rte-accent-ink);
2928
+ border-color: transparent;
2929
+ }
2930
+ .yjd-rich-editor .align-button svg {
2931
+ width: auto !important;
2932
+ height: 16px !important;
2933
+ color: inherit;
2934
+ fill: none !important;
2935
+ stroke: currentColor;
2936
+ stroke-width: 2;
2937
+ stroke-linecap: round;
2938
+ stroke-linejoin: round;
2939
+ }
2940
+ .yjd-rich-editor .align-button.active svg { color: var(--rte-accent-ink); }
2941
+
2942
+ /* Upload affordance icon (outline) → accent, matches the dashed accent button */
2943
+ .yjd-rich-editor .yjd-custom-upload-button svg {
2944
+ width: 17px;
2945
+ height: 17px;
2946
+ fill: none;
2947
+ stroke: var(--rte-accent-ink);
2948
+ }
2949
+
2950
+ /* keep align-picker labels on one line */
2951
+ .yjd-rich-editor .text-align-picker-popup { min-width: 168px; }
2952
+ .yjd-rich-editor .align-button { white-space: nowrap; }
2953
+ .yjd-rich-editor .align-button .label-text { white-space: nowrap; }
2954
+
2955
+ /* =====================================================================
2956
+ DESIGN SYSTEM v2.7 — responsive toolbar (no wrapping; overflow -> "more")
2957
+ ===================================================================== */
2958
+ .yjd-rich-editor .rich-editor-toolbar-1 {
2959
+ flex-wrap: nowrap !important;
2960
+ overflow: hidden;
2961
+ }
2962
+ .yjd-rich-editor .rich-editor-toolbar-2 {
2963
+ flex-wrap: wrap;
2964
+ border-top: 1px solid var(--rte-border);
2965
+ }
2966
+ .yjd-rich-editor .toolbar-group,
2967
+ .yjd-rich-editor .rich-editor-toolbar-btn,
2968
+ .yjd-rich-editor .custom-select-button {
2969
+ flex: 0 0 auto;
2970
+ }
2971
+ .yjd-rich-editor .rich-editor-toolbar-1 .more-btn {
2972
+ margin-left: 12px;
2973
+ }
2974
+
2975
+ /* =====================================================================
2976
+ DESIGN SYSTEM v2.8 — remove the triangle pointer on floating toolbars
2977
+ ===================================================================== */
2978
+ .yjd-rich-editor .block-toolbar-arrow,
2979
+ .yjd-rich-editor .table-toolbar-arrow {
2980
+ display: none !important;
2981
+ }
2982
+
2983
+ /* =====================================================================
2984
+ DESIGN SYSTEM v2.9 — slash command menu (rendered on <body>, so unscoped)
2985
+ ===================================================================== */
2986
+ .yjd-slash-menu {
2987
+ position: absolute;
2988
+ z-index: 2000;
2989
+ min-width: 264px;
2990
+ max-width: 320px;
2991
+ max-height: 320px;
2992
+ overflow-y: auto;
2993
+ padding: 6px;
2994
+ background: #ffffff;
2995
+ border: 1px solid #e9e9f1;
2996
+ border-radius: 12px;
2997
+ box-shadow: 0 12px 32px -8px rgba(20, 24, 46, 0.20), 0 4px 10px -4px rgba(20, 24, 46, 0.10);
2998
+ font: 14px/1.4 system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
2999
+ animation: yjd-slash-in 90ms ease-out;
3000
+ }
3001
+ @keyframes yjd-slash-in { from { opacity: 0; transform: translateY(-2px); } to { opacity: 1; transform: none; } }
3002
+ .yjd-slash-item {
3003
+ display: flex;
3004
+ align-items: center;
3005
+ gap: 10px;
3006
+ width: 100%;
3007
+ padding: 8px 10px;
3008
+ border: none;
3009
+ background: transparent;
3010
+ border-radius: 8px;
3011
+ cursor: pointer;
3012
+ text-align: left;
3013
+ color: #20242f;
3014
+ }
3015
+ .yjd-slash-item:hover,
3016
+ .yjd-slash-item.active { background: #efedff; color: #5a48ee; }
3017
+ .yjd-slash-icon {
3018
+ display: inline-flex;
3019
+ align-items: center;
3020
+ justify-content: center;
3021
+ width: 28px;
3022
+ height: 28px;
3023
+ flex: 0 0 auto;
3024
+ border-radius: 7px;
3025
+ background: #f2f2f7;
3026
+ color: inherit;
3027
+ }
3028
+ .yjd-slash-item.active .yjd-slash-icon { background: #ffffff; }
3029
+ .yjd-slash-icon svg {
3030
+ width: auto;
3031
+ height: 16px;
3032
+ fill: none;
3033
+ stroke: currentColor;
3034
+ stroke-width: 2;
3035
+ stroke-linecap: round;
3036
+ stroke-linejoin: round;
3037
+ }
3038
+ .yjd-slash-icon svg [fill="currentColor"] { fill: currentColor; stroke: none; }
3039
+ .yjd-slash-text { display: flex; flex-direction: column; line-height: 1.25; min-width: 0; }
3040
+ .yjd-slash-label { font-weight: 500; }
3041
+ .yjd-slash-hint { font-size: 12px; color: #767c8e; }
3042
+ .yjd-slash-item.active .yjd-slash-hint { color: #8b7ff0; }
3043
+ @media (prefers-reduced-motion: reduce) { .yjd-slash-menu { animation: none; } }
3044
+
3045
+ /* ── Colour button swatch (v2.10) ─────────────────────────────────────────
3046
+ The text-colour and background-colour buttons carry a small bar that
3047
+ reflects the colour currently applied at the caret. */
3048
+ .yjd-rich-editor .rich-editor-toolbar-btn.color-btn,
3049
+ .yjd-rich-editor .rich-editor-toolbar-btn.background-btn {
3050
+ position: relative;
3051
+ }
3052
+ .yjd-rich-editor .rich-editor-toolbar-btn .rte-swatch {
3053
+ position: absolute;
3054
+ left: 50%;
3055
+ bottom: 5px;
3056
+ transform: translateX(-50%);
3057
+ width: 16px;
3058
+ height: 3px;
3059
+ border-radius: 2px;
3060
+ background: var(--rte-ink, #20242f);
3061
+ pointer-events: none;
3062
+ box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.06);
3063
+ }
3064
+ /* Background swatch defaults to a "no fill" look until a colour is chosen. */
3065
+ .yjd-rich-editor .rich-editor-toolbar-btn.background-btn .rte-swatch {
3066
+ background: transparent;
3067
+ box-shadow: inset 0 0 0 1px var(--rte-border, #e9e9f1);
3068
+ }
3069
+ .yjd-rich-editor .rich-editor-toolbar-btn.background-btn.has-color .rte-swatch {
3070
+ box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.06);
3071
+ }
3072
+ /* Nudge the icon up slightly so the swatch bar has room. */
3073
+ .yjd-rich-editor .rich-editor-toolbar-btn.color-btn .icon,
3074
+ .yjd-rich-editor .rich-editor-toolbar-btn.background-btn .icon {
3075
+ transform: translateY(-1px);
3076
+ }
3077
+
3078
+ /* ── Inline link popup (v2.11) ────────────────────────────────────────────
3079
+ Compact link input anchored right at the selected text. */
3080
+ .yjd-rich-editor .link-popup.link-popup--inline {
3081
+ width: auto;
3082
+ min-width: 320px;
3083
+ max-width: min(92vw, 420px);
3084
+ padding: 10px;
3085
+ }
3086
+ .yjd-rich-editor .link-popup--inline .link-popup-content {
3087
+ display: flex;
3088
+ flex-direction: column;
3089
+ gap: 8px;
3090
+ }
3091
+ .yjd-rich-editor .link-popup--inline .link-popup-row {
3092
+ display: flex;
3093
+ align-items: center;
3094
+ gap: 8px;
3095
+ }
3096
+ .yjd-rich-editor .link-popup--inline .link-popup-row .yjd-input {
3097
+ flex: 1;
3098
+ min-width: 0;
3099
+ margin: 0;
3100
+ }
3101
+ .yjd-rich-editor .link-popup--inline .link-popup-apply {
3102
+ flex: 0 0 auto;
3103
+ white-space: nowrap;
3104
+ padding: 8px 16px;
3105
+ margin: 0;
3106
+ }
3107
+
3108
+ /* ── Inputs, selects & options — design polish (v2.12) ────────────────────── */
3109
+
3110
+ /* Uniform, comfortable dropdown option rows (Heading / Font / Size / …). */
3111
+ .yjd-rich-editor .custom-select-item-button {
3112
+ min-height: 34px;
3113
+ padding: 6px 10px !important;
3114
+ gap: 10px;
3115
+ border-radius: var(--rte-radius-sm) !important;
3116
+ }
3117
+ .yjd-rich-editor .custom-select-item-button:hover {
3118
+ background: var(--rte-accent-weak) !important;
3119
+ color: var(--rte-accent-ink) !important;
3120
+ }
3121
+ .yjd-rich-editor .custom-select-item-button.current {
3122
+ background: var(--rte-accent-weak) !important;
3123
+ color: var(--rte-accent-ink) !important;
3124
+ font-weight: 600;
3125
+ }
3126
+ /* Keep the size previews from breaking the row rhythm. */
3127
+ .yjd-rich-editor .heading-select-popup .custom-select-item-button,
3128
+ .yjd-rich-editor .font-family-select-popup .custom-select-item-button,
3129
+ .yjd-rich-editor .text-size-select-popup .custom-select-item-button {
3130
+ line-height: 1.15;
3131
+ }
3132
+
3133
+ /* Native <select> — make it look like the themed inputs, with a custom chevron
3134
+ (the OS-default control was the loudest mismatch among the popups). */
3135
+ .yjd-rich-editor select,
3136
+ .yjd-rich-editor .yjd-select-input,
3137
+ .yjd-rich-editor .tag-type-select,
3138
+ .yjd-rich-editor .import-type-select {
3139
+ -webkit-appearance: none;
3140
+ -moz-appearance: none;
3141
+ appearance: none;
3142
+ width: 100%;
3143
+ box-sizing: border-box;
3144
+ padding: 10px 36px 10px 12px;
3145
+ font: 500 14px/1.4 system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
3146
+ color: var(--rte-ink);
3147
+ background-color: var(--rte-bg);
3148
+ background-image: url("data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20width='16'%20height='16'%20viewBox='0%200%2024%2024'%20fill='none'%20stroke='%23767c8e'%20stroke-width='2'%20stroke-linecap='round'%20stroke-linejoin='round'%3E%3Cpath%20d='m6%209%206%206%206-6'/%3E%3C/svg%3E");
3149
+ background-repeat: no-repeat;
3150
+ background-position: right 12px center;
3151
+ background-size: 16px;
3152
+ border: 1px solid var(--rte-border-strong);
3153
+ border-radius: var(--rte-radius-sm);
3154
+ cursor: pointer;
3155
+ transition: border-color var(--rte-t), box-shadow var(--rte-t);
3156
+ }
3157
+ .yjd-rich-editor select:hover,
3158
+ .yjd-rich-editor .yjd-select-input:hover,
3159
+ .yjd-rich-editor .tag-type-select:hover,
3160
+ .yjd-rich-editor .import-type-select:hover {
3161
+ border-color: var(--rte-accent);
3162
+ }
3163
+ .yjd-rich-editor select:focus,
3164
+ .yjd-rich-editor .yjd-select-input:focus,
3165
+ .yjd-rich-editor .tag-type-select:focus,
3166
+ .yjd-rich-editor .import-type-select:focus {
3167
+ outline: none;
3168
+ border-color: var(--rte-accent);
3169
+ box-shadow: 0 0 0 3px var(--rte-accent-ring);
3170
+ }
3171
+
3172
+ /* Consistent text-input metrics across every popup. */
3173
+ .yjd-rich-editor .yjd-input,
3174
+ .yjd-rich-editor .yjd-find-input {
3175
+ box-sizing: border-box;
3176
+ padding: 10px 12px;
3177
+ font-size: 14px;
3178
+ line-height: 1.4;
3179
+ }
3180
+
3181
+ /* Table size picker — accent (not grey) on hover, matching the highlight. */
3182
+ .yjd-rich-editor .table-grid-cell:hover {
3183
+ background: var(--rte-accent-weak) !important;
3184
+ border-color: var(--rte-accent) !important;
3185
+ }
3186
+
3187
+ /* ── Toolbar layout (v2.13) ───────────────────────────────────────────────
3188
+ Keep icon groups packed tight on the left and push only "More" to the right
3189
+ edge. This uses the full bar width (More is flush right) WITHOUT scattering
3190
+ big gaps between every group — which looked empty on mobile / narrow bars. */
3191
+ .yjd-rich-editor .rich-editor-toolbar-1 {
3192
+ justify-content: flex-start !important;
3193
+ }
3194
+ .yjd-rich-editor .rich-editor-toolbar-1 .more-btn {
3195
+ margin-left: auto !important;
3196
+ }
3197
+
3198
+ /* ── Mobile toolbar: one horizontal-scroll row (v2.14) ────────────────────
3199
+ Instead of wrapping every tool into a cramped multi-row "More" panel, mobile
3200
+ shows a single row you swipe sideways — the pattern used by Google Docs,
3201
+ Notion, etc. (The reflow JS keeps all groups in row 1 at this width.) */
3202
+ @media (max-width: 640px) {
3203
+ .yjd-rich-editor .rich-editor-toolbar-1 {
3204
+ flex-wrap: nowrap !important;
3205
+ overflow-x: auto !important;
3206
+ overflow-y: hidden;
3207
+ -webkit-overflow-scrolling: touch;
3208
+ scrollbar-width: none; /* Firefox */
3209
+ justify-content: flex-start !important;
3210
+ padding: 6px 8px;
3211
+ scroll-padding: 8px;
3212
+ }
3213
+ .yjd-rich-editor .rich-editor-toolbar-1::-webkit-scrollbar {
3214
+ display: none; /* WebKit/Blink */
3215
+ }
3216
+ /* The overflow row + "More" button aren't used on mobile. */
3217
+ .yjd-rich-editor .rich-editor-toolbar-2,
3218
+ .yjd-rich-editor .rich-editor-toolbar-1 .more-btn {
3219
+ display: none !important;
3220
+ }
3221
+ /* Keep every group/button on one line and let the row scroll. */
3222
+ .yjd-rich-editor .toolbar-group {
3223
+ flex: 0 0 auto;
3224
+ }
3225
+ .yjd-rich-editor .toolbar-group + .toolbar-group {
3226
+ margin-left: 8px;
3227
+ }
3228
+ .yjd-rich-editor .rich-editor-toolbar-btn,
3229
+ .yjd-rich-editor .custom-select-button {
3230
+ min-width: 32px;
3231
+ height: 32px;
3232
+ padding: 0 8px;
3233
+ flex: 0 0 auto;
3234
+ }
3235
+ /* Selects keep their label readable (no truncation) — the row scrolls. */
3236
+ .yjd-rich-editor .custom-select-button {
3237
+ max-width: none;
3238
+ }
3239
+ }
3240
+
3241
+ /* Toolbar buttons hidden until usable (e.g. undo/redo before any history). */
3242
+ .yjd-rich-editor .rich-editor-toolbar-btn.rte-hidden { display: none !important; }
3243
+
3244
+ /* ── First/last block margin reset (v2.15) ────────────────────────────────
3245
+ The first block must sit exactly at the content origin (top padding) so the
3246
+ caret/text aligns with the placeholder — on mobile, `p { margin: .8em 0 }`
3247
+ was pushing the first line ~13px below the placeholder. */
3248
+ .yjd-rich-editor .rich-editor-area > :first-child { margin-top: 0 !important; }
3249
+ .yjd-rich-editor .rich-editor-area > :last-child { margin-bottom: 0 !important; }
3250
+
3251
+ /* ── Align picker: icon-only, compact row (v2.16) ─────────────────────────
3252
+ Labels removed (tooltip carries the name) → lay the 4 alignment icons out
3253
+ as a tight horizontal row of square buttons instead of wide list rows. */
3254
+ .yjd-rich-editor .align-button-container {
3255
+ flex-direction: row !important;
3256
+ width: auto !important;
3257
+ height: auto !important;
3258
+ gap: 4px;
3259
+ }
3260
+ .yjd-rich-editor .align-button {
3261
+ width: 34px !important;
3262
+ min-height: 34px !important;
3263
+ height: 34px !important;
3264
+ padding: 0 !important;
3265
+ gap: 0 !important;
3266
+ justify-content: center !important;
3267
+ }
3268
+ .yjd-rich-editor .text-align-picker-popup {
3269
+ width: auto !important;
3270
+ }
3271
+
3272
+ /* ── "More" overflow = one extra row, not a crammed wrap (v2.17) ───────────
3273
+ The secondary toolbar stays hidden until "More" is pressed; when shown it's
3274
+ a single tidy row (scrolls sideways if it ever exceeds the width) instead of
3275
+ wrapping its groups into several stacked rows. */
3276
+ .yjd-rich-editor .rich-editor-toolbar-2 {
3277
+ flex-wrap: nowrap !important;
3278
+ overflow-x: auto;
3279
+ overflow-y: hidden;
3280
+ -webkit-overflow-scrolling: touch;
3281
+ scrollbar-width: none;
3282
+ }
3283
+ .yjd-rich-editor .rich-editor-toolbar-2::-webkit-scrollbar { display: none; }
3284
+ .yjd-rich-editor .rich-editor-toolbar-2 .toolbar-group { flex: 0 0 auto; }
3285
+
3286
+ /* ── Labelled selects (v2.18) ─────────────────────────────────────────────
3287
+ A small header at the top of each dropdown + a leading icon on the trigger,
3288
+ so it's clear what Paragraph / Font / Size / Line-height / Case control. */
3289
+ .yjd-rich-editor .custom-select-header {
3290
+ padding: 8px 12px 6px;
3291
+ font-size: 11px;
3292
+ font-weight: 600;
3293
+ letter-spacing: 0.05em;
3294
+ text-transform: uppercase;
3295
+ color: var(--rte-muted);
3296
+ border-bottom: 1px solid var(--rte-border);
3297
+ margin-bottom: 4px;
3298
+ white-space: nowrap;
3299
+ }
3300
+ .yjd-rich-editor .custom-select-button .select-lead-icon {
3301
+ width: 16px;
3302
+ height: 16px;
3303
+ flex: 0 0 auto;
3304
+ display: inline-flex;
3305
+ align-items: center;
3306
+ justify-content: center;
3307
+ color: var(--rte-muted);
3308
+ margin-right: 4px;
3309
+ }
3310
+ .yjd-rich-editor .custom-select-button .select-lead-icon svg {
3311
+ width: 16px;
3312
+ height: 16px;
3313
+ display: block;
3314
+ stroke: currentColor;
3315
+ fill: none;
3316
+ }
3317
+
3318
+
3319
+ /* ── Select trigger: keep value on one line (v2.20) ───────────────────────
3320
+ Long values (e.g. "Times New Roman") must not wrap to a 2nd line and break
3321
+ the button height — clamp to one line with an ellipsis; icon + chevron stay. */
3322
+ .yjd-rich-editor .custom-select-button {
3323
+ white-space: nowrap;
3324
+ overflow: hidden;
3325
+ }
3326
+ .yjd-rich-editor .custom-select-button .button-text {
3327
+ flex: 1 1 auto;
3328
+ min-width: 0;
3329
+ white-space: nowrap;
3330
+ overflow: hidden;
3331
+ text-overflow: ellipsis;
3332
+ }
3333
+ .yjd-rich-editor .custom-select-button .select-lead-icon,
3334
+ .yjd-rich-editor .custom-select-button .dropdown-icon {
3335
+ flex: 0 0 auto;
3336
+ }
3337
+
3338
+ /* ── Align popover: match the other popovers (v2.21) ───────────────────────
3339
+ It had asymmetric padding (bottom 0) + a one-off radius, so it looked out of
3340
+ sync. Use the shared shell's symmetric padding + token radius. */
3341
+ .yjd-rich-editor .text-align-picker-popup {
3342
+ padding: 6px !important;
3343
+ border-radius: var(--rte-radius-md) !important;
3344
+ }
3345
+ .yjd-rich-editor .align-button-container {
3346
+ padding: 0 !important;
3347
+ }
3348
+
3349
+ /* ── A11y: statusbar text contrast (v2.22) ────────────────────────────────
3350
+ --rte-muted (#767c8e) on the near-white statusbar was only 4.02:1; darken
3351
+ the breadcrumb + word-count to meet WCAG AA (>=4.5:1). */
3352
+ .yjd-rich-editor .rich-editor-breadcrumb,
3353
+ .yjd-rich-editor .wordcount {
3354
+ color: #5b6373;
3355
+ }
3356
+
3357
+ /* ── Find & Replace: icon buttons (v2.23) ─────────────────────────────────
3358
+ Center the SVG icons (prev/next/close) in the square nav buttons. */
3359
+ .yjd-rich-editor .yjd-find-btn {
3360
+ display: inline-flex;
3361
+ align-items: center;
3362
+ justify-content: center;
3363
+ }
3364
+ .yjd-rich-editor .yjd-find-icon .icon,
3365
+ .yjd-rich-editor .yjd-find-icon .icon svg {
3366
+ width: 16px;
3367
+ height: 16px;
3368
+ display: block;
3369
+ }
3370
+ .yjd-rich-editor .yjd-find-icon .icon svg {
3371
+ stroke: currentColor;
3372
+ fill: none;
3373
+ }