stilo-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/README.md +61 -7
- package/dist/content.css +238 -1
- package/dist/core/editor.d.ts +15 -3
- package/dist/core/extension-manager.d.ts +3 -3
- package/dist/core/extension.d.ts +6 -1
- package/dist/core/helpers/block-style.d.ts +25 -0
- package/dist/core/helpers/input-rules.d.ts +8 -1
- package/dist/core/helpers/lists.d.ts +10 -2
- package/dist/core/helpers/marks.d.ts +14 -0
- package/dist/core/helpers/nodes.d.ts +12 -0
- package/dist/core/helpers/word-count.d.ts +14 -0
- package/dist/core/html/css.d.ts +16 -1
- package/dist/core/html/paste/base-styles.d.ts +7 -0
- package/dist/core/html/paste/google-docs.d.ts +7 -0
- package/dist/core/html/paste/index.d.ts +9 -0
- package/dist/core/html/paste/table-widths.d.ts +7 -0
- package/dist/core/html/paste/word.d.ts +8 -0
- package/dist/core/html/serialize.d.ts +2 -2
- package/dist/extensions/code-block/index.d.ts +24 -0
- package/dist/extensions/default-extensions/index.d.ts +11 -0
- package/dist/extensions/heading/index.d.ts +2 -1
- package/dist/extensions/image/image-view.d.ts +27 -0
- package/dist/extensions/image/index.d.ts +29 -0
- package/dist/extensions/index.d.ts +10 -1
- package/dist/extensions/line-height/index.d.ts +18 -0
- package/dist/extensions/list-item/index.d.ts +1 -1
- package/dist/extensions/paragraph/index.d.ts +4 -4
- package/dist/extensions/search/index.d.ts +55 -0
- package/dist/extensions/table/index.d.ts +70 -0
- package/dist/extensions/task-item/index.d.ts +24 -0
- package/dist/extensions/task-item/task-item-view.d.ts +24 -0
- package/dist/extensions/task-list/index.d.ts +11 -0
- package/dist/extensions/text-align/index.d.ts +18 -0
- package/dist/extensions/text-case/index.d.ts +14 -0
- package/dist/extensions/text-style/font-size.d.ts +21 -0
- package/dist/extensions/text-style/index.d.ts +18 -2
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -1
- package/dist/src-CV6pgfTS.js +2662 -0
- package/dist/style.css +599 -1
- package/dist/ui/components/dropdown.d.ts +9 -0
- package/dist/ui/components/find-bar.d.ts +24 -0
- package/dist/ui/components/font-size-input.d.ts +21 -0
- package/dist/ui/components/icon-menu.d.ts +20 -0
- package/dist/ui/components/status-bar.d.ts +19 -0
- package/dist/ui/components/table-actions.d.ts +25 -0
- package/dist/ui/components/table-handles.d.ts +16 -0
- package/dist/ui/components/table-menu.d.ts +21 -0
- package/dist/ui/i18n/types.d.ts +1 -1
- package/dist/ui/index.d.ts +6 -2
- package/dist/ui/toolbar/fonts.d.ts +8 -0
- package/dist/ui/toolbar/items.d.ts +23 -2
- package/dist/ui/toolbar/types.d.ts +67 -4
- package/dist/ui.css +361 -0
- package/dist/ui.js +1361 -303
- package/package.json +18 -8
- package/dist/src-3tAxKI0c.js +0 -1316
package/dist/style.css
CHANGED
|
@@ -96,6 +96,60 @@ li.ProseMirror-selectednode:after {
|
|
|
96
96
|
display: block;
|
|
97
97
|
}
|
|
98
98
|
|
|
99
|
+
/*
|
|
100
|
+
* prosemirror-tables/style/tables.css. Copyright (C) 2015-2016 by Marijn Haverbeke and others,
|
|
101
|
+
* MIT license. Adapted: one `cursor` value, the colors from the Stilo custom properties.
|
|
102
|
+
*/
|
|
103
|
+
.ProseMirror .tableWrapper {
|
|
104
|
+
overflow-x: auto;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
.ProseMirror table {
|
|
108
|
+
border-collapse: collapse;
|
|
109
|
+
table-layout: fixed;
|
|
110
|
+
width: 100%;
|
|
111
|
+
overflow: hidden;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
.ProseMirror td,
|
|
115
|
+
.ProseMirror th {
|
|
116
|
+
vertical-align: top;
|
|
117
|
+
box-sizing: border-box;
|
|
118
|
+
position: relative;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
.ProseMirror td:not([data-colwidth]):not(.column-resize-dragging),
|
|
122
|
+
.ProseMirror th:not([data-colwidth]):not(.column-resize-dragging) {
|
|
123
|
+
min-width: var(--default-cell-min-width);
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
.ProseMirror .column-resize-handle {
|
|
127
|
+
position: absolute;
|
|
128
|
+
right: -2px;
|
|
129
|
+
top: 0;
|
|
130
|
+
bottom: 0;
|
|
131
|
+
width: 4px;
|
|
132
|
+
z-index: 20;
|
|
133
|
+
background-color: var(--stilo-color-focus, #0969da);
|
|
134
|
+
pointer-events: none;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
.ProseMirror.resize-cursor {
|
|
138
|
+
cursor: col-resize;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
.ProseMirror .selectedCell:after {
|
|
142
|
+
z-index: 2;
|
|
143
|
+
position: absolute;
|
|
144
|
+
content: "";
|
|
145
|
+
left: 0;
|
|
146
|
+
right: 0;
|
|
147
|
+
top: 0;
|
|
148
|
+
bottom: 0;
|
|
149
|
+
background: var(--stilo-color-selected-cell, rgb(9 105 218 / 0.12));
|
|
150
|
+
pointer-events: none;
|
|
151
|
+
}
|
|
152
|
+
|
|
99
153
|
/* Stilo content defaults */
|
|
100
154
|
|
|
101
155
|
/* Lists: list items hold paragraphs, which must not add their own margins. */
|
|
@@ -107,10 +161,81 @@ li.ProseMirror-selectednode:after {
|
|
|
107
161
|
|
|
108
162
|
.stilo-content li > p,
|
|
109
163
|
.stilo-content li > ul,
|
|
110
|
-
.stilo-content li > ol
|
|
164
|
+
.stilo-content li > ol,
|
|
165
|
+
.stilo-content .stilo-task-item__content > p,
|
|
166
|
+
.stilo-content .stilo-task-item__content > ul,
|
|
167
|
+
.stilo-content .stilo-task-item__content > ol {
|
|
111
168
|
margin: 0;
|
|
112
169
|
}
|
|
113
170
|
|
|
171
|
+
/* Task lists: a checkbox in place of the bullet, done items struck through. In the editor the
|
|
172
|
+
item is a flex row: its <input> checkbox, then the content (ProseMirror needs a container that
|
|
173
|
+
holds only the content). Content shown elsewhere under the class stilo-content gets a box drawn
|
|
174
|
+
from data-checked instead. Either way the box is centered on the first line, not on the whole
|
|
175
|
+
item, which may hold more paragraphs and sub-lists. */
|
|
176
|
+
.stilo-content ul[data-type="taskList"] {
|
|
177
|
+
list-style: none;
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
.stilo-content.ProseMirror ul[data-type="taskList"] {
|
|
181
|
+
padding-left: 0.25em;
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
.stilo-content.ProseMirror ul[data-type="taskList"] > li {
|
|
185
|
+
display: flex;
|
|
186
|
+
gap: 0.5em;
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
.stilo-task-item__content {
|
|
190
|
+
flex: 1;
|
|
191
|
+
min-width: 0;
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
/* Form controls have their own font: inherit it, so that em and lh are those of the text. */
|
|
195
|
+
.stilo-task-item__checkbox {
|
|
196
|
+
flex: none;
|
|
197
|
+
width: 1em;
|
|
198
|
+
height: 1em;
|
|
199
|
+
margin: calc(0.5lh - 0.5em) 0 0;
|
|
200
|
+
font-size: inherit;
|
|
201
|
+
line-height: inherit;
|
|
202
|
+
accent-color: var(--stilo-color-focus, #0969da);
|
|
203
|
+
cursor: pointer;
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
.stilo-content:not(.ProseMirror) ul[data-type="taskList"] > li {
|
|
207
|
+
position: relative;
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
.stilo-content:not(.ProseMirror) ul[data-type="taskList"] > li::before {
|
|
211
|
+
content: "";
|
|
212
|
+
display: flex;
|
|
213
|
+
position: absolute;
|
|
214
|
+
top: calc(0.5lh - 0.5em);
|
|
215
|
+
left: -1.5em;
|
|
216
|
+
box-sizing: border-box;
|
|
217
|
+
width: 1em;
|
|
218
|
+
height: 1em;
|
|
219
|
+
align-items: center;
|
|
220
|
+
justify-content: center;
|
|
221
|
+
border: 1px solid var(--stilo-color-muted, #59636e);
|
|
222
|
+
border-radius: 0.2em;
|
|
223
|
+
color: #ffffff;
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
.stilo-content:not(.ProseMirror) ul[data-type="taskList"] > li[data-checked="true"]::before {
|
|
227
|
+
content: "\2713";
|
|
228
|
+
border-color: var(--stilo-color-focus, #0969da);
|
|
229
|
+
background: var(--stilo-color-focus, #0969da);
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
.stilo-content [data-checked="true"] > .stilo-task-item__content > p:first-child,
|
|
233
|
+
.stilo-content:not(.ProseMirror) [data-checked="true"] > p:first-child,
|
|
234
|
+
.stilo-content:not(.ProseMirror) [data-checked="true"]:not(:has(> p)) {
|
|
235
|
+
color: var(--stilo-color-muted, #59636e);
|
|
236
|
+
text-decoration: line-through;
|
|
237
|
+
}
|
|
238
|
+
|
|
114
239
|
.stilo-content blockquote {
|
|
115
240
|
margin: 0.5em 0;
|
|
116
241
|
padding-left: 1em;
|
|
@@ -132,6 +257,109 @@ li.ProseMirror-selectednode:after {
|
|
|
132
257
|
font-size: 0.9em;
|
|
133
258
|
}
|
|
134
259
|
|
|
260
|
+
/* Code block: the <code> inside it drops the inline code box. */
|
|
261
|
+
.stilo-content pre {
|
|
262
|
+
margin: 0.5em 0;
|
|
263
|
+
padding: 0.75em 1em;
|
|
264
|
+
border-radius: 0.375em;
|
|
265
|
+
background: var(--stilo-color-hover, #eef1f4);
|
|
266
|
+
font-family: ui-monospace, monospace;
|
|
267
|
+
font-size: 0.9em;
|
|
268
|
+
line-height: 1.5;
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
.stilo-content pre code {
|
|
272
|
+
padding: 0;
|
|
273
|
+
border-radius: 0;
|
|
274
|
+
background: none;
|
|
275
|
+
font-size: inherit;
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
/* Tables: a cell holds blocks, whose outer margins would pad the cell twice. */
|
|
279
|
+
.stilo-content .tableWrapper {
|
|
280
|
+
margin: 1em 0;
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
.stilo-content td,
|
|
284
|
+
.stilo-content th {
|
|
285
|
+
padding: 6px 8px;
|
|
286
|
+
border: 1px solid var(--stilo-color-border, #d1d9e0);
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
.stilo-content th {
|
|
290
|
+
background: var(--stilo-color-table-header, #f6f8fa);
|
|
291
|
+
font-weight: 600;
|
|
292
|
+
text-align: start;
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
.stilo-content td > :first-child,
|
|
296
|
+
.stilo-content th > :first-child {
|
|
297
|
+
margin-top: 0;
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
/* The resize handle shown on hover is the last child of its cell: the block before it is the last
|
|
301
|
+
block, otherwise its margin would come back and the table grow under the mouse. */
|
|
302
|
+
.stilo-content td > :last-child,
|
|
303
|
+
.stilo-content th > :last-child,
|
|
304
|
+
.stilo-content td > :has(+ .column-resize-handle:last-child),
|
|
305
|
+
.stilo-content th > :has(+ .column-resize-handle:last-child) {
|
|
306
|
+
margin-bottom: 0;
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
/* Images: never wider than the content; with width and height they keep their ratio. */
|
|
310
|
+
.stilo-content img {
|
|
311
|
+
max-width: 100%;
|
|
312
|
+
height: auto;
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
/* Image in the editor: two side handles, inside the image (a top-level block clips what
|
|
316
|
+
overflows it, see "Large documents" below), shown while the image is selected. Only a selected
|
|
317
|
+
image is positioned: a positioned element paints over the caret placed right after it. */
|
|
318
|
+
.stilo-image {
|
|
319
|
+
display: inline-block;
|
|
320
|
+
max-width: 100%;
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
.stilo-image.ProseMirror-selectednode {
|
|
324
|
+
position: relative;
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
.stilo-image img {
|
|
328
|
+
display: block;
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
.stilo-image__handle {
|
|
332
|
+
display: none;
|
|
333
|
+
position: absolute;
|
|
334
|
+
top: 50%;
|
|
335
|
+
width: 6px;
|
|
336
|
+
height: min(48px, 50%);
|
|
337
|
+
min-height: 16px;
|
|
338
|
+
transform: translateY(-50%);
|
|
339
|
+
border: 1px solid #ffffff;
|
|
340
|
+
border-radius: 3px;
|
|
341
|
+
background: var(--stilo-color-text, #1f2328);
|
|
342
|
+
opacity: 0.7;
|
|
343
|
+
cursor: ew-resize;
|
|
344
|
+
touch-action: none;
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
.stilo-image__handle--left {
|
|
348
|
+
left: 6px;
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
.stilo-image__handle--right {
|
|
352
|
+
right: 6px;
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
.stilo-content[contenteditable="true"] .stilo-image.ProseMirror-selectednode .stilo-image__handle {
|
|
356
|
+
display: block;
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
.stilo-image__handle:hover {
|
|
360
|
+
opacity: 1;
|
|
361
|
+
}
|
|
362
|
+
|
|
135
363
|
/* Placeholder: shown only while the content is editable. */
|
|
136
364
|
.stilo-content[contenteditable="true"] .stilo-placeholder::before {
|
|
137
365
|
content: attr(data-placeholder);
|
|
@@ -160,6 +388,15 @@ li.ProseMirror-selectednode:after {
|
|
|
160
388
|
margin-bottom: 0;
|
|
161
389
|
}
|
|
162
390
|
|
|
391
|
+
/* Find and replace (T-043): the matches and the selected one */
|
|
392
|
+
.stilo-search-match {
|
|
393
|
+
background: var(--stilo-color-search-match, #fff1a8);
|
|
394
|
+
}
|
|
395
|
+
|
|
396
|
+
.stilo-search-match--current {
|
|
397
|
+
background: var(--stilo-color-search-current, #ffb347);
|
|
398
|
+
}
|
|
399
|
+
|
|
163
400
|
/* Stilo default UI styles. */
|
|
164
401
|
|
|
165
402
|
/*
|
|
@@ -302,6 +539,11 @@ li.ProseMirror-selectednode:after {
|
|
|
302
539
|
background: var(--stilo-color-active);
|
|
303
540
|
}
|
|
304
541
|
|
|
542
|
+
/* The find button while its bar is open (T-043) */
|
|
543
|
+
.stilo-toolbar__button[data-item="find"][aria-expanded="true"] {
|
|
544
|
+
background: var(--stilo-color-active);
|
|
545
|
+
}
|
|
546
|
+
|
|
305
547
|
.stilo-toolbar__button[aria-disabled="true"] {
|
|
306
548
|
opacity: 0.4;
|
|
307
549
|
cursor: default;
|
|
@@ -346,13 +588,24 @@ li.ProseMirror-selectednode:after {
|
|
|
346
588
|
width: auto;
|
|
347
589
|
min-width: 120px;
|
|
348
590
|
justify-content: space-between;
|
|
591
|
+
gap: 6px;
|
|
349
592
|
padding: 0 8px;
|
|
350
593
|
}
|
|
351
594
|
|
|
595
|
+
.stilo-dropdown__trigger[data-item="fontFamily"] {
|
|
596
|
+
width: 120px;
|
|
597
|
+
}
|
|
598
|
+
|
|
599
|
+
/* A long value is truncated, the chevron keeps its size */
|
|
600
|
+
.stilo-dropdown__trigger .stilo-icon {
|
|
601
|
+
flex-shrink: 0;
|
|
602
|
+
}
|
|
603
|
+
|
|
352
604
|
.stilo-dropdown__value {
|
|
353
605
|
overflow: hidden;
|
|
354
606
|
text-overflow: ellipsis;
|
|
355
607
|
white-space: nowrap;
|
|
608
|
+
font-weight: 600;
|
|
356
609
|
}
|
|
357
610
|
|
|
358
611
|
.stilo-dropdown__menu {
|
|
@@ -434,6 +687,87 @@ li.ProseMirror-selectednode:after {
|
|
|
434
687
|
font-weight: 600;
|
|
435
688
|
}
|
|
436
689
|
|
|
690
|
+
/* Font size control: − field + */
|
|
691
|
+
.stilo-font-size {
|
|
692
|
+
display: inline-flex;
|
|
693
|
+
align-items: center;
|
|
694
|
+
gap: var(--stilo-toolbar-gap);
|
|
695
|
+
}
|
|
696
|
+
|
|
697
|
+
.stilo-font-size__input {
|
|
698
|
+
box-sizing: border-box;
|
|
699
|
+
width: 2.5em;
|
|
700
|
+
height: calc(var(--stilo-button-size) - 4px);
|
|
701
|
+
padding: 0 4px;
|
|
702
|
+
border: 1px solid var(--stilo-color-border);
|
|
703
|
+
border-radius: var(--stilo-radius);
|
|
704
|
+
background: var(--stilo-color-bg);
|
|
705
|
+
color: var(--stilo-color-text);
|
|
706
|
+
font-family: var(--stilo-font-family);
|
|
707
|
+
font-size: var(--stilo-font-size);
|
|
708
|
+
text-align: center;
|
|
709
|
+
font-weight: 600;
|
|
710
|
+
}
|
|
711
|
+
|
|
712
|
+
.stilo-font-size__input:focus-visible {
|
|
713
|
+
outline: 2px solid var(--stilo-color-focus);
|
|
714
|
+
outline-offset: -1px;
|
|
715
|
+
}
|
|
716
|
+
|
|
717
|
+
.stilo-font-size__input[aria-invalid="true"] {
|
|
718
|
+
border-color: var(--stilo-color-error);
|
|
719
|
+
}
|
|
720
|
+
|
|
721
|
+
.stilo-font-size__input[aria-disabled="true"] {
|
|
722
|
+
opacity: 0.4;
|
|
723
|
+
}
|
|
724
|
+
|
|
725
|
+
.stilo-font-size__list {
|
|
726
|
+
min-width: 4.5em;
|
|
727
|
+
max-height: 280px;
|
|
728
|
+
overflow-y: auto;
|
|
729
|
+
}
|
|
730
|
+
|
|
731
|
+
.stilo-font-size__option {
|
|
732
|
+
padding: 4px 12px;
|
|
733
|
+
border-radius: var(--stilo-radius);
|
|
734
|
+
cursor: pointer;
|
|
735
|
+
font-family: var(--stilo-font-family);
|
|
736
|
+
font-size: var(--stilo-font-size);
|
|
737
|
+
color: var(--stilo-color-text);
|
|
738
|
+
text-align: center;
|
|
739
|
+
}
|
|
740
|
+
|
|
741
|
+
.stilo-font-size__option:hover,
|
|
742
|
+
.stilo-font-size__option--active {
|
|
743
|
+
background: var(--stilo-color-hover);
|
|
744
|
+
}
|
|
745
|
+
|
|
746
|
+
.stilo-font-size__option[aria-selected="true"] {
|
|
747
|
+
background: var(--stilo-color-active);
|
|
748
|
+
}
|
|
749
|
+
|
|
750
|
+
/* Icon menu (text alignment): the options in a row. An icon dropdown (line spacing) has the same
|
|
751
|
+
trigger. */
|
|
752
|
+
.stilo-icon-menu__trigger,
|
|
753
|
+
.stilo-dropdown__trigger--icon {
|
|
754
|
+
width: auto;
|
|
755
|
+
min-width: var(--stilo-button-size);
|
|
756
|
+
gap: 2px;
|
|
757
|
+
padding: 0 4px;
|
|
758
|
+
}
|
|
759
|
+
|
|
760
|
+
.stilo-icon-menu {
|
|
761
|
+
display: flex;
|
|
762
|
+
gap: var(--stilo-toolbar-gap);
|
|
763
|
+
}
|
|
764
|
+
|
|
765
|
+
.stilo-icon-menu__trigger .stilo-icon:last-child,
|
|
766
|
+
.stilo-dropdown__trigger--icon .stilo-icon:last-child {
|
|
767
|
+
width: 12px;
|
|
768
|
+
height: 12px;
|
|
769
|
+
}
|
|
770
|
+
|
|
437
771
|
/* Link popover */
|
|
438
772
|
.stilo-link-popover__form {
|
|
439
773
|
display: flex;
|
|
@@ -624,6 +958,132 @@ li.ProseMirror-selectednode:after {
|
|
|
624
958
|
color: var(--stilo-color-muted);
|
|
625
959
|
}
|
|
626
960
|
|
|
961
|
+
/* Table menu (T-045): insert grid of 10 columns (GRID_COLUMNS in table-menu.ts), operations */
|
|
962
|
+
.stilo-table-menu {
|
|
963
|
+
font-family: var(--stilo-font-family);
|
|
964
|
+
font-size: var(--stilo-font-size);
|
|
965
|
+
color: var(--stilo-color-text);
|
|
966
|
+
}
|
|
967
|
+
|
|
968
|
+
.stilo-table-menu__picker {
|
|
969
|
+
display: flex;
|
|
970
|
+
flex-direction: column;
|
|
971
|
+
gap: 6px;
|
|
972
|
+
padding: 4px;
|
|
973
|
+
}
|
|
974
|
+
|
|
975
|
+
.stilo-table-menu__picker[hidden],
|
|
976
|
+
.stilo-table-menu__actions[hidden] {
|
|
977
|
+
display: none;
|
|
978
|
+
}
|
|
979
|
+
|
|
980
|
+
.stilo-table-menu__grid {
|
|
981
|
+
display: grid;
|
|
982
|
+
grid-template-columns: repeat(10, 18px);
|
|
983
|
+
gap: 3px;
|
|
984
|
+
}
|
|
985
|
+
|
|
986
|
+
.stilo-table-menu__cell {
|
|
987
|
+
width: 18px;
|
|
988
|
+
height: 18px;
|
|
989
|
+
padding: 0;
|
|
990
|
+
border: 1px solid var(--stilo-color-border);
|
|
991
|
+
border-radius: 3px;
|
|
992
|
+
background: var(--stilo-color-bg);
|
|
993
|
+
cursor: pointer;
|
|
994
|
+
}
|
|
995
|
+
|
|
996
|
+
.stilo-table-menu__cell--active {
|
|
997
|
+
border-color: var(--stilo-color-focus);
|
|
998
|
+
background: var(--stilo-color-active);
|
|
999
|
+
}
|
|
1000
|
+
|
|
1001
|
+
.stilo-table-menu__cell:focus-visible {
|
|
1002
|
+
outline: 2px solid var(--stilo-color-focus);
|
|
1003
|
+
outline-offset: 1px;
|
|
1004
|
+
}
|
|
1005
|
+
|
|
1006
|
+
.stilo-table-menu__size {
|
|
1007
|
+
text-align: center;
|
|
1008
|
+
color: var(--stilo-color-muted);
|
|
1009
|
+
}
|
|
1010
|
+
|
|
1011
|
+
.stilo-table-menu__header {
|
|
1012
|
+
display: flex;
|
|
1013
|
+
align-items: center;
|
|
1014
|
+
gap: 6px;
|
|
1015
|
+
cursor: pointer;
|
|
1016
|
+
}
|
|
1017
|
+
|
|
1018
|
+
.stilo-table-menu__actions {
|
|
1019
|
+
min-width: 200px;
|
|
1020
|
+
}
|
|
1021
|
+
|
|
1022
|
+
.stilo-table-menu__actions .stilo-dropdown__option[aria-checked] {
|
|
1023
|
+
background: transparent;
|
|
1024
|
+
}
|
|
1025
|
+
|
|
1026
|
+
.stilo-table-menu__actions .stilo-dropdown__option[aria-checked]:hover,
|
|
1027
|
+
.stilo-table-menu__actions .stilo-dropdown__option[aria-checked]:focus-visible {
|
|
1028
|
+
background: var(--stilo-color-hover);
|
|
1029
|
+
}
|
|
1030
|
+
|
|
1031
|
+
.stilo-table-menu__actions .stilo-dropdown__option[aria-checked]::after {
|
|
1032
|
+
content: "✓";
|
|
1033
|
+
margin-left: auto;
|
|
1034
|
+
visibility: hidden;
|
|
1035
|
+
}
|
|
1036
|
+
|
|
1037
|
+
.stilo-table-menu__actions .stilo-dropdown__option[aria-checked="true"]::after {
|
|
1038
|
+
visibility: visible;
|
|
1039
|
+
}
|
|
1040
|
+
|
|
1041
|
+
/* Table handles (T-049): row, column and corner, over the editor */
|
|
1042
|
+
.stilo-table-handle {
|
|
1043
|
+
position: absolute;
|
|
1044
|
+
top: 0;
|
|
1045
|
+
left: 0;
|
|
1046
|
+
z-index: var(--stilo-z-popover);
|
|
1047
|
+
display: flex;
|
|
1048
|
+
align-items: center;
|
|
1049
|
+
justify-content: center;
|
|
1050
|
+
width: 18px;
|
|
1051
|
+
height: 18px;
|
|
1052
|
+
padding: 0;
|
|
1053
|
+
border: 1px solid var(--stilo-color-border);
|
|
1054
|
+
border-radius: var(--stilo-radius);
|
|
1055
|
+
background: var(--stilo-color-bg);
|
|
1056
|
+
color: var(--stilo-color-muted);
|
|
1057
|
+
cursor: pointer;
|
|
1058
|
+
}
|
|
1059
|
+
|
|
1060
|
+
.stilo-table-handle[hidden] {
|
|
1061
|
+
display: none;
|
|
1062
|
+
}
|
|
1063
|
+
|
|
1064
|
+
.stilo-table-handle:hover,
|
|
1065
|
+
.stilo-table-handle[aria-expanded="true"] {
|
|
1066
|
+
border-color: var(--stilo-color-focus);
|
|
1067
|
+
color: var(--stilo-color-focus);
|
|
1068
|
+
}
|
|
1069
|
+
|
|
1070
|
+
.stilo-table-handle .stilo-icon {
|
|
1071
|
+
width: 14px;
|
|
1072
|
+
height: 14px;
|
|
1073
|
+
}
|
|
1074
|
+
|
|
1075
|
+
.stilo-table-handle-menu {
|
|
1076
|
+
font-family: var(--stilo-font-family);
|
|
1077
|
+
font-size: var(--stilo-font-size);
|
|
1078
|
+
color: var(--stilo-color-text);
|
|
1079
|
+
}
|
|
1080
|
+
|
|
1081
|
+
.stilo-table-menu__separator {
|
|
1082
|
+
height: 1px;
|
|
1083
|
+
margin: 4px 0;
|
|
1084
|
+
background: var(--stilo-color-separator);
|
|
1085
|
+
}
|
|
1086
|
+
|
|
627
1087
|
/* Color split button (T-026): the main part shows the last used color under its icon */
|
|
628
1088
|
.stilo-split {
|
|
629
1089
|
display: flex;
|
|
@@ -795,3 +1255,141 @@ li.ProseMirror-selectednode:after {
|
|
|
795
1255
|
font: inherit;
|
|
796
1256
|
cursor: pointer;
|
|
797
1257
|
}
|
|
1258
|
+
|
|
1259
|
+
/*
|
|
1260
|
+
* Find bar (T-043): a floating panel at the top right, just under the toolbar, over the content
|
|
1261
|
+
* (the content does not move). It lives in the toolbar container, so it stays at the top with a
|
|
1262
|
+
* sticky toolbar; without `sticky` the container is made a positioned ancestor.
|
|
1263
|
+
*/
|
|
1264
|
+
.stilo-find-bar-host:not(.stilo-toolbar-host) {
|
|
1265
|
+
position: relative;
|
|
1266
|
+
}
|
|
1267
|
+
|
|
1268
|
+
.stilo-find-bar {
|
|
1269
|
+
position: absolute;
|
|
1270
|
+
top: calc(100% + 4px);
|
|
1271
|
+
right: 8px;
|
|
1272
|
+
/* Under the popovers of the toolbar (character picker, colors, menus), which open over it. */
|
|
1273
|
+
z-index: calc(var(--stilo-z-popover) - 1);
|
|
1274
|
+
box-sizing: border-box;
|
|
1275
|
+
display: flex;
|
|
1276
|
+
flex-direction: column;
|
|
1277
|
+
gap: 4px;
|
|
1278
|
+
max-width: calc(100% - 16px);
|
|
1279
|
+
padding: 6px 8px;
|
|
1280
|
+
border: 1px solid var(--stilo-color-border);
|
|
1281
|
+
border-radius: var(--stilo-radius);
|
|
1282
|
+
background: var(--stilo-color-bg);
|
|
1283
|
+
box-shadow: var(--stilo-popover-shadow);
|
|
1284
|
+
color: var(--stilo-color-text);
|
|
1285
|
+
font-family: var(--stilo-font-family);
|
|
1286
|
+
font-size: var(--stilo-font-size);
|
|
1287
|
+
transition:
|
|
1288
|
+
opacity 0.15s ease,
|
|
1289
|
+
transform 0.15s ease,
|
|
1290
|
+
display 0.15s allow-discrete;
|
|
1291
|
+
}
|
|
1292
|
+
|
|
1293
|
+
/* Slides in from above; browsers without @starting-style show it at once. */
|
|
1294
|
+
@starting-style {
|
|
1295
|
+
.stilo-find-bar {
|
|
1296
|
+
opacity: 0;
|
|
1297
|
+
transform: translateY(-6px);
|
|
1298
|
+
}
|
|
1299
|
+
}
|
|
1300
|
+
|
|
1301
|
+
@media (prefers-reduced-motion: reduce) {
|
|
1302
|
+
.stilo-find-bar {
|
|
1303
|
+
transition: none;
|
|
1304
|
+
}
|
|
1305
|
+
}
|
|
1306
|
+
|
|
1307
|
+
.stilo-find-bar__row {
|
|
1308
|
+
display: flex;
|
|
1309
|
+
align-items: center;
|
|
1310
|
+
gap: 4px;
|
|
1311
|
+
}
|
|
1312
|
+
|
|
1313
|
+
.stilo-find-bar[hidden] {
|
|
1314
|
+
display: none;
|
|
1315
|
+
opacity: 0;
|
|
1316
|
+
transform: translateY(-6px);
|
|
1317
|
+
}
|
|
1318
|
+
|
|
1319
|
+
.stilo-find-bar__row[hidden] {
|
|
1320
|
+
display: none;
|
|
1321
|
+
}
|
|
1322
|
+
|
|
1323
|
+
.stilo-find-bar__input {
|
|
1324
|
+
box-sizing: border-box;
|
|
1325
|
+
width: 200px;
|
|
1326
|
+
min-width: 0;
|
|
1327
|
+
flex: 1 1 auto;
|
|
1328
|
+
padding: 4px 8px;
|
|
1329
|
+
border: 1px solid var(--stilo-color-border);
|
|
1330
|
+
border-radius: var(--stilo-radius);
|
|
1331
|
+
background: var(--stilo-color-bg);
|
|
1332
|
+
color: inherit;
|
|
1333
|
+
font: inherit;
|
|
1334
|
+
}
|
|
1335
|
+
|
|
1336
|
+
.stilo-find-bar__input:focus-visible {
|
|
1337
|
+
outline: 2px solid var(--stilo-color-focus);
|
|
1338
|
+
outline-offset: -1px;
|
|
1339
|
+
}
|
|
1340
|
+
|
|
1341
|
+
.stilo-find-bar__count {
|
|
1342
|
+
min-width: 7em;
|
|
1343
|
+
color: var(--stilo-color-muted);
|
|
1344
|
+
font-size: 0.9em;
|
|
1345
|
+
white-space: nowrap;
|
|
1346
|
+
}
|
|
1347
|
+
|
|
1348
|
+
.stilo-find-bar__button {
|
|
1349
|
+
display: flex;
|
|
1350
|
+
align-items: center;
|
|
1351
|
+
justify-content: center;
|
|
1352
|
+
min-width: 28px;
|
|
1353
|
+
height: 28px;
|
|
1354
|
+
padding: 0;
|
|
1355
|
+
border: none;
|
|
1356
|
+
border-radius: var(--stilo-radius);
|
|
1357
|
+
background: transparent;
|
|
1358
|
+
color: inherit;
|
|
1359
|
+
cursor: pointer;
|
|
1360
|
+
font: inherit;
|
|
1361
|
+
}
|
|
1362
|
+
|
|
1363
|
+
.stilo-find-bar__button:hover {
|
|
1364
|
+
background: var(--stilo-color-hover);
|
|
1365
|
+
}
|
|
1366
|
+
|
|
1367
|
+
.stilo-find-bar__button:focus-visible {
|
|
1368
|
+
outline: 2px solid var(--stilo-color-focus);
|
|
1369
|
+
outline-offset: 1px;
|
|
1370
|
+
}
|
|
1371
|
+
|
|
1372
|
+
.stilo-find-bar__toggle[aria-pressed="true"] {
|
|
1373
|
+
background: var(--stilo-color-active);
|
|
1374
|
+
}
|
|
1375
|
+
|
|
1376
|
+
.stilo-find-bar__button--text {
|
|
1377
|
+
padding: 0 10px;
|
|
1378
|
+
white-space: nowrap;
|
|
1379
|
+
border: 1px solid var(--stilo-color-border);
|
|
1380
|
+
background: var(--stilo-color-bg);
|
|
1381
|
+
}
|
|
1382
|
+
|
|
1383
|
+
/* Status bar (T-043): word and character count under the editor */
|
|
1384
|
+
.stilo-status-bar {
|
|
1385
|
+
display: flex;
|
|
1386
|
+
gap: 16px;
|
|
1387
|
+
padding: 4px 12px;
|
|
1388
|
+
border-top: 1px solid var(--stilo-color-separator);
|
|
1389
|
+
border-bottom-left-radius: inherit;
|
|
1390
|
+
border-bottom-right-radius: inherit;
|
|
1391
|
+
background: var(--stilo-color-toolbar-bg);
|
|
1392
|
+
color: var(--stilo-color-muted);
|
|
1393
|
+
font-family: var(--stilo-font-family);
|
|
1394
|
+
font-size: 12px;
|
|
1395
|
+
}
|
|
@@ -1,13 +1,20 @@
|
|
|
1
|
+
import { type IconNode } from 'lucide';
|
|
1
2
|
/** One option as displayed: label and shortcut already resolved and formatted. */
|
|
2
3
|
export interface DropdownOptionView {
|
|
3
4
|
id: string;
|
|
4
5
|
label: string;
|
|
5
6
|
shortcut?: string;
|
|
7
|
+
/** The label is drawn in this font family. */
|
|
8
|
+
fontFamily?: string;
|
|
9
|
+
/** An action (`menuitem`), never checked; otherwise a `menuitemradio`. */
|
|
10
|
+
action?: boolean;
|
|
6
11
|
}
|
|
7
12
|
export interface DropdownOptions {
|
|
8
13
|
/** Accessible name of the trigger and of the menu; shown when no option is active. */
|
|
9
14
|
label: string;
|
|
10
15
|
options: DropdownOptionView[];
|
|
16
|
+
/** Shown by the trigger instead of the value; the value stays in its accessible name. */
|
|
17
|
+
icon?: IconNode;
|
|
11
18
|
/** The popover container (the toolbar element). */
|
|
12
19
|
container: HTMLElement;
|
|
13
20
|
onSelect(id: string): void;
|
|
@@ -15,6 +22,8 @@ export interface DropdownOptions {
|
|
|
15
22
|
export interface DropdownState {
|
|
16
23
|
activeId: string | null;
|
|
17
24
|
disabledIds: ReadonlySet<string>;
|
|
25
|
+
/** Shown by the trigger when no option is active; default: the dropdown label. */
|
|
26
|
+
valueLabel?: string | null;
|
|
18
27
|
}
|
|
19
28
|
export interface Dropdown {
|
|
20
29
|
/** The trigger button; the toolbar inserts it in its group. */
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import type { Editor } from '../../index';
|
|
2
|
+
import type { Messages } from '../i18n/types';
|
|
3
|
+
/** Options of {@link createFindBar}. */
|
|
4
|
+
export interface FindBarOptions {
|
|
5
|
+
/** The find bar is appended inside it, after the toolbar. */
|
|
6
|
+
container: HTMLElement;
|
|
7
|
+
messages: Messages;
|
|
8
|
+
/** The toolbar button that toggles the bar: it gets `aria-expanded`. */
|
|
9
|
+
button?: HTMLElement | null;
|
|
10
|
+
}
|
|
11
|
+
/** The find and replace bar (T-043). */
|
|
12
|
+
export interface FindBar {
|
|
13
|
+
readonly element: HTMLElement;
|
|
14
|
+
readonly isOpen: boolean;
|
|
15
|
+
/** Shows the bar and focuses the find field, prefilled with the selected text. */
|
|
16
|
+
open(): void;
|
|
17
|
+
/** Hides the bar, clears the search and gives the focus back to the editor. */
|
|
18
|
+
close(): void;
|
|
19
|
+
/** Closes the bar when it is open, otherwise opens it. */
|
|
20
|
+
toggle(): void;
|
|
21
|
+
destroy(): void;
|
|
22
|
+
}
|
|
23
|
+
/** Creates the find bar (hidden). */
|
|
24
|
+
export declare function createFindBar(editor: Editor, options: FindBarOptions): FindBar;
|