stilo-editor 0.0.0-stage → 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.
Files changed (100) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +226 -2
  3. package/dist/characters--8h5uTeF.js +854 -0
  4. package/dist/content.css +398 -0
  5. package/dist/core/drop.d.ts +6 -0
  6. package/dist/core/editor.d.ts +120 -0
  7. package/dist/core/errors.d.ts +6 -0
  8. package/dist/core/events.d.ts +19 -0
  9. package/dist/core/extension-manager.d.ts +57 -0
  10. package/dist/core/extension.d.ts +48 -0
  11. package/dist/core/helpers/active.d.ts +33 -0
  12. package/dist/core/helpers/block-style.d.ts +25 -0
  13. package/dist/core/helpers/input-rules.d.ts +28 -0
  14. package/dist/core/helpers/lists.d.ts +20 -0
  15. package/dist/core/helpers/marks.d.ts +52 -0
  16. package/dist/core/helpers/nodes.d.ts +26 -0
  17. package/dist/core/helpers/parse-rules.d.ts +8 -0
  18. package/dist/core/helpers/word-count.d.ts +14 -0
  19. package/dist/core/html/css.d.ts +106 -0
  20. package/dist/core/html/parse.d.ts +7 -0
  21. package/dist/core/html/paste/base-styles.d.ts +7 -0
  22. package/dist/core/html/paste/google-docs.d.ts +7 -0
  23. package/dist/core/html/paste/index.d.ts +9 -0
  24. package/dist/core/html/paste/table-widths.d.ts +7 -0
  25. package/dist/core/html/paste/word.d.ts +8 -0
  26. package/dist/core/html/sanitize.d.ts +49 -0
  27. package/dist/core/html/serialize.d.ts +31 -0
  28. package/dist/core/types.d.ts +107 -0
  29. package/dist/extensions/blockquote/index.d.ts +15 -0
  30. package/dist/extensions/bold/index.d.ts +17 -0
  31. package/dist/extensions/bullet-list/index.d.ts +9 -0
  32. package/dist/extensions/clear-formatting/index.d.ts +12 -0
  33. package/dist/extensions/code/index.d.ts +15 -0
  34. package/dist/extensions/code-block/index.d.ts +24 -0
  35. package/dist/extensions/default-extensions/index.d.ts +57 -0
  36. package/dist/extensions/document/index.d.ts +17 -0
  37. package/dist/extensions/drop-cursor/index.d.ts +15 -0
  38. package/dist/extensions/gap-cursor/index.d.ts +6 -0
  39. package/dist/extensions/hard-break/index.d.ts +11 -0
  40. package/dist/extensions/heading/index.d.ts +25 -0
  41. package/dist/extensions/highlight/index.d.ts +24 -0
  42. package/dist/extensions/history/index.d.ts +21 -0
  43. package/dist/extensions/horizontal-rule/index.d.ts +11 -0
  44. package/dist/extensions/image/image-view.d.ts +27 -0
  45. package/dist/extensions/image/index.d.ts +29 -0
  46. package/dist/extensions/index.d.ts +36 -0
  47. package/dist/extensions/italic/index.d.ts +16 -0
  48. package/dist/extensions/line-height/index.d.ts +18 -0
  49. package/dist/extensions/link/index.d.ts +23 -0
  50. package/dist/extensions/list-item/index.d.ts +16 -0
  51. package/dist/extensions/move-block/index.d.ts +17 -0
  52. package/dist/extensions/ordered-list/index.d.ts +12 -0
  53. package/dist/extensions/paragraph/index.d.ts +14 -0
  54. package/dist/extensions/placeholder/index.d.ts +13 -0
  55. package/dist/extensions/search/index.d.ts +55 -0
  56. package/dist/extensions/strike/index.d.ts +16 -0
  57. package/dist/extensions/subscript/index.d.ts +16 -0
  58. package/dist/extensions/superscript/index.d.ts +17 -0
  59. package/dist/extensions/table/index.d.ts +70 -0
  60. package/dist/extensions/task-item/index.d.ts +24 -0
  61. package/dist/extensions/task-item/task-item-view.d.ts +24 -0
  62. package/dist/extensions/task-list/index.d.ts +11 -0
  63. package/dist/extensions/text/index.d.ts +12 -0
  64. package/dist/extensions/text-align/index.d.ts +18 -0
  65. package/dist/extensions/text-case/index.d.ts +14 -0
  66. package/dist/extensions/text-style/font-size.d.ts +21 -0
  67. package/dist/extensions/text-style/index.d.ts +30 -0
  68. package/dist/extensions/underline/index.d.ts +15 -0
  69. package/dist/index.d.ts +14 -0
  70. package/dist/index.js +1 -0
  71. package/dist/src-CV6pgfTS.js +2662 -0
  72. package/dist/style.css +1395 -0
  73. package/dist/ui/components/character-picker.d.ts +22 -0
  74. package/dist/ui/components/characters.d.ts +10 -0
  75. package/dist/ui/components/color-button.d.ts +23 -0
  76. package/dist/ui/components/dropdown.d.ts +34 -0
  77. package/dist/ui/components/find-bar.d.ts +24 -0
  78. package/dist/ui/components/font-size-input.d.ts +21 -0
  79. package/dist/ui/components/icon-menu.d.ts +20 -0
  80. package/dist/ui/components/icon.d.ts +3 -0
  81. package/dist/ui/components/link-bubble.d.ts +19 -0
  82. package/dist/ui/components/link-popover.d.ts +20 -0
  83. package/dist/ui/components/popover.d.ts +27 -0
  84. package/dist/ui/components/shortcut.d.ts +11 -0
  85. package/dist/ui/components/status-bar.d.ts +19 -0
  86. package/dist/ui/components/table-actions.d.ts +25 -0
  87. package/dist/ui/components/table-handles.d.ts +16 -0
  88. package/dist/ui/components/table-menu.d.ts +21 -0
  89. package/dist/ui/i18n/en.d.ts +3 -0
  90. package/dist/ui/i18n/it.d.ts +3 -0
  91. package/dist/ui/i18n/types.d.ts +4 -0
  92. package/dist/ui/index.d.ts +23 -0
  93. package/dist/ui/toolbar/fonts.d.ts +8 -0
  94. package/dist/ui/toolbar/items.d.ts +33 -0
  95. package/dist/ui/toolbar/palette.d.ts +6 -0
  96. package/dist/ui/toolbar/toolbar.d.ts +28 -0
  97. package/dist/ui/toolbar/types.d.ts +150 -0
  98. package/dist/ui.css +996 -0
  99. package/dist/ui.js +2350 -0
  100. package/package.json +96 -4
package/dist/ui.css ADDED
@@ -0,0 +1,996 @@
1
+ /* Stilo default UI styles. */
2
+
3
+ /*
4
+ * Default values of the custom properties (docs/UI.md §7). `:where()` has no specificity, so any
5
+ * rule of the host page that sets them wins, whatever the order of the stylesheets.
6
+ */
7
+ :where(:root) {
8
+ --stilo-font-family: system-ui, sans-serif;
9
+ --stilo-font-size: 14px;
10
+
11
+ --stilo-color-text: #1f2328;
12
+ --stilo-color-muted: #59636e;
13
+ --stilo-color-bg: #ffffff;
14
+ --stilo-color-toolbar-bg: #f9fbfd;
15
+ --stilo-color-border: #d1d9e0;
16
+ --stilo-color-separator: #e4e8ec;
17
+ --stilo-color-hover: #eef1f4;
18
+ --stilo-color-hover-group: #f5f7f9;
19
+ --stilo-color-active: #dde4ee;
20
+ --stilo-color-focus: #0969da;
21
+ --stilo-color-error: #d1242f;
22
+
23
+ --stilo-radius: 6px;
24
+
25
+ --stilo-toolbar-padding-x: 2px;
26
+ --stilo-toolbar-padding-y: 4px;
27
+ --stilo-toolbar-gap: 2px;
28
+ --stilo-toolbar-group-gap: 4px;
29
+ --stilo-toolbar-separator-height: 18px;
30
+ --stilo-toolbar-sticky-top: 0;
31
+ --stilo-toolbar-shadow: 0 2px 6px rgb(0 0 0 / 0.08);
32
+ --stilo-z-toolbar: 1001;
33
+
34
+ --stilo-button-size: 30px;
35
+ --stilo-icon-size: 18px;
36
+
37
+ --stilo-popover-shadow: 0 8px 24px rgb(0 0 0 / 0.12);
38
+ --stilo-z-popover: 1000;
39
+
40
+ --stilo-menu-h1-size: 1.5em;
41
+ --stilo-menu-h2-size: 1.3em;
42
+ --stilo-menu-h3-size: 1.15em;
43
+ --stilo-menu-h4-size: 1em;
44
+ --stilo-menu-h5-size: 1em;
45
+ --stilo-menu-h6-size: 1em;
46
+ }
47
+
48
+ /* Toolbar */
49
+ .stilo-toolbar {
50
+ display: flex;
51
+ flex-wrap: wrap;
52
+ gap: var(--stilo-toolbar-group-gap);
53
+ padding: var(--stilo-toolbar-padding-y) var(--stilo-toolbar-padding-x);
54
+ background: var(--stilo-color-toolbar-bg);
55
+ }
56
+
57
+ /*
58
+ * The toolbar and its sticky container have a background: their top corners follow the element
59
+ * that holds them, so that a rounded editor box keeps its corners (no `overflow` on the host,
60
+ * which would cut the popovers).
61
+ */
62
+ .stilo-toolbar-host,
63
+ .stilo-toolbar {
64
+ border-top-left-radius: inherit;
65
+ border-top-right-radius: inherit;
66
+ }
67
+
68
+ /* Sticky toolbar container (option `sticky`) */
69
+ .stilo-toolbar-host {
70
+ position: sticky;
71
+ top: var(--stilo-toolbar-sticky-top);
72
+ z-index: var(--stilo-z-toolbar);
73
+ background: var(--stilo-color-bg);
74
+ container-type: scroll-state;
75
+ }
76
+
77
+ /*
78
+ * A shadow while the toolbar is stuck at the top of the scrolling page. Pure CSS: browsers
79
+ * without scroll-state container queries ignore it and show the toolbar without shadow.
80
+ */
81
+ @container scroll-state(stuck: top) {
82
+ .stilo-toolbar {
83
+ box-shadow: var(--stilo-toolbar-shadow);
84
+ }
85
+ }
86
+
87
+ /* Group */
88
+ .stilo-toolbar__group {
89
+ display: flex;
90
+ gap: var(--stilo-toolbar-gap);
91
+ }
92
+
93
+ /* Separator: a short line, vertically centered, before every group after the first */
94
+ .stilo-toolbar__group:not(:first-child) {
95
+ position: relative;
96
+ padding-left: var(--stilo-toolbar-group-gap);
97
+ }
98
+
99
+ .stilo-toolbar__group:not(:first-child)::before {
100
+ content: "";
101
+ position: absolute;
102
+ top: 50%;
103
+ left: 0;
104
+ width: 1px;
105
+ height: var(--stilo-toolbar-separator-height);
106
+ background: var(--stilo-color-separator);
107
+ transform: translateY(-50%);
108
+ }
109
+
110
+ /* Button */
111
+ .stilo-toolbar__button {
112
+ display: flex;
113
+ align-items: center;
114
+ justify-content: center;
115
+ width: var(--stilo-button-size);
116
+ min-width: var(--stilo-button-size);
117
+ height: var(--stilo-button-size);
118
+ border: none;
119
+ border-radius: var(--stilo-radius);
120
+ background: transparent;
121
+ color: var(--stilo-color-text);
122
+ cursor: pointer;
123
+ font-family: var(--stilo-font-family);
124
+ font-size: var(--stilo-font-size);
125
+ padding: 0;
126
+ margin: 0;
127
+ transition: background-color 0.15s;
128
+ }
129
+
130
+ .stilo-toolbar__button:hover {
131
+ background: var(--stilo-color-hover);
132
+ }
133
+
134
+ .stilo-toolbar__button:focus-visible {
135
+ outline: 2px solid var(--stilo-color-focus);
136
+ outline-offset: 2px;
137
+ }
138
+
139
+ .stilo-toolbar__button.stilo-toolbar__button--active {
140
+ background: var(--stilo-color-active);
141
+ }
142
+
143
+ /* The find button while its bar is open (T-043) */
144
+ .stilo-toolbar__button[data-item="find"][aria-expanded="true"] {
145
+ background: var(--stilo-color-active);
146
+ }
147
+
148
+ .stilo-toolbar__button[aria-disabled="true"] {
149
+ opacity: 0.4;
150
+ cursor: default;
151
+ }
152
+
153
+ .stilo-toolbar__button[aria-disabled="true"]:hover {
154
+ background: transparent;
155
+ }
156
+
157
+ /* Icon */
158
+ .stilo-icon {
159
+ width: var(--stilo-icon-size);
160
+ height: var(--stilo-icon-size);
161
+ color: var(--stilo-color-text);
162
+ }
163
+
164
+ /* Popover */
165
+ .stilo-popover-host {
166
+ position: relative;
167
+ }
168
+
169
+ .stilo-popover {
170
+ position: absolute;
171
+ top: 0;
172
+ left: 0;
173
+ width: max-content;
174
+ background: var(--stilo-color-bg);
175
+ border: 1px solid var(--stilo-color-border);
176
+ border-radius: var(--stilo-radius);
177
+ box-shadow: var(--stilo-popover-shadow);
178
+ z-index: var(--stilo-z-popover);
179
+ padding: 4px;
180
+ }
181
+
182
+ /* A component class with its own `display` must not show a closed popover. */
183
+ .stilo-popover[hidden] {
184
+ display: none;
185
+ }
186
+
187
+ /* Dropdown */
188
+ .stilo-dropdown__trigger {
189
+ width: auto;
190
+ min-width: 120px;
191
+ justify-content: space-between;
192
+ gap: 6px;
193
+ padding: 0 8px;
194
+ }
195
+
196
+ .stilo-dropdown__trigger[data-item="fontFamily"] {
197
+ width: 120px;
198
+ }
199
+
200
+ /* A long value is truncated, the chevron keeps its size */
201
+ .stilo-dropdown__trigger .stilo-icon {
202
+ flex-shrink: 0;
203
+ }
204
+
205
+ .stilo-dropdown__value {
206
+ overflow: hidden;
207
+ text-overflow: ellipsis;
208
+ white-space: nowrap;
209
+ font-weight: 600;
210
+ }
211
+
212
+ .stilo-dropdown__menu {
213
+ min-width: 160px;
214
+ }
215
+
216
+ .stilo-dropdown__option {
217
+ display: flex;
218
+ align-items: center;
219
+ gap: 8px;
220
+ padding: 6px 8px;
221
+ border-radius: var(--stilo-radius);
222
+ cursor: pointer;
223
+ font-family: var(--stilo-font-family);
224
+ font-size: var(--stilo-font-size);
225
+ color: var(--stilo-color-text);
226
+ }
227
+
228
+ .stilo-dropdown__option:hover,
229
+ .stilo-dropdown__option:focus-visible {
230
+ background: var(--stilo-color-hover);
231
+ }
232
+
233
+ .stilo-dropdown__option:focus-visible {
234
+ outline: 2px solid var(--stilo-color-focus);
235
+ outline-offset: -2px;
236
+ }
237
+
238
+ .stilo-dropdown__option[aria-checked="true"] {
239
+ background: var(--stilo-color-active);
240
+ }
241
+
242
+ .stilo-dropdown__option[aria-disabled="true"] {
243
+ opacity: 0.4;
244
+ cursor: default;
245
+ }
246
+
247
+ .stilo-dropdown__option[aria-disabled="true"]:hover {
248
+ background: transparent;
249
+ }
250
+
251
+ .stilo-dropdown__label {
252
+ flex: 1;
253
+ }
254
+
255
+ .stilo-dropdown__shortcut {
256
+ font-size: 0.85em;
257
+ color: var(--stilo-color-muted);
258
+ }
259
+
260
+ /* Heading preview */
261
+ .stilo-dropdown__option--h1 .stilo-dropdown__label {
262
+ font-size: var(--stilo-menu-h1-size);
263
+ font-weight: 600;
264
+ }
265
+
266
+ .stilo-dropdown__option--h2 .stilo-dropdown__label {
267
+ font-size: var(--stilo-menu-h2-size);
268
+ font-weight: 600;
269
+ }
270
+
271
+ .stilo-dropdown__option--h3 .stilo-dropdown__label {
272
+ font-size: var(--stilo-menu-h3-size);
273
+ font-weight: 600;
274
+ }
275
+
276
+ .stilo-dropdown__option--h4 .stilo-dropdown__label {
277
+ font-size: var(--stilo-menu-h4-size);
278
+ font-weight: 600;
279
+ }
280
+
281
+ .stilo-dropdown__option--h5 .stilo-dropdown__label {
282
+ font-size: var(--stilo-menu-h5-size);
283
+ font-weight: 600;
284
+ }
285
+
286
+ .stilo-dropdown__option--h6 .stilo-dropdown__label {
287
+ font-size: var(--stilo-menu-h6-size);
288
+ font-weight: 600;
289
+ }
290
+
291
+ /* Font size control: − field + */
292
+ .stilo-font-size {
293
+ display: inline-flex;
294
+ align-items: center;
295
+ gap: var(--stilo-toolbar-gap);
296
+ }
297
+
298
+ .stilo-font-size__input {
299
+ box-sizing: border-box;
300
+ width: 2.5em;
301
+ height: calc(var(--stilo-button-size) - 4px);
302
+ padding: 0 4px;
303
+ border: 1px solid var(--stilo-color-border);
304
+ border-radius: var(--stilo-radius);
305
+ background: var(--stilo-color-bg);
306
+ color: var(--stilo-color-text);
307
+ font-family: var(--stilo-font-family);
308
+ font-size: var(--stilo-font-size);
309
+ text-align: center;
310
+ font-weight: 600;
311
+ }
312
+
313
+ .stilo-font-size__input:focus-visible {
314
+ outline: 2px solid var(--stilo-color-focus);
315
+ outline-offset: -1px;
316
+ }
317
+
318
+ .stilo-font-size__input[aria-invalid="true"] {
319
+ border-color: var(--stilo-color-error);
320
+ }
321
+
322
+ .stilo-font-size__input[aria-disabled="true"] {
323
+ opacity: 0.4;
324
+ }
325
+
326
+ .stilo-font-size__list {
327
+ min-width: 4.5em;
328
+ max-height: 280px;
329
+ overflow-y: auto;
330
+ }
331
+
332
+ .stilo-font-size__option {
333
+ padding: 4px 12px;
334
+ border-radius: var(--stilo-radius);
335
+ cursor: pointer;
336
+ font-family: var(--stilo-font-family);
337
+ font-size: var(--stilo-font-size);
338
+ color: var(--stilo-color-text);
339
+ text-align: center;
340
+ }
341
+
342
+ .stilo-font-size__option:hover,
343
+ .stilo-font-size__option--active {
344
+ background: var(--stilo-color-hover);
345
+ }
346
+
347
+ .stilo-font-size__option[aria-selected="true"] {
348
+ background: var(--stilo-color-active);
349
+ }
350
+
351
+ /* Icon menu (text alignment): the options in a row. An icon dropdown (line spacing) has the same
352
+ trigger. */
353
+ .stilo-icon-menu__trigger,
354
+ .stilo-dropdown__trigger--icon {
355
+ width: auto;
356
+ min-width: var(--stilo-button-size);
357
+ gap: 2px;
358
+ padding: 0 4px;
359
+ }
360
+
361
+ .stilo-icon-menu {
362
+ display: flex;
363
+ gap: var(--stilo-toolbar-gap);
364
+ }
365
+
366
+ .stilo-icon-menu__trigger .stilo-icon:last-child,
367
+ .stilo-dropdown__trigger--icon .stilo-icon:last-child {
368
+ width: 12px;
369
+ height: 12px;
370
+ }
371
+
372
+ /* Link popover */
373
+ .stilo-link-popover__form {
374
+ display: flex;
375
+ flex-wrap: wrap;
376
+ align-items: center;
377
+ gap: 8px;
378
+ width: 320px;
379
+ padding: 4px;
380
+ font-family: var(--stilo-font-family);
381
+ font-size: var(--stilo-font-size);
382
+ color: var(--stilo-color-text);
383
+ }
384
+
385
+ .stilo-link-popover__url {
386
+ flex: 1 1 100%;
387
+ box-sizing: border-box;
388
+ padding: 6px 8px;
389
+ border: 1px solid var(--stilo-color-border);
390
+ border-radius: var(--stilo-radius);
391
+ background: var(--stilo-color-bg);
392
+ color: inherit;
393
+ font: inherit;
394
+ }
395
+
396
+ .stilo-link-popover__url:focus-visible {
397
+ outline: 2px solid var(--stilo-color-focus);
398
+ outline-offset: -1px;
399
+ }
400
+
401
+ .stilo-link-popover__url[aria-invalid="true"] {
402
+ border-color: var(--stilo-color-error);
403
+ }
404
+
405
+ .stilo-link-popover__new-tab {
406
+ display: flex;
407
+ flex: 1;
408
+ align-items: center;
409
+ gap: 6px;
410
+ cursor: pointer;
411
+ }
412
+
413
+ .stilo-link-popover__actions {
414
+ display: flex;
415
+ gap: 4px;
416
+ }
417
+
418
+ .stilo-link-popover__button {
419
+ padding: 4px 10px;
420
+ border: 1px solid var(--stilo-color-border);
421
+ border-radius: var(--stilo-radius);
422
+ background: var(--stilo-color-bg);
423
+ color: inherit;
424
+ cursor: pointer;
425
+ font: inherit;
426
+ }
427
+
428
+ .stilo-link-popover__button:hover {
429
+ background: var(--stilo-color-hover);
430
+ }
431
+
432
+ .stilo-link-popover__button:focus-visible {
433
+ outline: 2px solid var(--stilo-color-focus);
434
+ outline-offset: 1px;
435
+ }
436
+
437
+ .stilo-link-popover__button--primary,
438
+ .stilo-link-popover__button--primary:hover {
439
+ border-color: var(--stilo-color-focus);
440
+ background: var(--stilo-color-focus);
441
+ color: #ffffff;
442
+ }
443
+
444
+ /* Link bubble: small and unobtrusive */
445
+ .stilo-link-bubble {
446
+ display: flex;
447
+ gap: 1px;
448
+ padding: 2px;
449
+ }
450
+
451
+ .stilo-link-bubble__button {
452
+ display: flex;
453
+ align-items: center;
454
+ justify-content: center;
455
+ width: 24px;
456
+ height: 24px;
457
+ padding: 0;
458
+ border: none;
459
+ border-radius: var(--stilo-radius);
460
+ background: transparent;
461
+ color: var(--stilo-color-text);
462
+ cursor: pointer;
463
+ }
464
+
465
+ .stilo-link-bubble__button:hover {
466
+ background: var(--stilo-color-hover);
467
+ }
468
+
469
+ .stilo-link-bubble__button .stilo-icon {
470
+ width: 16px;
471
+ height: 16px;
472
+ }
473
+
474
+ /* Character picker: 10 columns (COLUMNS in character-picker.ts) */
475
+ .stilo-char-picker {
476
+ display: flex;
477
+ flex-direction: column;
478
+ gap: 4px;
479
+ font-family: var(--stilo-font-family);
480
+ font-size: var(--stilo-font-size);
481
+ color: var(--stilo-color-text);
482
+ }
483
+
484
+ .stilo-char-picker__search {
485
+ padding: 6px 8px;
486
+ border: 1px solid var(--stilo-color-border);
487
+ border-radius: var(--stilo-radius);
488
+ font: inherit;
489
+ }
490
+
491
+ .stilo-char-picker__search:focus-visible,
492
+ .stilo-char-picker__tab:focus-visible,
493
+ .stilo-char-picker__char:focus-visible {
494
+ outline: 2px solid var(--stilo-color-focus);
495
+ outline-offset: -2px;
496
+ }
497
+
498
+ .stilo-char-picker__tabs {
499
+ display: flex;
500
+ gap: 4px;
501
+ border-bottom: 1px solid var(--stilo-color-border);
502
+ }
503
+
504
+ .stilo-char-picker__tabs[hidden] {
505
+ display: none;
506
+ }
507
+
508
+ .stilo-char-picker__tab {
509
+ padding: 6px 10px;
510
+ border: none;
511
+ border-bottom: 2px solid transparent;
512
+ background: transparent;
513
+ color: var(--stilo-color-muted);
514
+ font: inherit;
515
+ cursor: pointer;
516
+ }
517
+
518
+ .stilo-char-picker__tab[aria-selected="true"] {
519
+ border-bottom-color: var(--stilo-color-focus);
520
+ color: var(--stilo-color-text);
521
+ }
522
+
523
+ .stilo-char-picker__panel {
524
+ max-height: 280px;
525
+ overflow-y: auto;
526
+ }
527
+
528
+ .stilo-char-picker__heading {
529
+ margin: 8px 0 4px;
530
+ color: var(--stilo-color-muted);
531
+ font-size: 0.85em;
532
+ }
533
+
534
+ .stilo-char-picker__grid {
535
+ display: grid;
536
+ grid-template-columns: repeat(10, 32px);
537
+ gap: 2px;
538
+ }
539
+
540
+ .stilo-char-picker__char {
541
+ width: 32px;
542
+ height: 32px;
543
+ padding: 0;
544
+ border: none;
545
+ border-radius: var(--stilo-radius);
546
+ background: transparent;
547
+ color: inherit;
548
+ font-size: 18px;
549
+ line-height: 1;
550
+ cursor: pointer;
551
+ }
552
+
553
+ .stilo-char-picker__char:hover {
554
+ background: var(--stilo-color-hover);
555
+ }
556
+
557
+ .stilo-char-picker__empty {
558
+ margin: 8px 0;
559
+ color: var(--stilo-color-muted);
560
+ }
561
+
562
+ /* Table menu (T-045): insert grid of 10 columns (GRID_COLUMNS in table-menu.ts), operations */
563
+ .stilo-table-menu {
564
+ font-family: var(--stilo-font-family);
565
+ font-size: var(--stilo-font-size);
566
+ color: var(--stilo-color-text);
567
+ }
568
+
569
+ .stilo-table-menu__picker {
570
+ display: flex;
571
+ flex-direction: column;
572
+ gap: 6px;
573
+ padding: 4px;
574
+ }
575
+
576
+ .stilo-table-menu__picker[hidden],
577
+ .stilo-table-menu__actions[hidden] {
578
+ display: none;
579
+ }
580
+
581
+ .stilo-table-menu__grid {
582
+ display: grid;
583
+ grid-template-columns: repeat(10, 18px);
584
+ gap: 3px;
585
+ }
586
+
587
+ .stilo-table-menu__cell {
588
+ width: 18px;
589
+ height: 18px;
590
+ padding: 0;
591
+ border: 1px solid var(--stilo-color-border);
592
+ border-radius: 3px;
593
+ background: var(--stilo-color-bg);
594
+ cursor: pointer;
595
+ }
596
+
597
+ .stilo-table-menu__cell--active {
598
+ border-color: var(--stilo-color-focus);
599
+ background: var(--stilo-color-active);
600
+ }
601
+
602
+ .stilo-table-menu__cell:focus-visible {
603
+ outline: 2px solid var(--stilo-color-focus);
604
+ outline-offset: 1px;
605
+ }
606
+
607
+ .stilo-table-menu__size {
608
+ text-align: center;
609
+ color: var(--stilo-color-muted);
610
+ }
611
+
612
+ .stilo-table-menu__header {
613
+ display: flex;
614
+ align-items: center;
615
+ gap: 6px;
616
+ cursor: pointer;
617
+ }
618
+
619
+ .stilo-table-menu__actions {
620
+ min-width: 200px;
621
+ }
622
+
623
+ .stilo-table-menu__actions .stilo-dropdown__option[aria-checked] {
624
+ background: transparent;
625
+ }
626
+
627
+ .stilo-table-menu__actions .stilo-dropdown__option[aria-checked]:hover,
628
+ .stilo-table-menu__actions .stilo-dropdown__option[aria-checked]:focus-visible {
629
+ background: var(--stilo-color-hover);
630
+ }
631
+
632
+ .stilo-table-menu__actions .stilo-dropdown__option[aria-checked]::after {
633
+ content: "✓";
634
+ margin-left: auto;
635
+ visibility: hidden;
636
+ }
637
+
638
+ .stilo-table-menu__actions .stilo-dropdown__option[aria-checked="true"]::after {
639
+ visibility: visible;
640
+ }
641
+
642
+ /* Table handles (T-049): row, column and corner, over the editor */
643
+ .stilo-table-handle {
644
+ position: absolute;
645
+ top: 0;
646
+ left: 0;
647
+ z-index: var(--stilo-z-popover);
648
+ display: flex;
649
+ align-items: center;
650
+ justify-content: center;
651
+ width: 18px;
652
+ height: 18px;
653
+ padding: 0;
654
+ border: 1px solid var(--stilo-color-border);
655
+ border-radius: var(--stilo-radius);
656
+ background: var(--stilo-color-bg);
657
+ color: var(--stilo-color-muted);
658
+ cursor: pointer;
659
+ }
660
+
661
+ .stilo-table-handle[hidden] {
662
+ display: none;
663
+ }
664
+
665
+ .stilo-table-handle:hover,
666
+ .stilo-table-handle[aria-expanded="true"] {
667
+ border-color: var(--stilo-color-focus);
668
+ color: var(--stilo-color-focus);
669
+ }
670
+
671
+ .stilo-table-handle .stilo-icon {
672
+ width: 14px;
673
+ height: 14px;
674
+ }
675
+
676
+ .stilo-table-handle-menu {
677
+ font-family: var(--stilo-font-family);
678
+ font-size: var(--stilo-font-size);
679
+ color: var(--stilo-color-text);
680
+ }
681
+
682
+ .stilo-table-menu__separator {
683
+ height: 1px;
684
+ margin: 4px 0;
685
+ background: var(--stilo-color-separator);
686
+ }
687
+
688
+ /* Color split button (T-026): the main part shows the last used color under its icon */
689
+ .stilo-split {
690
+ display: flex;
691
+ }
692
+
693
+ /* Group hover: hovering one part lightly highlights both; the hovered part stays darker */
694
+ .stilo-split:hover
695
+ .stilo-toolbar__button:not(.stilo-toolbar__button--active, [aria-disabled="true"]) {
696
+ background: var(--stilo-color-hover-group);
697
+ }
698
+
699
+ .stilo-split
700
+ .stilo-toolbar__button:not(.stilo-toolbar__button--active, [aria-disabled="true"]):hover {
701
+ background: var(--stilo-color-hover);
702
+ }
703
+
704
+ .stilo-toolbar__button.stilo-split__main {
705
+ flex-direction: column;
706
+ gap: 1px;
707
+ border-top-right-radius: 0;
708
+ border-bottom-right-radius: 0;
709
+ }
710
+
711
+ .stilo-split__main .stilo-icon {
712
+ width: 16px;
713
+ height: 16px;
714
+ }
715
+
716
+ .stilo-split__color {
717
+ width: 16px;
718
+ height: 4px;
719
+ border-radius: 1px;
720
+ box-shadow: inset 0 0 0 1px rgb(0 0 0 / 0.15);
721
+ }
722
+
723
+ .stilo-toolbar__button.stilo-split__arrow {
724
+ width: 20px;
725
+ min-width: 20px;
726
+ border-top-left-radius: 0;
727
+ border-bottom-left-radius: 0;
728
+ }
729
+
730
+ .stilo-split__arrow .stilo-icon {
731
+ width: 12px;
732
+ height: 12px;
733
+ }
734
+
735
+ /* Color picker: 8 columns (COLUMNS in color-button.ts) */
736
+ .stilo-color-picker {
737
+ display: flex;
738
+ flex-direction: column;
739
+ gap: 6px;
740
+ padding: 4px;
741
+ font-family: var(--stilo-font-family);
742
+ font-size: var(--stilo-font-size);
743
+ color: var(--stilo-color-text);
744
+ }
745
+
746
+ .stilo-color-picker__actions {
747
+ display: flex;
748
+ align-items: center;
749
+ gap: 6px;
750
+ }
751
+
752
+ .stilo-color-picker__none,
753
+ .stilo-color-picker__default {
754
+ flex: 1;
755
+ padding: 4px 8px;
756
+ border: none;
757
+ border-radius: var(--stilo-radius);
758
+ background: transparent;
759
+ color: inherit;
760
+ font: inherit;
761
+ text-align: center;
762
+ cursor: pointer;
763
+ }
764
+
765
+ .stilo-color-picker__none:hover,
766
+ .stilo-color-picker__default:hover {
767
+ background: var(--stilo-color-hover);
768
+ }
769
+
770
+ .stilo-color-picker__default[aria-pressed="true"] {
771
+ background: var(--stilo-color-active);
772
+ }
773
+
774
+ .stilo-color-picker__default mark {
775
+ padding: 0 4px;
776
+ border-radius: 2px;
777
+ }
778
+
779
+ .stilo-color-picker__separator {
780
+ width: 1px;
781
+ height: 18px;
782
+ background: var(--stilo-color-separator);
783
+ }
784
+
785
+ .stilo-color-picker__grid {
786
+ display: grid;
787
+ grid-template-columns: repeat(8, 22px);
788
+ gap: 4px;
789
+ }
790
+
791
+ .stilo-color-picker__swatch {
792
+ width: 22px;
793
+ height: 22px;
794
+ padding: 0;
795
+ border: none;
796
+ border-radius: 4px;
797
+ box-shadow: inset 0 0 0 1px rgb(0 0 0 / 0.15);
798
+ cursor: pointer;
799
+ }
800
+
801
+ .stilo-color-picker__swatch:hover {
802
+ transform: scale(1.15);
803
+ }
804
+
805
+ .stilo-color-picker__swatch[aria-pressed="true"] {
806
+ outline: 2px solid var(--stilo-color-text);
807
+ outline-offset: 1px;
808
+ }
809
+
810
+ .stilo-color-picker__none:focus-visible,
811
+ .stilo-color-picker__default:focus-visible,
812
+ .stilo-color-picker__swatch:focus-visible,
813
+ .stilo-color-picker__value:focus-visible,
814
+ .stilo-color-picker__native:focus-visible,
815
+ .stilo-color-picker__apply:focus-visible {
816
+ outline: 2px solid var(--stilo-color-focus);
817
+ outline-offset: 1px;
818
+ }
819
+
820
+ .stilo-color-picker__custom {
821
+ display: flex;
822
+ gap: 4px;
823
+ align-items: center;
824
+ margin: 0;
825
+ }
826
+
827
+ .stilo-color-picker__native {
828
+ width: 32px;
829
+ height: 28px;
830
+ padding: 0;
831
+ border: 1px solid var(--stilo-color-border);
832
+ border-radius: var(--stilo-radius);
833
+ background: var(--stilo-color-bg);
834
+ cursor: pointer;
835
+ }
836
+
837
+ .stilo-color-picker__value {
838
+ flex: 1;
839
+ min-width: 0;
840
+ padding: 4px 8px;
841
+ border: 1px solid var(--stilo-color-border);
842
+ border-radius: var(--stilo-radius);
843
+ font: inherit;
844
+ }
845
+
846
+ .stilo-color-picker__value[aria-invalid="true"] {
847
+ border-color: var(--stilo-color-error);
848
+ }
849
+
850
+ .stilo-color-picker__apply {
851
+ padding: 4px 10px;
852
+ border: 1px solid var(--stilo-color-focus);
853
+ border-radius: var(--stilo-radius);
854
+ background: var(--stilo-color-focus);
855
+ color: #ffffff;
856
+ font: inherit;
857
+ cursor: pointer;
858
+ }
859
+
860
+ /*
861
+ * Find bar (T-043): a floating panel at the top right, just under the toolbar, over the content
862
+ * (the content does not move). It lives in the toolbar container, so it stays at the top with a
863
+ * sticky toolbar; without `sticky` the container is made a positioned ancestor.
864
+ */
865
+ .stilo-find-bar-host:not(.stilo-toolbar-host) {
866
+ position: relative;
867
+ }
868
+
869
+ .stilo-find-bar {
870
+ position: absolute;
871
+ top: calc(100% + 4px);
872
+ right: 8px;
873
+ /* Under the popovers of the toolbar (character picker, colors, menus), which open over it. */
874
+ z-index: calc(var(--stilo-z-popover) - 1);
875
+ box-sizing: border-box;
876
+ display: flex;
877
+ flex-direction: column;
878
+ gap: 4px;
879
+ max-width: calc(100% - 16px);
880
+ padding: 6px 8px;
881
+ border: 1px solid var(--stilo-color-border);
882
+ border-radius: var(--stilo-radius);
883
+ background: var(--stilo-color-bg);
884
+ box-shadow: var(--stilo-popover-shadow);
885
+ color: var(--stilo-color-text);
886
+ font-family: var(--stilo-font-family);
887
+ font-size: var(--stilo-font-size);
888
+ transition:
889
+ opacity 0.15s ease,
890
+ transform 0.15s ease,
891
+ display 0.15s allow-discrete;
892
+ }
893
+
894
+ /* Slides in from above; browsers without @starting-style show it at once. */
895
+ @starting-style {
896
+ .stilo-find-bar {
897
+ opacity: 0;
898
+ transform: translateY(-6px);
899
+ }
900
+ }
901
+
902
+ @media (prefers-reduced-motion: reduce) {
903
+ .stilo-find-bar {
904
+ transition: none;
905
+ }
906
+ }
907
+
908
+ .stilo-find-bar__row {
909
+ display: flex;
910
+ align-items: center;
911
+ gap: 4px;
912
+ }
913
+
914
+ .stilo-find-bar[hidden] {
915
+ display: none;
916
+ opacity: 0;
917
+ transform: translateY(-6px);
918
+ }
919
+
920
+ .stilo-find-bar__row[hidden] {
921
+ display: none;
922
+ }
923
+
924
+ .stilo-find-bar__input {
925
+ box-sizing: border-box;
926
+ width: 200px;
927
+ min-width: 0;
928
+ flex: 1 1 auto;
929
+ padding: 4px 8px;
930
+ border: 1px solid var(--stilo-color-border);
931
+ border-radius: var(--stilo-radius);
932
+ background: var(--stilo-color-bg);
933
+ color: inherit;
934
+ font: inherit;
935
+ }
936
+
937
+ .stilo-find-bar__input:focus-visible {
938
+ outline: 2px solid var(--stilo-color-focus);
939
+ outline-offset: -1px;
940
+ }
941
+
942
+ .stilo-find-bar__count {
943
+ min-width: 7em;
944
+ color: var(--stilo-color-muted);
945
+ font-size: 0.9em;
946
+ white-space: nowrap;
947
+ }
948
+
949
+ .stilo-find-bar__button {
950
+ display: flex;
951
+ align-items: center;
952
+ justify-content: center;
953
+ min-width: 28px;
954
+ height: 28px;
955
+ padding: 0;
956
+ border: none;
957
+ border-radius: var(--stilo-radius);
958
+ background: transparent;
959
+ color: inherit;
960
+ cursor: pointer;
961
+ font: inherit;
962
+ }
963
+
964
+ .stilo-find-bar__button:hover {
965
+ background: var(--stilo-color-hover);
966
+ }
967
+
968
+ .stilo-find-bar__button:focus-visible {
969
+ outline: 2px solid var(--stilo-color-focus);
970
+ outline-offset: 1px;
971
+ }
972
+
973
+ .stilo-find-bar__toggle[aria-pressed="true"] {
974
+ background: var(--stilo-color-active);
975
+ }
976
+
977
+ .stilo-find-bar__button--text {
978
+ padding: 0 10px;
979
+ white-space: nowrap;
980
+ border: 1px solid var(--stilo-color-border);
981
+ background: var(--stilo-color-bg);
982
+ }
983
+
984
+ /* Status bar (T-043): word and character count under the editor */
985
+ .stilo-status-bar {
986
+ display: flex;
987
+ gap: 16px;
988
+ padding: 4px 12px;
989
+ border-top: 1px solid var(--stilo-color-separator);
990
+ border-bottom-left-radius: inherit;
991
+ border-bottom-right-radius: inherit;
992
+ background: var(--stilo-color-toolbar-bg);
993
+ color: var(--stilo-color-muted);
994
+ font-family: var(--stilo-font-family);
995
+ font-size: 12px;
996
+ }