@standhigher/react-email-editor 0.1.0 → 0.2.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.
package/dist/styles.css CHANGED
@@ -61,6 +61,459 @@
61
61
  }
62
62
 
63
63
 
64
+ /* ---------- 共享表单控件 ---------- */
65
+
66
+ .ree-input {
67
+ width: 100%;
68
+ border: 1px solid var(--ree-border, #e3e3e5);
69
+ border-radius: var(--ree-radius, 8px);
70
+ --ree-control-padding-x: 12px;
71
+ --ree-control-padding-y: 8px;
72
+ --ree-control-padding-end: var(--ree-control-padding-x);
73
+ padding: var(--ree-control-padding-y) var(--ree-control-padding-end) var(--ree-control-padding-y) var(--ree-control-padding-x);
74
+ font-size: 14px;
75
+ line-height: 1.4;
76
+ font-family: inherit;
77
+ color: var(--ree-text, #202223);
78
+ background: var(--ree-panel, #ffffff);
79
+ transition: border-color 0.12s ease, box-shadow 0.12s ease;
80
+ }
81
+
82
+ .ree-input:focus {
83
+ outline: none;
84
+ border: 2px solid #202223;
85
+ padding: max(0px, calc(var(--ree-control-padding-y) - 1px)) calc(var(--ree-control-padding-end) - 1px) max(0px, calc(var(--ree-control-padding-y) - 1px)) calc(var(--ree-control-padding-x) - 1px);
86
+ box-shadow: none;
87
+ }
88
+
89
+ .ree-select {
90
+ display: block;
91
+ min-width: 0;
92
+ width: 100%;
93
+ position: relative;
94
+ }
95
+
96
+ .ree-select .ree-input {
97
+ appearance: none;
98
+ -webkit-appearance: none;
99
+ --ree-control-padding-end: 40px;
100
+ cursor: pointer;
101
+ background-color: var(--ree-panel);
102
+ }
103
+
104
+ .ree-select-icon {
105
+ position: absolute;
106
+ top: 0;
107
+ right: 12px;
108
+ bottom: 0;
109
+ display: flex;
110
+ align-items: center;
111
+ pointer-events: none;
112
+ color: var(--ree-muted);
113
+ }
114
+
115
+ .ree-select.is-compact {
116
+ width: auto;
117
+ flex-shrink: 0;
118
+ }
119
+
120
+ .ree-select.is-compact .ree-input {
121
+ --ree-control-padding-x: 8px;
122
+ --ree-control-padding-y: 0px;
123
+ --ree-control-padding-end: 32px;
124
+ height: 28px;
125
+ font-size: 12px;
126
+ line-height: 1;
127
+ border-radius: 6px;
128
+ }
129
+
130
+ .ree-select.is-compact .ree-select-icon svg {
131
+ width: 12px;
132
+ height: 12px;
133
+ }
134
+
135
+ .ree-color-control {
136
+ display: inline-flex;
137
+ min-width: 0;
138
+ }
139
+
140
+ .ree-color-chip {
141
+ display: inline-flex;
142
+ align-items: center;
143
+ gap: 8px;
144
+ min-width: 0;
145
+ width: fit-content;
146
+ max-width: 100%;
147
+ justify-self: start;
148
+ cursor: pointer;
149
+ appearance: none;
150
+ border: 0;
151
+ padding: 0;
152
+ background: transparent;
153
+ font: inherit;
154
+ }
155
+
156
+ .ree-color-swatch {
157
+ position: relative;
158
+ width: 36px;
159
+ height: 22px;
160
+ flex-shrink: 0;
161
+ }
162
+
163
+ .ree-color-swatch-face {
164
+ display: block;
165
+ width: 100%;
166
+ height: 100%;
167
+ border: 1px solid #d2d5d8;
168
+ border-radius: 999px;
169
+ background: #ffffff;
170
+ }
171
+
172
+ .ree-color-swatch-face.is-empty {
173
+ background:
174
+ linear-gradient(45deg, #e3e3e5 25%, transparent 25%),
175
+ linear-gradient(-45deg, #e3e3e5 25%, transparent 25%),
176
+ linear-gradient(45deg, transparent 75%, #e3e3e5 75%),
177
+ linear-gradient(-45deg, transparent 75%, #e3e3e5 75%);
178
+ background-size: 8px 8px;
179
+ background-position: 0 0, 0 4px, 4px -4px, -4px 0;
180
+ background-color: #ffffff;
181
+ }
182
+
183
+ .ree-color-chip-label {
184
+ min-width: 0;
185
+ overflow-wrap: anywhere;
186
+ color: var(--ree-text);
187
+ font-size: 13px;
188
+ line-height: 1.3;
189
+ }
190
+
191
+ .ree-checkbox-control {
192
+ display: inline-flex;
193
+ align-items: center;
194
+ justify-self: start;
195
+ gap: 8px;
196
+ width: fit-content;
197
+ max-width: 100%;
198
+ cursor: pointer;
199
+ }
200
+
201
+ .ree-checkbox-control input {
202
+ appearance: none;
203
+ display: grid;
204
+ place-items: center;
205
+ flex-shrink: 0;
206
+ width: 16px;
207
+ height: 16px;
208
+ margin: 0;
209
+ border: 1px solid #b5b5b5;
210
+ border-radius: 3px;
211
+ background: #ffffff;
212
+ cursor: pointer;
213
+ }
214
+
215
+ .ree-checkbox-control input:checked {
216
+ border-color: #202223;
217
+ background: #202223;
218
+ }
219
+
220
+ .ree-checkbox-control input:checked::before {
221
+ content: "";
222
+ width: 5px;
223
+ height: 9px;
224
+ margin-top: -2px;
225
+ border: solid #ffffff;
226
+ border-width: 0 2px 2px 0;
227
+ transform: rotate(45deg);
228
+ }
229
+
230
+ .ree-checkbox-control input:focus-visible,
231
+ .ree-color-chip:focus-visible .ree-color-swatch-face {
232
+ border: 2px solid #202223;
233
+ }
234
+
235
+ .ree-checkbox-control input:focus,
236
+ .ree-color-chip:focus {
237
+ outline: none;
238
+ box-shadow: none;
239
+ }
240
+
241
+ .ree-checkbox-control:has(input:disabled) {
242
+ opacity: 0.4;
243
+ cursor: default;
244
+ }
245
+
246
+ .ree-checkbox-control input:disabled,
247
+ .ree-select .ree-input:disabled {
248
+ cursor: default;
249
+ }
250
+
251
+ .ree-range {
252
+ -webkit-appearance: none;
253
+ appearance: none;
254
+ display: block;
255
+ flex: 1 1 auto;
256
+ width: 100%;
257
+ min-width: 0;
258
+ height: 20px;
259
+ margin: 0;
260
+ background: transparent;
261
+ cursor: pointer;
262
+ }
263
+
264
+ .ree-range::-webkit-slider-container {
265
+ width: 100%;
266
+ }
267
+
268
+ .ree-range::-webkit-slider-runnable-track {
269
+ width: 100%;
270
+ height: 4px;
271
+ border: 0;
272
+ border-radius: 999px;
273
+ background: linear-gradient(to right, #303030 0%, #303030 var(--ree-range-progress), #e3e3e5 var(--ree-range-progress), #e3e3e5 100%);
274
+ }
275
+
276
+ .ree-range::-webkit-slider-thumb {
277
+ appearance: none;
278
+ width: 14px;
279
+ height: 14px;
280
+ margin-top: -5px;
281
+ border: 0;
282
+ border-radius: 50%;
283
+ background: #303030;
284
+ }
285
+
286
+ .ree-range::-moz-range-track {
287
+ height: 4px;
288
+ border: 0;
289
+ border-radius: 999px;
290
+ background: #e3e3e5;
291
+ }
292
+
293
+ .ree-range::-moz-range-progress {
294
+ height: 4px;
295
+ border: 0;
296
+ border-radius: 999px;
297
+ background: #303030;
298
+ }
299
+
300
+ .ree-range::-moz-range-thumb {
301
+ width: 14px;
302
+ height: 14px;
303
+ border: 0;
304
+ border-radius: 50%;
305
+ background: #303030;
306
+ }
307
+
308
+ /* ---------- 共享普通按钮 ---------- */
309
+
310
+ .ree-btn {
311
+ appearance: none;
312
+ border: 1px solid #b5b5b5;
313
+ background: var(--ree-panel, #ffffff);
314
+ color: var(--ree-text, #202223);
315
+ border-radius: var(--ree-radius, 8px);
316
+ --ree-button-padding-y: 8px;
317
+ --ree-button-padding-x: 16px;
318
+ padding: var(--ree-button-padding-y) var(--ree-button-padding-x);
319
+ font-size: 14px;
320
+ font-weight: 500;
321
+ line-height: 1.4;
322
+ cursor: pointer;
323
+ font-family: inherit;
324
+ transition: background 0.12s ease, border-color 0.12s ease,
325
+ box-shadow 0.12s ease;
326
+ }
327
+
328
+ .ree-btn:hover {
329
+ background: var(--ree-panel-secondary);
330
+ border-color: var(--ree-border);
331
+ }
332
+
333
+ .ree-btn:active {
334
+ background: #f0f0f1;
335
+ }
336
+
337
+ .ree-btn-primary {
338
+ background: var(--ree-primary, #005bd3);
339
+ border-color: var(--ree-primary, #005bd3);
340
+ color: var(--ree-primary-fg, #ffffff);
341
+ }
342
+
343
+ .ree-btn-primary:hover {
344
+ background: var(--ree-primary-hover);
345
+ border-color: var(--ree-primary-hover);
346
+ }
347
+
348
+ .ree-btn-primary:active {
349
+ background: var(--ree-primary-hover);
350
+ }
351
+
352
+
353
+ .ree-btn:disabled {
354
+ opacity: 0.4;
355
+ cursor: default;
356
+ }
357
+
358
+ .ree-btn-solid {
359
+ background: #202223;
360
+ border-color: #202223;
361
+ color: #ffffff;
362
+ }
363
+
364
+ .ree-btn-solid:hover,
365
+ .ree-btn-solid:active {
366
+ background: #000000;
367
+ border-color: #000000;
368
+ }
369
+
370
+ .ree-btn:focus-visible {
371
+ outline: none;
372
+ box-shadow: none;
373
+ border-width: 2px;
374
+ border-color: #202223;
375
+ padding: calc(var(--ree-button-padding-y) - 1px) calc(var(--ree-button-padding-x) - 1px);
376
+ }
377
+
378
+ .ree-reset {
379
+ appearance: none;
380
+ display: inline-flex;
381
+ align-items: center;
382
+ justify-content: center;
383
+ width: 22px;
384
+ height: 22px;
385
+ flex-shrink: 0;
386
+ padding: 0;
387
+ border: 0;
388
+ border-radius: 6px;
389
+ background: transparent;
390
+ color: var(--ree-muted);
391
+ cursor: pointer;
392
+ }
393
+
394
+ .ree-reset:hover {
395
+ background: var(--ree-panel-secondary);
396
+ color: var(--ree-text);
397
+ }
398
+
399
+ .ree-reset:disabled {
400
+ opacity: 0.35;
401
+ cursor: default;
402
+ }
403
+
404
+ .ree-reset:disabled:hover {
405
+ background: transparent;
406
+ color: var(--ree-muted);
407
+ }
408
+
409
+ .ree-reset:focus-visible {
410
+ outline: 1px solid #202223;
411
+ outline-offset: -1px;
412
+ }
413
+
414
+ .ree-color-picker {
415
+ position: fixed;
416
+ inset: auto;
417
+ width: min(256px, calc(100vw - 16px));
418
+ max-height: calc(100dvh - 16px);
419
+ margin: 0;
420
+ padding: 12px;
421
+ overflow: auto;
422
+ border: 1px solid var(--ree-border, #e3e3e5);
423
+ border-radius: 10px;
424
+ background: var(--ree-panel, #ffffff);
425
+ box-shadow: var(--ree-shadow-lg, 0 6px 32px rgba(31, 33, 36, 0.16));
426
+ color: var(--ree-text, #202223);
427
+ font: 400 13px/1.4 var(--ree-font, Arial, sans-serif);
428
+ }
429
+
430
+ .ree-color-picker:popover-open {
431
+ display: grid;
432
+ gap: 12px;
433
+ }
434
+
435
+ .ree-color-saturation {
436
+ position: relative;
437
+ height: 144px;
438
+ border-radius: 6px;
439
+ background: linear-gradient(to top, #000000, transparent), linear-gradient(to right, #ffffff, transparent), var(--ree-color-hue);
440
+ cursor: crosshair;
441
+ touch-action: none;
442
+ }
443
+
444
+ .ree-color-saturation:focus-visible {
445
+ outline: 2px solid #202223;
446
+ outline-offset: 2px;
447
+ }
448
+
449
+ .ree-color-cursor {
450
+ position: absolute;
451
+ width: 12px;
452
+ height: 12px;
453
+ border: 2px solid #ffffff;
454
+ border-radius: 50%;
455
+ box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.5);
456
+ transform: translate(-50%, -50%);
457
+ pointer-events: none;
458
+ }
459
+
460
+ .ree-color-hue .ree-range::-webkit-slider-runnable-track {
461
+ height: 10px;
462
+ background: linear-gradient(to right, #ff0000, #ffff00, #00ff00, #00ffff, #0000ff, #ff00ff, #ff0000);
463
+ }
464
+
465
+ .ree-color-hue .ree-range::-moz-range-track {
466
+ height: 10px;
467
+ background: linear-gradient(to right, #ff0000, #ffff00, #00ff00, #00ffff, #0000ff, #ff00ff, #ff0000);
468
+ }
469
+
470
+ .ree-color-hue .ree-range::-moz-range-progress {
471
+ background: transparent;
472
+ }
473
+
474
+ .ree-color-hue .ree-range::-webkit-slider-thumb {
475
+ margin-top: -2px;
476
+ border: 2px solid #ffffff;
477
+ box-shadow: 0 0 0 1px #6d7175;
478
+ }
479
+
480
+ .ree-color-hue .ree-range::-moz-range-thumb {
481
+ border: 2px solid #ffffff;
482
+ box-shadow: 0 0 0 1px #6d7175;
483
+ }
484
+
485
+ .ree-color-hex-row {
486
+ display: flex;
487
+ align-items: center;
488
+ gap: 10px;
489
+ }
490
+
491
+ .ree-color-preview {
492
+ flex: 0 0 28px;
493
+ height: 28px;
494
+ border: 1px solid var(--ree-border);
495
+ border-radius: 6px;
496
+ }
497
+
498
+ .ree-color-hex-field {
499
+ display: flex;
500
+ flex: 1;
501
+ align-items: center;
502
+ gap: 8px;
503
+ min-width: 0;
504
+ }
505
+
506
+ .ree-color-hex-field .ree-input {
507
+ min-width: 0;
508
+ font-variant-numeric: tabular-nums;
509
+ }
510
+
511
+ .ree-color-error {
512
+ margin: 0;
513
+ color: var(--ree-danger, #d72c0d);
514
+ font-size: 12px;
515
+ }
516
+
64
517
  /* ---------- 邮件主题 ---------- */
65
518
 
66
519
  .ree-subject-bar {
@@ -84,20 +537,7 @@
84
537
  .ree-subject-input {
85
538
  flex: 1 1 360px;
86
539
  min-width: 240px;
87
- border: 1px solid var(--ree-border);
88
- border-radius: var(--ree-radius);
89
- background: var(--ree-panel);
90
- color: var(--ree-text);
91
- font: inherit;
92
- font-size: 14px;
93
- line-height: 1.4;
94
- padding: 8px 12px;
95
- }
96
-
97
- .ree-subject-input:focus {
98
- outline: none;
99
- border-color: var(--ree-primary);
100
- box-shadow: 0 0 0 1px var(--ree-primary);
540
+ width: auto;
101
541
  }
102
542
 
103
543
  .ree-subject-count {
@@ -138,12 +578,6 @@
138
578
  min-width: 240px;
139
579
  }
140
580
 
141
- .ree-personalization-empty {
142
- padding: 8px 10px;
143
- color: var(--ree-muted);
144
- font-size: 13px;
145
- }
146
-
147
581
  .ree-subject-hint {
148
582
  flex: 0 1 auto;
149
583
  margin: 0;
@@ -153,56 +587,6 @@
153
587
  white-space: nowrap;
154
588
  }
155
589
 
156
- .ree-subject-reset {
157
- flex-shrink: 0;
158
- margin-left: auto;
159
- }
160
-
161
- .ree-btn {
162
- appearance: none;
163
- border: 1px solid var(--ree-border, #e3e3e5);
164
- background: var(--ree-panel, #ffffff);
165
- color: var(--ree-text, #202223);
166
- border-radius: var(--ree-radius, 8px);
167
- padding: 8px 16px;
168
- font-size: 14px;
169
- font-weight: 500;
170
- line-height: 1.4;
171
- cursor: pointer;
172
- font-family: inherit;
173
- transition: background 0.12s ease, border-color 0.12s ease,
174
- box-shadow 0.12s ease;
175
- }
176
-
177
- .ree-btn:hover {
178
- background: var(--ree-panel-secondary);
179
- border-color: var(--ree-border);
180
- }
181
-
182
- .ree-btn:active {
183
- background: #f0f0f1;
184
- }
185
-
186
- .ree-btn:focus-visible {
187
- outline: none;
188
- box-shadow: 0 0 0 2px var(--ree-panel), 0 0 0 4px var(--ree-primary);
189
- }
190
-
191
- .ree-btn-primary {
192
- background: var(--ree-primary, #005bd3);
193
- border-color: var(--ree-primary, #005bd3);
194
- color: var(--ree-primary-fg, #ffffff);
195
- }
196
-
197
- .ree-btn-primary:hover {
198
- background: var(--ree-primary-hover);
199
- border-color: var(--ree-primary-hover);
200
- }
201
-
202
- .ree-btn-primary:active {
203
- background: var(--ree-primary-hover);
204
- }
205
-
206
590
 
207
591
  /* ---------- 三栏布局 ---------- */
208
592
 
@@ -223,8 +607,8 @@
223
607
  display: flex;
224
608
  align-items: center;
225
609
  flex-shrink: 0;
226
- min-height: 52px;
227
- padding: 8px 16px;
610
+ height: 52px;
611
+ padding: 7px 16px;
228
612
  font-weight: 600;
229
613
  font-size: 12px;
230
614
  color: var(--ree-muted);
@@ -436,6 +820,14 @@
436
820
  flex: 1;
437
821
  min-height: 0;
438
822
  min-width: 0;
823
+ background-color: var(--ree-panel);
824
+ background-image:
825
+ linear-gradient(45deg, rgba(0, 0, 0, 0.02) 25%, transparent 25%),
826
+ linear-gradient(-45deg, rgba(0, 0, 0, 0.02) 25%, transparent 25%),
827
+ linear-gradient(45deg, transparent 75%, rgba(0, 0, 0, 0.02) 75%),
828
+ linear-gradient(-45deg, transparent 75%, rgba(0, 0, 0, 0.02) 75%);
829
+ background-size: 20px 20px;
830
+ background-position: 0 0, 0 10px, 10px -10px, -10px 0;
439
831
  }
440
832
 
441
833
  .ree-stage-view[hidden] {
@@ -444,14 +836,13 @@
444
836
 
445
837
  .ree-canvas,
446
838
  .ree-preview-stage {
839
+ display: flex;
840
+ flex-direction: column;
447
841
  flex: 1;
448
842
  min-height: 0;
449
843
  min-width: 0;
450
844
  overflow: auto;
451
- }
452
-
453
- .ree-canvas {
454
- padding: 64px 24px 40px;
845
+ padding: 64px 24px;
455
846
  }
456
847
 
457
848
  .ree-canvas.is-over {
@@ -462,7 +853,6 @@
462
853
  .ree-email-surface {
463
854
  box-sizing: border-box;
464
855
  margin: 0 auto;
465
- box-shadow: var(--ree-shadow-md);
466
856
  }
467
857
 
468
858
  .ree-root .ree-canvas-inner {
@@ -475,10 +865,13 @@
475
865
  gap: var(--ree-block-gap, 0px);
476
866
  }
477
867
 
478
- .ree-preview-stage {
479
- display: flex;
480
- justify-content: center;
481
- padding: 24px 16px;
868
+ .ree-preview-frame {
869
+ display: block;
870
+ width: 100%;
871
+ height: 1px;
872
+ flex-shrink: 0;
873
+ border: none;
874
+ background: #ffffff;
482
875
  }
483
876
 
484
877
  .ree-inspector-scroll {
@@ -495,35 +888,55 @@
495
888
  }
496
889
 
497
890
 
498
- .ree-email-viewport { box-sizing: border-box; }
891
+ .ree-email-viewport {
892
+ box-sizing: border-box;
893
+ flex: 1 0 auto;
894
+ }
895
+
896
+ .ree-canvas .ree-email-viewport {
897
+ background: rgb(246, 246, 247);
898
+ box-shadow: var(--ree-shadow-md);
899
+ }
499
900
 
500
901
  /* ---------- 区块 ---------- */
501
902
 
502
903
  .ree-block {
503
904
  position: relative;
504
905
  border: 0;
505
- border-radius: var(--ree-radius-sm);
506
- outline: 1px solid transparent;
507
- outline-offset: -1px;
906
+ border-radius: 0;
508
907
  background: transparent;
509
908
  cursor: pointer;
510
- transition: background 0.12s ease, outline-color 0.12s ease,
511
- box-shadow 0.12s ease;
909
+ transition: background 0.12s ease;
512
910
  width: 100%;
513
911
  display: flow-root;
514
912
  }
515
913
 
516
- /* hover:区块背景 + 边框均为浅蓝(参照 unlayer) */
914
+ /* hover 和选中共用外侧辅助框,内沿贴住区块,不覆盖真实边框或占用布局空间。 */
915
+ .ree-block-highlight {
916
+ position: absolute;
917
+ inset: -1px;
918
+ z-index: 5;
919
+ border: 1px solid transparent;
920
+ pointer-events: none;
921
+ transition: border-color 0.12s ease;
922
+ }
923
+
517
924
  .ree-block:hover {
925
+ z-index: 1;
518
926
  background: var(--ree-accent-bg);
519
- outline-color: var(--ree-accent-border);
927
+ }
928
+
929
+ .ree-block:hover > .ree-block-highlight {
930
+ border-color: var(--ree-accent-border);
520
931
  }
521
932
 
522
933
  .ree-block.is-selected {
523
934
  z-index: 8;
524
935
  background: var(--ree-accent-bg-strong);
525
- outline-color: var(--ree-primary);
526
- box-shadow: 0 0 0 1px var(--ree-primary);
936
+ }
937
+
938
+ .ree-block.is-selected > .ree-block-highlight {
939
+ border-color: var(--ree-primary);
527
940
  }
528
941
 
529
942
  .ree-block.is-dragging {
@@ -627,7 +1040,7 @@
627
1040
  .ree-block-toolbar {
628
1041
  position: absolute;
629
1042
  top: calc(100% + 4px);
630
- left: 8px;
1043
+ left: 0;
631
1044
  z-index: 7;
632
1045
  display: flex;
633
1046
  gap: 2px;
@@ -636,9 +1049,11 @@
636
1049
  border-radius: var(--ree-radius);
637
1050
  padding: 3px;
638
1051
  box-shadow: var(--ree-shadow-md);
1052
+ font-family: var(--ree-font);
639
1053
  }
640
1054
 
641
1055
  .ree-block-btn {
1056
+ position: relative;
642
1057
  appearance: none;
643
1058
  border: none;
644
1059
  background: transparent;
@@ -658,11 +1073,58 @@
658
1073
  color: var(--ree-primary);
659
1074
  }
660
1075
 
1076
+ .ree-block-btn:active {
1077
+ background: var(--ree-accent-bg-strong);
1078
+ color: var(--ree-primary);
1079
+ }
1080
+
1081
+ .ree-block-btn:focus-visible {
1082
+ outline: 2px solid var(--ree-primary);
1083
+ outline-offset: 1px;
1084
+ }
1085
+
661
1086
  .ree-block-btn.ree-danger:hover {
662
1087
  background: var(--ree-danger-soft);
663
1088
  color: var(--ree-danger);
664
1089
  }
665
1090
 
1091
+ .ree-block-btn.ree-danger:active {
1092
+ background: var(--ree-danger-soft);
1093
+ color: var(--ree-danger);
1094
+ }
1095
+
1096
+ .ree-block-tooltip {
1097
+ position: absolute;
1098
+ top: calc(100% + 8px);
1099
+ left: 0;
1100
+ z-index: 10;
1101
+ display: none;
1102
+ padding: 6px 9px;
1103
+ border-radius: var(--ree-radius-sm);
1104
+ background: var(--ree-text);
1105
+ color: var(--ree-panel);
1106
+ box-shadow: var(--ree-shadow-md);
1107
+ font-size: 12px;
1108
+ font-weight: 500;
1109
+ line-height: 1.4;
1110
+ white-space: nowrap;
1111
+ cursor: default;
1112
+ }
1113
+
1114
+ .ree-block-tooltip::before {
1115
+ content: "";
1116
+ position: absolute;
1117
+ top: -8px;
1118
+ left: 0;
1119
+ width: 100%;
1120
+ height: 8px;
1121
+ }
1122
+
1123
+ .ree-block-btn:hover .ree-block-tooltip,
1124
+ .ree-block-btn:focus-visible .ree-block-tooltip {
1125
+ display: block;
1126
+ }
1127
+
666
1128
  .ree-block-content {
667
1129
  width: 100%;
668
1130
  overflow: hidden;
@@ -738,6 +1200,10 @@
738
1200
  pointer-events: none;
739
1201
  }
740
1202
 
1203
+ .ree-button-canvas-row {
1204
+ width: 100%;
1205
+ border: 0;
1206
+ }
741
1207
 
742
1208
  /* ---------- 富文本 ---------- */
743
1209
 
@@ -755,8 +1221,9 @@
755
1221
  left: 0;
756
1222
  visibility: hidden;
757
1223
  display: flex;
758
- flex-direction: column;
759
- gap: 2px;
1224
+ flex-wrap: wrap;
1225
+ align-items: center;
1226
+ gap: 4px 0;
760
1227
  width: auto;
761
1228
  margin: 0;
762
1229
  padding: 4px;
@@ -773,19 +1240,27 @@
773
1240
  visibility: visible;
774
1241
  }
775
1242
 
776
- .ree-rte-row {
1243
+ .ree-rte-group {
777
1244
  display: flex;
778
- align-items: center;
1245
+ flex: 0 0 auto;
779
1246
  flex-wrap: wrap;
1247
+ align-items: center;
780
1248
  gap: 2px;
1249
+ max-width: 100%;
1250
+ box-sizing: border-box;
1251
+ padding: 0 4px;
1252
+ }
1253
+
1254
+ .ree-rte-group + .ree-rte-group {
1255
+ border-inline-start: 1px solid var(--ree-border);
781
1256
  }
782
1257
 
783
- .ree-rte-sep {
1258
+ .ree-rte-group.is-row-start {
1259
+ border-inline-start-color: transparent;
1260
+ }
1261
+
1262
+ .ree-rte-group > * {
784
1263
  flex-shrink: 0;
785
- align-self: stretch;
786
- width: 1px;
787
- margin: 4px 4px;
788
- background: var(--ree-border);
789
1264
  }
790
1265
 
791
1266
  .ree-tool-btn,
@@ -899,12 +1374,6 @@
899
1374
  right: 0;
900
1375
  }
901
1376
 
902
- .ree-rte-menu.is-link {
903
- min-width: 0;
904
- padding: 0;
905
- overflow: visible;
906
- }
907
-
908
1377
  .ree-rte-pop.is-up .ree-rte-menu {
909
1378
  top: auto;
910
1379
  bottom: calc(100% + 6px);
@@ -933,46 +1402,6 @@
933
1402
  font-weight: 600;
934
1403
  }
935
1404
 
936
- .ree-rte-swatches {
937
- display: grid;
938
- grid-template-columns: repeat(6, 22px);
939
- gap: 6px;
940
- padding: 4px;
941
- }
942
-
943
- .ree-rte-swatch {
944
- width: 22px;
945
- height: 22px;
946
- padding: 0;
947
- border: 1px solid rgba(32, 34, 35, 0.16);
948
- border-radius: 4px;
949
- cursor: pointer;
950
- }
951
-
952
- .ree-rte-swatch.is-active {
953
- outline: 2px solid #202223;
954
- outline-offset: 1px;
955
- }
956
-
957
- .ree-rte-color-actions {
958
- display: flex;
959
- gap: 6px;
960
- padding: 4px;
961
- }
962
-
963
- .ree-rte-color-actions .ree-btn {
964
- padding: 6px 10px;
965
- font-size: 13px;
966
- }
967
-
968
- .ree-rte-color-input {
969
- position: absolute;
970
- width: 1px;
971
- height: 1px;
972
- opacity: 0;
973
- pointer-events: none;
974
- }
975
-
976
1405
  .ree-rte-emoji-grid {
977
1406
  display: grid;
978
1407
  grid-template-columns: repeat(8, 28px);
@@ -991,26 +1420,8 @@
991
1420
  line-height: 1;
992
1421
  }
993
1422
 
994
- .ree-rte-emoji:hover {
995
- background: var(--ree-panel-secondary);
996
- }
997
-
998
- .ree-rte-link {
999
- display: flex;
1000
- flex-direction: column;
1001
- gap: 10px;
1002
- width: 280px;
1003
- padding: 6px;
1004
- }
1005
-
1006
- .ree-rte-link-actions {
1007
- display: flex;
1008
- justify-content: flex-end;
1009
- gap: 8px;
1010
- }
1011
-
1012
- .ree-rte-link-actions .ree-btn {
1013
- padding: 6px 12px;
1423
+ .ree-rte-emoji:hover {
1424
+ background: var(--ree-panel-secondary);
1014
1425
  }
1015
1426
 
1016
1427
  .ree-rte-variables {
@@ -1041,12 +1452,19 @@
1041
1452
 
1042
1453
  .ree-rte-metric-label {
1043
1454
  display: flex;
1455
+ align-items: center;
1044
1456
  justify-content: space-between;
1045
1457
  gap: 8px;
1046
1458
  color: var(--ree-muted);
1047
1459
  font-size: 12px;
1048
1460
  }
1049
1461
 
1462
+ .ree-rte-metric-meta {
1463
+ display: inline-flex;
1464
+ align-items: center;
1465
+ gap: 6px;
1466
+ }
1467
+
1050
1468
  .ree-rte-option:disabled {
1051
1469
  opacity: 0.35;
1052
1470
  cursor: default;
@@ -1080,6 +1498,10 @@
1080
1498
  font-size: 0.75em;
1081
1499
  }
1082
1500
 
1501
+ .ree-rte-button .ProseMirror p {
1502
+ margin: 0;
1503
+ text-align: center;
1504
+ }
1083
1505
 
1084
1506
  /* ---------- 变量 ---------- */
1085
1507
 
@@ -1151,6 +1573,12 @@
1151
1573
 
1152
1574
  /* ---------- 配置区 ---------- */
1153
1575
 
1576
+ .ree-col-right {
1577
+ --ree-primary: #202223;
1578
+ --ree-primary-hover: #303030;
1579
+ --ree-primary-soft: #f6f6f7;
1580
+ }
1581
+
1154
1582
  .ree-inspector {
1155
1583
  --ree-inspector-section-space: 16px;
1156
1584
  padding: 20px 16px;
@@ -1259,47 +1687,40 @@
1259
1687
  margin-left: auto;
1260
1688
  }
1261
1689
 
1262
- .ree-input {
1263
- width: 100%;
1264
- border: 1px solid var(--ree-border, #e3e3e5);
1265
- border-radius: var(--ree-radius, 8px);
1266
- padding: 8px 12px;
1267
- font-size: 14px;
1268
- line-height: 1.4;
1269
- font-family: inherit;
1270
- color: var(--ree-text, #202223);
1271
- background: var(--ree-panel, #ffffff);
1272
- transition: border-color 0.12s ease, box-shadow 0.12s ease;
1690
+ .ree-inspector-advanced summary {
1691
+ cursor: pointer;
1692
+ color: var(--ree-muted);
1693
+ font-size: 12px;
1273
1694
  }
1274
1695
 
1275
- .ree-input:focus {
1276
- outline: none;
1277
- border-color: var(--ree-primary, #005bd3);
1278
- box-shadow: 0 0 0 1px var(--ree-primary, #005bd3);
1696
+ .ree-inspector-advanced[open] summary {
1697
+ margin-bottom: 14px;
1279
1698
  }
1280
1699
 
1281
- .ree-select {
1700
+ .ree-field-label:has(> .ree-var-wrap) {
1282
1701
  position: relative;
1702
+ justify-content: flex-start;
1283
1703
  }
1284
1704
 
1285
- .ree-select .ree-input {
1286
- appearance: none;
1287
- -webkit-appearance: none;
1288
- padding-right: 36px;
1289
- background-color: var(--ree-panel);
1705
+ .ree-field-label > .ree-var-wrap {
1706
+ position: static;
1290
1707
  }
1291
1708
 
1292
- .ree-select-icon {
1293
- position: absolute;
1294
- top: 0;
1295
- right: 10px;
1296
- bottom: 0;
1297
- display: flex;
1298
- align-items: center;
1299
- pointer-events: none;
1300
- color: var(--ree-muted);
1709
+ .ree-field-label .ree-var-menu {
1710
+ left: 0;
1711
+ width: min(280px, 100%);
1712
+ min-width: 0;
1713
+ }
1714
+
1715
+ .ree-field-label .ree-var-name,
1716
+ .ree-field-label .ree-var-label {
1717
+ max-width: 100%;
1718
+ overflow-wrap: anywhere;
1719
+ white-space: pre-wrap;
1301
1720
  }
1302
1721
 
1722
+ /* ---------- 配置控件 ---------- */
1723
+
1303
1724
  .ree-textarea {
1304
1725
  resize: vertical;
1305
1726
  min-height: 60px;
@@ -1338,8 +1759,8 @@
1338
1759
  }
1339
1760
 
1340
1761
  .ree-color-grid {
1341
- display: grid;
1342
- grid-template-columns: 1fr 1fr;
1762
+ display: flex;
1763
+ flex-wrap: wrap;
1343
1764
  gap: 12px 16px;
1344
1765
  }
1345
1766
 
@@ -1350,83 +1771,6 @@
1350
1771
  min-width: 0;
1351
1772
  }
1352
1773
 
1353
- .ree-color-chip {
1354
- display: flex;
1355
- align-items: center;
1356
- gap: 8px;
1357
- min-width: 0;
1358
- cursor: pointer;
1359
- }
1360
-
1361
- .ree-color-swatch {
1362
- position: relative;
1363
- width: 36px;
1364
- height: 22px;
1365
- flex-shrink: 0;
1366
- }
1367
-
1368
- .ree-color-swatch-face {
1369
- display: block;
1370
- width: 100%;
1371
- height: 100%;
1372
- border: 1px solid #d2d5d8;
1373
- border-radius: 999px;
1374
- background: #ffffff;
1375
- }
1376
-
1377
- .ree-color-swatch-face.is-empty {
1378
- background:
1379
- linear-gradient(45deg, #e3e3e5 25%, transparent 25%),
1380
- linear-gradient(-45deg, #e3e3e5 25%, transparent 25%),
1381
- linear-gradient(45deg, transparent 75%, #e3e3e5 75%),
1382
- linear-gradient(-45deg, transparent 75%, #e3e3e5 75%);
1383
- background-size: 8px 8px;
1384
- background-position: 0 0, 0 4px, 4px -4px, -4px 0;
1385
- background-color: #ffffff;
1386
- }
1387
-
1388
- .ree-color-native {
1389
- position: absolute;
1390
- inset: 0;
1391
- width: 100%;
1392
- height: 100%;
1393
- opacity: 0;
1394
- cursor: pointer;
1395
- border: 0;
1396
- padding: 0;
1397
- }
1398
-
1399
- .ree-color-chip-label {
1400
- min-width: 0;
1401
- overflow: hidden;
1402
- color: var(--ree-text);
1403
- font-size: 13px;
1404
- line-height: 1.3;
1405
- text-overflow: ellipsis;
1406
- white-space: nowrap;
1407
- }
1408
-
1409
- .ree-reset {
1410
- appearance: none;
1411
- display: inline-flex;
1412
- align-items: center;
1413
- justify-content: center;
1414
- width: 22px;
1415
- height: 22px;
1416
- flex-shrink: 0;
1417
- padding: 0;
1418
- border: 0;
1419
- border-radius: 6px;
1420
- background: transparent;
1421
- color: var(--ree-muted);
1422
- cursor: pointer;
1423
- }
1424
-
1425
- .ree-reset:hover {
1426
- background: var(--ree-panel-secondary);
1427
- color: var(--ree-text);
1428
- }
1429
-
1430
1774
  .ree-field-value {
1431
1775
  font-size: 12px;
1432
1776
  color: var(--ree-muted);
@@ -1456,82 +1800,6 @@
1456
1800
  width: 100%;
1457
1801
  }
1458
1802
 
1459
- .ree-range {
1460
- -webkit-appearance: none;
1461
- appearance: none;
1462
- display: block;
1463
- flex: 1 1 auto;
1464
- width: 100%;
1465
- min-width: 0;
1466
- height: 20px;
1467
- margin: 0;
1468
- background: transparent;
1469
- cursor: pointer;
1470
- }
1471
-
1472
- .ree-range::-webkit-slider-container {
1473
- width: 100%;
1474
- }
1475
-
1476
- .ree-range::-webkit-slider-runnable-track {
1477
- width: 100%;
1478
- height: 4px;
1479
- border: 0;
1480
- border-radius: 999px;
1481
- background: linear-gradient(to right, #303030 0%, #303030 var(--ree-range-progress), #e3e3e5 var(--ree-range-progress), #e3e3e5 100%);
1482
- }
1483
-
1484
- .ree-range::-webkit-slider-thumb {
1485
- appearance: none;
1486
- width: 14px;
1487
- height: 14px;
1488
- margin-top: -5px;
1489
- border: 0;
1490
- border-radius: 50%;
1491
- background: #303030;
1492
- }
1493
-
1494
- .ree-range::-moz-range-track {
1495
- height: 4px;
1496
- border: 0;
1497
- border-radius: 999px;
1498
- background: #e3e3e5;
1499
- }
1500
-
1501
- .ree-range::-moz-range-progress {
1502
- height: 4px;
1503
- border: 0;
1504
- border-radius: 999px;
1505
- background: #303030;
1506
- }
1507
-
1508
- .ree-range::-moz-range-thumb {
1509
- width: 14px;
1510
- height: 14px;
1511
- border: 0;
1512
- border-radius: 50%;
1513
- background: #303030;
1514
- }
1515
-
1516
- .ree-unit-select {
1517
- appearance: none;
1518
- flex-shrink: 0;
1519
- height: 28px;
1520
- border: 1px solid var(--ree-border);
1521
- border-radius: 6px;
1522
- background-color: var(--ree-panel);
1523
- background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='none'%3E%3Cpath d='M4 6.25 8 10.25 12 6.25' stroke='%236d7175' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
1524
- background-repeat: no-repeat;
1525
- background-position: right 4px center;
1526
- background-size: 12px;
1527
- color: var(--ree-text);
1528
- font: inherit;
1529
- font-size: 12px;
1530
- line-height: 1;
1531
- padding: 0 20px 0 8px;
1532
- cursor: pointer;
1533
- }
1534
-
1535
1803
  .ree-align-row {
1536
1804
  display: flex;
1537
1805
  gap: 4px;
@@ -1555,45 +1823,73 @@
1555
1823
  }
1556
1824
 
1557
1825
  .ree-align-btn.is-active {
1558
- border-color: var(--ree-primary);
1559
- color: var(--ree-primary);
1560
- background: var(--ree-primary-soft);
1826
+ border-color: var(--ree-text);
1827
+ color: var(--ree-text);
1828
+ background: var(--ree-panel-secondary);
1561
1829
  }
1562
1830
 
1563
1831
 
1564
1832
  .ree-spacing-control { display: grid; gap: 10px; }
1565
- .ree-spacing-link { display: flex; gap: 6px; align-items: center; font-size: 12px; color: var(--ree-muted); }
1566
- .ree-spacing-link input[type="checkbox"] {
1567
- appearance: none;
1568
- -webkit-appearance: none;
1569
- width: 16px;
1570
- height: 16px;
1833
+ .ree-spacing-link { gap: 6px; font-size: 12px; color: var(--ree-muted); }
1834
+ .ree-spacing-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; }
1835
+
1836
+ /* 原生 modal dialog 进入 top layer,覆盖整个视口并隔离背景交互。 */
1837
+ .ree-rte-link {
1838
+ position: fixed;
1839
+ inset: 0;
1840
+ width: min(440px, calc(100vw - 32px));
1841
+ max-width: none;
1842
+ max-height: calc(100dvh - 32px);
1843
+ margin: auto;
1844
+ padding: 0;
1845
+ overflow: auto;
1846
+ background: var(--ree-panel, #ffffff);
1847
+ border: 1px solid var(--ree-border, #e3e3e5);
1848
+ border-radius: 12px;
1849
+ box-shadow: 0 16px 48px rgba(0, 0, 0, 0.2);
1850
+ color: var(--ree-text, #202223);
1851
+ font: 400 14px/1.5 var(--ree-font, Arial, sans-serif);
1852
+ visibility: visible;
1853
+ }
1854
+
1855
+ .ree-rte-link::backdrop {
1856
+ background: rgba(0, 0, 0, 0.6);
1857
+ -webkit-backdrop-filter: blur(4px);
1858
+ backdrop-filter: blur(4px);
1859
+ }
1860
+
1861
+ .ree-rte-link-title {
1571
1862
  margin: 0;
1572
- border: 1px solid #1a1a1a;
1573
- border-radius: 3px;
1574
- background: #ffffff;
1863
+ padding: 20px 24px;
1864
+ border-bottom: 1px solid var(--ree-border);
1865
+ font-size: 18px;
1866
+ font-weight: 600;
1867
+ line-height: 1.4;
1868
+ }
1869
+
1870
+ .ree-rte-link-fields {
1575
1871
  display: grid;
1576
- place-content: center;
1577
- cursor: pointer;
1578
- flex-shrink: 0;
1872
+ gap: 20px;
1873
+ padding: 24px;
1579
1874
  }
1580
- .ree-spacing-link input[type="checkbox"]:checked {
1581
- background: #1a1a1a;
1582
- border-color: #1a1a1a;
1875
+
1876
+ .ree-rte-link-actions {
1877
+ display: flex;
1878
+ justify-content: flex-end;
1879
+ gap: 8px;
1880
+ padding: 16px 24px;
1881
+ border-top: 1px solid var(--ree-border);
1583
1882
  }
1584
- .ree-spacing-link input[type="checkbox"]:checked::after {
1585
- content: "";
1586
- width: 8px;
1587
- height: 4px;
1588
- border: solid #ffffff;
1589
- border-width: 0 0 1.5px 1.5px;
1590
- transform: rotate(-45deg) translateY(-1px);
1883
+
1884
+ .ree-rte-link-actions .ree-btn {
1885
+ min-width: 80px;
1591
1886
  }
1592
- .ree-spacing-link input[type="checkbox"]:focus-visible {
1593
- outline: 2px solid #1a1a1a;
1594
- outline-offset: 2px;
1887
+
1888
+ .ree-rte-link-error {
1889
+ margin: -12px 0 0;
1890
+ color: var(--ree-danger);
1891
+ font-size: 12px;
1595
1892
  }
1596
- .ree-spacing-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; }
1597
1893
 
1598
1894
  /* ---------- 拖拽浮层 ---------- */
1599
1895
 
@@ -1608,12 +1904,3 @@
1608
1904
  cursor: grabbing;
1609
1905
  font-weight: 500;
1610
1906
  }
1611
-
1612
- .ree-preview-frame {
1613
- height: 100%;
1614
- min-height: 520px;
1615
- flex-shrink: 0;
1616
- border: none;
1617
- background: #ffffff;
1618
- box-shadow: var(--ree-shadow-md);
1619
- }