@kerebron/extension-menu 0.1.3 → 0.2.1
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/assets/menu.css +539 -0
- package/esm/editor/src/CoreEditor.d.ts.map +1 -1
- package/esm/editor/src/CoreEditor.js +3 -0
- package/esm/extension-menu/src/ExtensionMenu.d.ts.map +1 -1
- package/esm/extension-menu/src/ExtensionMenu.js +6 -6
- package/esm/extension-menu/src/MenuPlugin.d.ts.map +1 -1
- package/esm/extension-menu/src/MenuPlugin.js +5 -6
- package/esm/extension-menu/src/icons.js +1 -1
- package/esm/extension-menu/src/menu.d.ts +2 -0
- package/esm/extension-menu/src/menu.d.ts.map +1 -1
- package/esm/extension-menu/src/menu.js +65 -26
- package/esm/extension-menu/src/prompt.js +6 -6
- package/package.json +1 -1
package/assets/menu.css
ADDED
|
@@ -0,0 +1,539 @@
|
|
|
1
|
+
/* Base menu and toolbar styles */
|
|
2
|
+
.kb-menu {
|
|
3
|
+
margin: 0;
|
|
4
|
+
line-height: 1;
|
|
5
|
+
font-size: var(--kb-text-sm);
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
/* Mobile-first toolbar */
|
|
9
|
+
.kb-menu {
|
|
10
|
+
position: sticky;
|
|
11
|
+
top: 0;
|
|
12
|
+
display: flex;
|
|
13
|
+
flex-wrap: wrap;
|
|
14
|
+
gap: var(--kb-space-xs);
|
|
15
|
+
padding: var(--kb-space-sm);
|
|
16
|
+
background: var(--kb-color-surface);
|
|
17
|
+
border-bottom: 1px solid var(--kb-color-border);
|
|
18
|
+
z-index: var(--kb-z-dropdown);
|
|
19
|
+
overflow-x: auto;
|
|
20
|
+
-webkit-overflow-scrolling: touch;
|
|
21
|
+
scrollbar-width: none;
|
|
22
|
+
-ms-overflow-style: none;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
.kb-menu::-webkit-scrollbar {
|
|
26
|
+
display: none;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/* Mobile: bottom-anchored toolbar for one-handed use */
|
|
30
|
+
@media (max-width: 767px) {
|
|
31
|
+
.kb-menu {
|
|
32
|
+
position: fixed;
|
|
33
|
+
bottom: 0;
|
|
34
|
+
left: 0;
|
|
35
|
+
right: 0;
|
|
36
|
+
top: auto;
|
|
37
|
+
border-bottom: none;
|
|
38
|
+
border-top: 1px solid var(--kb-color-border);
|
|
39
|
+
box-shadow: var(--kb-shadow-lg);
|
|
40
|
+
backdrop-filter: blur(10px);
|
|
41
|
+
background: rgba(255, 255, 255, 0.95);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/* Add bottom padding to editor content to prevent overlap */
|
|
45
|
+
.kb-component {
|
|
46
|
+
padding-bottom: calc(
|
|
47
|
+
var(--kb-touch-target-comfortable) + var(--kb-space-md) * 2
|
|
48
|
+
);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/* Tablet and desktop: top toolbar */
|
|
53
|
+
@media (min-width: 768px) {
|
|
54
|
+
.kb-menu {
|
|
55
|
+
position: relative;
|
|
56
|
+
border-radius: var(--kb-radius-md) var(--kb-radius-md) 0 0;
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
.kb-menu {
|
|
61
|
+
background-color: var(--kb-color-surface);
|
|
62
|
+
z-index: 10000;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/* Toolbar items */
|
|
66
|
+
.kb-menu__button {
|
|
67
|
+
border-radius: var(--kb-radius-sm);
|
|
68
|
+
|
|
69
|
+
min-width: var(--kb-touch-target-comfortable);
|
|
70
|
+
min-height: var(--kb-touch-target-comfortable);
|
|
71
|
+
|
|
72
|
+
border: none;
|
|
73
|
+
background: transparent;
|
|
74
|
+
color: var(--kb-color-text);
|
|
75
|
+
cursor: pointer;
|
|
76
|
+
transition: all 0.2s ease;
|
|
77
|
+
font-size: var(--kb-text-sm);
|
|
78
|
+
flex-shrink: 0;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
.kb-menu__button:hover {
|
|
82
|
+
background: var(--kb-color-hover);
|
|
83
|
+
border-color: var(--kb-color-border);
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
.kb-menu__button:focus {
|
|
87
|
+
outline: 2px solid var(--kb-color-primary);
|
|
88
|
+
outline-offset: 2px;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
.kb-menu__button--active {
|
|
92
|
+
background: var(--kb-color-primary);
|
|
93
|
+
color: white;
|
|
94
|
+
border-color: var(--kb-color-primary);
|
|
95
|
+
border-radius: var(--kb-radius-sm);
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
.kb-menu__button--pressed {
|
|
99
|
+
background: var(--kb-color-active);
|
|
100
|
+
transform: scale(0.95);
|
|
101
|
+
transition: transform 0.1s ease;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
.kb-menu__button--disabled {
|
|
105
|
+
opacity: 0.4;
|
|
106
|
+
cursor: not-allowed;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
.kb-menu__button--disabled:hover {
|
|
110
|
+
background: transparent;
|
|
111
|
+
border-color: transparent;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
/* Icon styling */
|
|
115
|
+
.kb-dropdown__item svg,
|
|
116
|
+
.kb-menu__button svg {
|
|
117
|
+
fill: currentColor;
|
|
118
|
+
height: 1em;
|
|
119
|
+
width: 1em;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
.kb-dropdown__item svg,
|
|
123
|
+
.kb-menu__button span,
|
|
124
|
+
.kb-menu__button svg {
|
|
125
|
+
vertical-align: middle;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
/* Separator */
|
|
129
|
+
.kb-menu__separator {
|
|
130
|
+
width: 1px;
|
|
131
|
+
height: var(--kb-space-lg);
|
|
132
|
+
background: var(--kb-color-border);
|
|
133
|
+
margin: 0 var(--kb-space-xs);
|
|
134
|
+
flex-shrink: 0;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
/* Dropdown menu */
|
|
138
|
+
.kb-dropdown {
|
|
139
|
+
position: relative;
|
|
140
|
+
padding: 1px 0 1px var(--kb-space-sm);
|
|
141
|
+
display: inline-block;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
.kb-dropdown__label {
|
|
145
|
+
min-width: var(--kb-touch-target-comfortable);
|
|
146
|
+
min-height: var(--kb-touch-target-comfortable);
|
|
147
|
+
|
|
148
|
+
border: none;
|
|
149
|
+
background: none;
|
|
150
|
+
font-size: var(--kb-text-sm);
|
|
151
|
+
align-items: center;
|
|
152
|
+
padding-right: var(--kb-space-lg);
|
|
153
|
+
white-space: nowrap;
|
|
154
|
+
cursor: pointer;
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
.kb-dropdown__label:focus {
|
|
158
|
+
outline: 2px solid var(--kb-color-primary);
|
|
159
|
+
outline-offset: -2px;
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
.kb-dropdown__label--active {
|
|
163
|
+
background: var(--kb-color-active);
|
|
164
|
+
color: var(--kb-color-primary);
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
.kb-dropdown__label:after {
|
|
168
|
+
content: '';
|
|
169
|
+
border-left: 4px solid transparent;
|
|
170
|
+
border-right: 4px solid transparent;
|
|
171
|
+
border-top: 4px solid currentColor;
|
|
172
|
+
opacity: 0.6;
|
|
173
|
+
position: absolute;
|
|
174
|
+
right: var(--kb-space-sm);
|
|
175
|
+
top: calc(50% - 2px);
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
.kb-dropdown__menu {
|
|
179
|
+
position: fixed;
|
|
180
|
+
/*min-width: 200px;*/
|
|
181
|
+
min-width: 6em;
|
|
182
|
+
background: var(--kb-color-surface);
|
|
183
|
+
border: 1px solid var(--kb-color-border);
|
|
184
|
+
border-radius: var(--kb-radius-md);
|
|
185
|
+
box-shadow: var(--kb-shadow-lg);
|
|
186
|
+
z-index: var(--kb-z-dropdown);
|
|
187
|
+
padding: var(--kb-space-xs);
|
|
188
|
+
margin-top: var(--kb-space-xs);
|
|
189
|
+
opacity: 0;
|
|
190
|
+
visibility: hidden;
|
|
191
|
+
transform: translateY(-4px);
|
|
192
|
+
transition: all 0.2s ease;
|
|
193
|
+
white-space: nowrap;
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
.kb-dropdown--open .kb-dropdown__menu {
|
|
197
|
+
opacity: 1;
|
|
198
|
+
visibility: visible;
|
|
199
|
+
transform: translateY(0);
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
.kb-dropdown__item {
|
|
203
|
+
display: flex;
|
|
204
|
+
padding: var(--kb-space-sm) var(--kb-space-md);
|
|
205
|
+
border: none;
|
|
206
|
+
background: none;
|
|
207
|
+
text-align: left;
|
|
208
|
+
cursor: pointer;
|
|
209
|
+
border-radius: var(--kb-radius-sm);
|
|
210
|
+
color: var(--kb-color-text);
|
|
211
|
+
font-size: var(--kb-text-sm);
|
|
212
|
+
min-height: var(--kb-touch-target-comfortable);
|
|
213
|
+
align-items: center;
|
|
214
|
+
transition: background-color 0.2s ease;
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
.kb-dropdown__item:hover {
|
|
218
|
+
background: var(--kb-color-hover);
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
.kb-dropdown__item:focus {
|
|
222
|
+
outline: 2px solid var(--kb-color-primary);
|
|
223
|
+
outline-offset: -2px;
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
.kb-dropdown__item--active {
|
|
227
|
+
background: var(--kb-color-active);
|
|
228
|
+
color: var(--kb-color-primary);
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
/* Accessibility: High contrast mode support */
|
|
232
|
+
@media (prefers-contrast: high) {
|
|
233
|
+
.kb-dropdown__item,
|
|
234
|
+
.kb-dropdown__item:focus {
|
|
235
|
+
outline-width: 3px;
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
/* Mobile: full-screen dropdown */
|
|
240
|
+
@media (max-width: 767px) {
|
|
241
|
+
.kb-dropdown__menu,
|
|
242
|
+
.kb-dropdown__menu--mobile {
|
|
243
|
+
position: fixed;
|
|
244
|
+
top: auto;
|
|
245
|
+
bottom: calc(var(--kb-touch-target-comfortable) + var(--kb-space-md) * 2);
|
|
246
|
+
left: var(--kb-space-sm);
|
|
247
|
+
right: var(--kb-space-sm);
|
|
248
|
+
min-width: auto;
|
|
249
|
+
border-radius: var(--kb-radius-lg);
|
|
250
|
+
max-height: 50vh;
|
|
251
|
+
overflow-y: auto;
|
|
252
|
+
padding: var(--kb-space-md);
|
|
253
|
+
backdrop-filter: blur(10px);
|
|
254
|
+
background: rgba(255, 255, 255, 0.95);
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
.kb-dropdown__item {
|
|
258
|
+
padding: var(--kb-space-md);
|
|
259
|
+
min-height: var(--kb-touch-target-comfortable);
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
/* Submenu support */
|
|
264
|
+
.kb-submenu {
|
|
265
|
+
position: relative;
|
|
266
|
+
margin-right: var(--kb-space-sm);
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
.kb-submenu__label {
|
|
270
|
+
position: relative;
|
|
271
|
+
padding-right: var(--kb-space-lg);
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
.kb-submenu__label:after {
|
|
275
|
+
content: '';
|
|
276
|
+
border-top: 4px solid transparent;
|
|
277
|
+
border-bottom: 4px solid transparent;
|
|
278
|
+
border-left: 4px solid currentColor;
|
|
279
|
+
opacity: 0.6;
|
|
280
|
+
position: absolute;
|
|
281
|
+
right: var(--kb-space-sm);
|
|
282
|
+
top: calc(50% - 4px);
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
.kb-submenu__content {
|
|
286
|
+
position: absolute;
|
|
287
|
+
left: 100%;
|
|
288
|
+
top: var(--kb-space-xs);
|
|
289
|
+
/*min-width: 160px;*/
|
|
290
|
+
min-width: 4em;
|
|
291
|
+
background: var(--kb-color-surface);
|
|
292
|
+
border: 1px solid var(--kb-color-border);
|
|
293
|
+
border-radius: var(--kb-radius-md);
|
|
294
|
+
box-shadow: var(--kb-shadow-lg);
|
|
295
|
+
z-index: calc(var(--kb-z-dropdown) + 1);
|
|
296
|
+
padding: var(--kb-space-xs);
|
|
297
|
+
opacity: 0;
|
|
298
|
+
visibility: hidden;
|
|
299
|
+
transform: translateX(-4px);
|
|
300
|
+
transition: all 0.2s ease;
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
.kb-submenu:hover .kb-submenu__content,
|
|
304
|
+
.kb-submenu--open .kb-submenu__content {
|
|
305
|
+
opacity: 1;
|
|
306
|
+
visibility: visible;
|
|
307
|
+
transform: translateX(0);
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
/* Mobile: no submenus, flatten structure */
|
|
311
|
+
@media (max-width: 767px) {
|
|
312
|
+
.kb-submenu__content {
|
|
313
|
+
display: none;
|
|
314
|
+
}
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
/* Tooltip for button labels */
|
|
318
|
+
.kb-tooltip {
|
|
319
|
+
position: absolute;
|
|
320
|
+
bottom: 100%;
|
|
321
|
+
left: 50%;
|
|
322
|
+
transform: translateX(-50%);
|
|
323
|
+
background: var(--kb-color-text);
|
|
324
|
+
color: var(--kb-color-surface);
|
|
325
|
+
padding: var(--kb-space-xs) var(--kb-space-sm);
|
|
326
|
+
border-radius: var(--kb-radius-sm);
|
|
327
|
+
font-size: var(--kb-text-xs);
|
|
328
|
+
white-space: nowrap;
|
|
329
|
+
opacity: 0;
|
|
330
|
+
visibility: hidden;
|
|
331
|
+
transition: all 0.2s ease;
|
|
332
|
+
margin-bottom: var(--kb-space-xs);
|
|
333
|
+
z-index: var(--kb-z-tooltip);
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
.kb-tooltip:after {
|
|
337
|
+
content: '';
|
|
338
|
+
position: absolute;
|
|
339
|
+
top: 100%;
|
|
340
|
+
left: 50%;
|
|
341
|
+
transform: translateX(-50%);
|
|
342
|
+
border-left: 4px solid transparent;
|
|
343
|
+
border-right: 4px solid transparent;
|
|
344
|
+
border-top: 4px solid var(--kb-color-text);
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
.kb-menu__button:hover .kb-tooltip {
|
|
348
|
+
opacity: 1;
|
|
349
|
+
visibility: visible;
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
/* Mobile: no tooltips on touch devices */
|
|
353
|
+
@media (max-width: 767px) {
|
|
354
|
+
.kb-tooltip {
|
|
355
|
+
display: none;
|
|
356
|
+
}
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
/* Accessibility improvements */
|
|
360
|
+
@media (prefers-reduced-motion: reduce) {
|
|
361
|
+
.kb-menu__button,
|
|
362
|
+
.kb-dropdown__menu,
|
|
363
|
+
.kb-submenu__content,
|
|
364
|
+
.kb-tooltip {
|
|
365
|
+
transition: none;
|
|
366
|
+
}
|
|
367
|
+
}
|
|
368
|
+
|
|
369
|
+
.kb-icon {
|
|
370
|
+
min-width: var(--kb-touch-target-comfortable);
|
|
371
|
+
min-height: var(--kb-touch-target-comfortable);
|
|
372
|
+
|
|
373
|
+
display: inline-block;
|
|
374
|
+
line-height: var(--kb-touch-target-comfortable);
|
|
375
|
+
vertical-align: middle;
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
/* Prompt/dialog styles with mobile optimization */
|
|
379
|
+
.kb-prompt {
|
|
380
|
+
background: var(--kb-color-surface);
|
|
381
|
+
padding: var(--kb-space-md) var(--kb-space-lg) var(--kb-space-md)
|
|
382
|
+
var(--kb-space-lg);
|
|
383
|
+
border: 1px solid var(--kb-color-border);
|
|
384
|
+
position: fixed;
|
|
385
|
+
border-radius: var(--kb-radius-md);
|
|
386
|
+
z-index: var(--kb-z-modal);
|
|
387
|
+
box-shadow: var(--kb-shadow-lg);
|
|
388
|
+
top: 50%;
|
|
389
|
+
left: 50%;
|
|
390
|
+
transform: translate(-50%, -50%);
|
|
391
|
+
min-width: 300px;
|
|
392
|
+
max-width: 90vw;
|
|
393
|
+
}
|
|
394
|
+
|
|
395
|
+
.kb-prompt h5 {
|
|
396
|
+
margin: 0 0 var(--kb-space-md) 0;
|
|
397
|
+
font-weight: 600;
|
|
398
|
+
font-size: var(--kb-text-base);
|
|
399
|
+
color: var(--kb-color-text);
|
|
400
|
+
}
|
|
401
|
+
|
|
402
|
+
.kb-prompt input[type='text'],
|
|
403
|
+
.kb-prompt textarea {
|
|
404
|
+
background: var(--kb-color-surface-elevated);
|
|
405
|
+
border: 1px solid var(--kb-color-border);
|
|
406
|
+
border-radius: var(--kb-radius-sm);
|
|
407
|
+
padding: var(--kb-space-sm);
|
|
408
|
+
font-size: var(--kb-text-sm);
|
|
409
|
+
color: var(--kb-color-text);
|
|
410
|
+
width: 100%;
|
|
411
|
+
box-sizing: border-box;
|
|
412
|
+
outline: none;
|
|
413
|
+
}
|
|
414
|
+
|
|
415
|
+
.kb-prompt input[type='text']:focus,
|
|
416
|
+
.kb-prompt textarea:focus {
|
|
417
|
+
border-color: var(--kb-color-primary);
|
|
418
|
+
box-shadow: 0 0 0 3px var(--kb-color-focus);
|
|
419
|
+
}
|
|
420
|
+
|
|
421
|
+
.kb-prompt--close {
|
|
422
|
+
position: absolute;
|
|
423
|
+
right: var(--kb-space-sm);
|
|
424
|
+
top: var(--kb-space-sm);
|
|
425
|
+
color: var(--kb-color-text-muted);
|
|
426
|
+
border: none;
|
|
427
|
+
background: transparent;
|
|
428
|
+
padding: var(--kb-space-xs);
|
|
429
|
+
cursor: pointer;
|
|
430
|
+
border-radius: var(--kb-radius-sm);
|
|
431
|
+
width: var(--kb-space-lg);
|
|
432
|
+
height: var(--kb-space-lg);
|
|
433
|
+
display: flex;
|
|
434
|
+
align-items: center;
|
|
435
|
+
justify-content: center;
|
|
436
|
+
}
|
|
437
|
+
|
|
438
|
+
.kb-prompt--close:hover {
|
|
439
|
+
background: var(--kb-color-hover);
|
|
440
|
+
color: var(--kb-color-text);
|
|
441
|
+
}
|
|
442
|
+
|
|
443
|
+
.kb-prompt--close:after {
|
|
444
|
+
content: '✕';
|
|
445
|
+
font-size: var(--kb-text-sm);
|
|
446
|
+
}
|
|
447
|
+
|
|
448
|
+
.kb-invalid {
|
|
449
|
+
background: #fef2f2;
|
|
450
|
+
border: 1px solid #fecaca;
|
|
451
|
+
color: #991b1b;
|
|
452
|
+
border-radius: var(--kb-radius-sm);
|
|
453
|
+
padding: var(--kb-space-sm) var(--kb-space-md);
|
|
454
|
+
position: absolute;
|
|
455
|
+
min-width: 10em;
|
|
456
|
+
font-size: var(--kb-text-sm);
|
|
457
|
+
}
|
|
458
|
+
|
|
459
|
+
.kb-prompt__buttons {
|
|
460
|
+
margin-top: var(--kb-space-md);
|
|
461
|
+
display: flex;
|
|
462
|
+
gap: var(--kb-space-sm);
|
|
463
|
+
justify-content: flex-end;
|
|
464
|
+
}
|
|
465
|
+
|
|
466
|
+
.kb-prompt__buttons button {
|
|
467
|
+
padding: var(--kb-space-sm) var(--kb-space-md);
|
|
468
|
+
border: 1px solid var(--kb-color-border);
|
|
469
|
+
border-radius: var(--kb-radius-sm);
|
|
470
|
+
background: var(--kb-color-surface);
|
|
471
|
+
color: var(--kb-color-text);
|
|
472
|
+
cursor: pointer;
|
|
473
|
+
font-size: var(--kb-text-sm);
|
|
474
|
+
min-height: var(--kb-touch-target-comfortable);
|
|
475
|
+
}
|
|
476
|
+
|
|
477
|
+
.kb-prompt__buttons button:hover {
|
|
478
|
+
background: var(--kb-color-hover);
|
|
479
|
+
}
|
|
480
|
+
|
|
481
|
+
.kb-prompt__buttons button[type='submit'] {
|
|
482
|
+
background: var(--kb-color-primary);
|
|
483
|
+
color: white;
|
|
484
|
+
border-color: var(--kb-color-primary);
|
|
485
|
+
}
|
|
486
|
+
|
|
487
|
+
.kb-prompt__buttons button[type='submit']:hover {
|
|
488
|
+
background: var(--kb-color-primary-hover);
|
|
489
|
+
}
|
|
490
|
+
|
|
491
|
+
/* Prompt/Dialog mobile optimization */
|
|
492
|
+
@media (max-width: 767px) {
|
|
493
|
+
.kb-editor-prompt {
|
|
494
|
+
position: fixed;
|
|
495
|
+
bottom: var(--kb-space-md);
|
|
496
|
+
left: var(--kb-space-md);
|
|
497
|
+
right: var(--kb-space-md);
|
|
498
|
+
top: auto;
|
|
499
|
+
transform: none;
|
|
500
|
+
max-width: none;
|
|
501
|
+
border-radius: var(--kb-radius-lg);
|
|
502
|
+
padding: var(--kb-space-lg);
|
|
503
|
+
}
|
|
504
|
+
|
|
505
|
+
.kb-editor-prompt input[type='text'],
|
|
506
|
+
.kb-editor-prompt textarea {
|
|
507
|
+
min-height: var(--kb-touch-target-min);
|
|
508
|
+
padding: var(--kb-space-sm);
|
|
509
|
+
font-size: var(--kb-text-base);
|
|
510
|
+
border: 1px solid var(--kb-color-border);
|
|
511
|
+
border-radius: var(--kb-radius-sm);
|
|
512
|
+
background: var(--kb-color-surface);
|
|
513
|
+
color: var(--kb-color-text);
|
|
514
|
+
}
|
|
515
|
+
|
|
516
|
+
.kb-editor-prompt-buttons {
|
|
517
|
+
display: flex;
|
|
518
|
+
gap: var(--kb-space-sm);
|
|
519
|
+
margin-top: var(--kb-space-md);
|
|
520
|
+
}
|
|
521
|
+
|
|
522
|
+
.kb-editor-prompt-buttons button {
|
|
523
|
+
flex: 1;
|
|
524
|
+
min-height: var(--kb-touch-target-comfortable);
|
|
525
|
+
padding: var(--kb-space-sm) var(--kb-space-md);
|
|
526
|
+
border: 1px solid var(--kb-color-border);
|
|
527
|
+
border-radius: var(--kb-radius-sm);
|
|
528
|
+
background: var(--kb-color-surface);
|
|
529
|
+
color: var(--kb-color-text);
|
|
530
|
+
font-size: var(--kb-text-base);
|
|
531
|
+
cursor: pointer;
|
|
532
|
+
}
|
|
533
|
+
|
|
534
|
+
.kb-editor-prompt-buttons button[type='submit'] {
|
|
535
|
+
background: var(--kb-color-primary);
|
|
536
|
+
color: white;
|
|
537
|
+
border-color: var(--kb-color-primary);
|
|
538
|
+
}
|
|
539
|
+
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"CoreEditor.d.ts","sourceRoot":"","sources":["../../../src/editor/src/CoreEditor.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAC9C,OAAO,EAAE,IAAI,IAAI,eAAe,EAAE,KAAK,MAAM,EAAE,MAAM,mBAAmB,CAAC;AAGzE,OAAO,KAAK,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAC7D,OAAO,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAE7D,OAAO,EAAE,eAAe,EAAkB,MAAM,8BAA8B,CAAC;AAgC/E,qBAAa,UAAW,SAAQ,WAAW;IACzC,SAAgB,OAAO,EAAE,OAAO,CAAC,aAAa,CAAC,CAG7C;IACF,OAAO,CAAC,gBAAgB,CAAmB;IAC3C,OAAO,CAAC,cAAc,CAAiB;IAChC,IAAI,EAAG,UAAU,CAAC;IAClB,KAAK,EAAG,WAAW,CAAC;gBAEf,OAAO,GAAE,OAAO,CAAC,aAAa,CAAM;IAyBhD,IAAW,MAAM,qBAEhB;IAEM,KAAK,IAAI,eAAe;IAIxB,GAAG,IAAI,eAAe;IAI7B,OAAO,CAAC,UAAU;
|
|
1
|
+
{"version":3,"file":"CoreEditor.d.ts","sourceRoot":"","sources":["../../../src/editor/src/CoreEditor.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAC9C,OAAO,EAAE,IAAI,IAAI,eAAe,EAAE,KAAK,MAAM,EAAE,MAAM,mBAAmB,CAAC;AAGzE,OAAO,KAAK,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAC7D,OAAO,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAE7D,OAAO,EAAE,eAAe,EAAkB,MAAM,8BAA8B,CAAC;AAgC/E,qBAAa,UAAW,SAAQ,WAAW;IACzC,SAAgB,OAAO,EAAE,OAAO,CAAC,aAAa,CAAC,CAG7C;IACF,OAAO,CAAC,gBAAgB,CAAmB;IAC3C,OAAO,CAAC,cAAc,CAAiB;IAChC,IAAI,EAAG,UAAU,CAAC;IAClB,KAAK,EAAG,WAAW,CAAC;gBAEf,OAAO,GAAE,OAAO,CAAC,aAAa,CAAM;IAyBhD,IAAW,MAAM,qBAEhB;IAEM,KAAK,IAAI,eAAe;IAIxB,GAAG,IAAI,eAAe;IAI7B,OAAO,CAAC,UAAU;IAgBX,mBAAmB,CAAC,WAAW,EAAE,WAAW;IAcnD,OAAO,CAAC,YAAY;IAcb,WAAW,CAAC,OAAO,CAAC,EAAE,GAAG,EAAE,SAAS,CAAC,EAAE,MAAM;IAwC7C,WAAW,CAAC,SAAS,CAAC,EAAE,MAAM;IAkB9B,OAAO,IAAI,WAAW;IAItB,KAAK,CAAC,OAAO,GAAE,OAAO,CAAC,aAAa,CAAM,GAAG,UAAU;IAOvD,KAAK,CAAC,GAAG,CAAC,EAAE,eAAe;CAMnC"}
|
|
@@ -99,6 +99,9 @@ export class CoreEditor extends EventTarget {
|
|
|
99
99
|
if (this.options.element) {
|
|
100
100
|
this.view = new EditorView(this.options.element, {
|
|
101
101
|
state: this.state,
|
|
102
|
+
attributes: {
|
|
103
|
+
class: 'kb-editor',
|
|
104
|
+
},
|
|
102
105
|
dispatchTransaction: (tx) => this.dispatchTransaction(tx),
|
|
103
106
|
});
|
|
104
107
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ExtensionMenu.d.ts","sourceRoot":"","sources":["../../../src/extension-menu/src/ExtensionMenu.ts"],"names":[],"mappings":"AAAA,OAAO,EAAuC,MAAM,EAAE,MAAM,mBAAmB,CAAC;AAChF,OAAO,EAAsB,MAAM,EAAE,MAAM,mBAAmB,CAAC;AAE/D,OAAO,EAAE,KAAK,UAAU,EAAE,SAAS,EAAE,MAAM,yBAAyB,CAAC;AAGrE,OAAO,EAIL,WAAW,EAIZ,MAAM,WAAW,CAAC;AAKnB,OAAO,EACL,aAAa,EACb,QAAQ,EACR,eAAe,EAEf,QAAQ,EAER,QAAQ,GACT,MAAM,WAAW,CAAC;AAkDnB,wBAAgB,SAAS,CAAC,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,MAAM,GAAG,WAAW,EAAE,EAAE,CA2R7E;AAED,MAAM,WAAW,UAAU;IACzB,UAAU,CAAC,CAAC,KAAK,EAAE,WAAW,EAAE,EAAE,GAAG,WAAW,EAAE,EAAE,CAAC;IACrD,QAAQ,EAAE,OAAO,CAAC;CACnB;AAED,qBAAa,aAAc,SAAQ,SAAS;IAG9B,SAAS,CAAC,MAAM,EAAE,UAAU;IAFxC,IAAI,SAAU;gBAEQ,MAAM,GAAE,UAA+B;IAIpD,qBAAqB,CAAC,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE;
|
|
1
|
+
{"version":3,"file":"ExtensionMenu.d.ts","sourceRoot":"","sources":["../../../src/extension-menu/src/ExtensionMenu.ts"],"names":[],"mappings":"AAAA,OAAO,EAAuC,MAAM,EAAE,MAAM,mBAAmB,CAAC;AAChF,OAAO,EAAsB,MAAM,EAAE,MAAM,mBAAmB,CAAC;AAE/D,OAAO,EAAE,KAAK,UAAU,EAAE,SAAS,EAAE,MAAM,yBAAyB,CAAC;AAGrE,OAAO,EAIL,WAAW,EAIZ,MAAM,WAAW,CAAC;AAKnB,OAAO,EACL,aAAa,EACb,QAAQ,EACR,eAAe,EAEf,QAAQ,EAER,QAAQ,GACT,MAAM,WAAW,CAAC;AAkDnB,wBAAgB,SAAS,CAAC,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,MAAM,GAAG,WAAW,EAAE,EAAE,CA2R7E;AAED,MAAM,WAAW,UAAU;IACzB,UAAU,CAAC,CAAC,KAAK,EAAE,WAAW,EAAE,EAAE,GAAG,WAAW,EAAE,EAAE,CAAC;IACrD,QAAQ,EAAE,OAAO,CAAC;CACnB;AAED,qBAAa,aAAc,SAAQ,SAAS;IAG9B,SAAS,CAAC,MAAM,EAAE,UAAU;IAFxC,IAAI,SAAU;gBAEQ,MAAM,GAAE,UAA+B;IAIpD,qBAAqB,CAAC,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE;CAgB7E"}
|
|
@@ -304,15 +304,15 @@ export class ExtensionMenu extends Extension {
|
|
|
304
304
|
});
|
|
305
305
|
}
|
|
306
306
|
getProseMirrorPlugins(editor, schema) {
|
|
307
|
+
const plugins = [];
|
|
307
308
|
let content = buildMenu(editor, schema);
|
|
308
309
|
if (this.config.modifyMenu) {
|
|
309
310
|
content = this.config.modifyMenu(content);
|
|
310
311
|
}
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
];
|
|
312
|
+
plugins.push(new MenuPlugin({
|
|
313
|
+
content,
|
|
314
|
+
floating: this.config.floating,
|
|
315
|
+
}));
|
|
316
|
+
return plugins;
|
|
317
317
|
}
|
|
318
318
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"MenuPlugin.d.ts","sourceRoot":"","sources":["../../../src/extension-menu/src/MenuPlugin.ts"],"names":[],"mappings":"AACA,OAAO,EAAe,MAAM,EAAa,MAAM,mBAAmB,CAAC;AAEnE,OAAO,EAAE,WAAW,EAAiB,MAAM,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"MenuPlugin.d.ts","sourceRoot":"","sources":["../../../src/extension-menu/src/MenuPlugin.ts"],"names":[],"mappings":"AACA,OAAO,EAAe,MAAM,EAAa,MAAM,mBAAmB,CAAC;AAEnE,OAAO,EAAE,WAAW,EAAiB,MAAM,WAAW,CAAC;AAyLvD,qBAAa,UAAW,SAAQ,MAAM;gBACxB,OAAO,EAAE;QAGnB,OAAO,EAAE,SAAS,CAAC,SAAS,WAAW,EAAE,CAAC,EAAE,CAAC;QAK7C,QAAQ,CAAC,EAAE,OAAO,CAAC;KACpB;CAOF"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Plugin } from 'prosemirror-state';
|
|
2
2
|
import { renderGrouped } from './menu.js';
|
|
3
|
-
const
|
|
3
|
+
const CSS_PREFIX = 'kb-menu';
|
|
4
4
|
function isIOS() {
|
|
5
5
|
if (typeof navigator == 'undefined')
|
|
6
6
|
return false;
|
|
@@ -78,11 +78,11 @@ class MenuBarView {
|
|
|
78
78
|
});
|
|
79
79
|
this.root = editorView.root;
|
|
80
80
|
this.wrapper = document.createElement('div');
|
|
81
|
-
this.wrapper.classList.add(
|
|
81
|
+
this.wrapper.classList.add(CSS_PREFIX + '__wrapper');
|
|
82
82
|
this.menu = document.createElement('div');
|
|
83
|
-
this.menu.classList.add(
|
|
83
|
+
this.menu.classList.add(CSS_PREFIX);
|
|
84
84
|
this.wrapper.appendChild(this.menu);
|
|
85
|
-
this.menu.className =
|
|
85
|
+
this.menu.className = CSS_PREFIX;
|
|
86
86
|
if (editorView.dom.parentNode) {
|
|
87
87
|
editorView.dom.parentNode.replaceChild(this.wrapper, editorView.dom);
|
|
88
88
|
}
|
|
@@ -126,7 +126,6 @@ class MenuBarView {
|
|
|
126
126
|
}
|
|
127
127
|
if (this.menu.offsetHeight > this.maxHeight) {
|
|
128
128
|
this.maxHeight = this.menu.offsetHeight;
|
|
129
|
-
this.menu.style.minHeight = this.maxHeight + 'px';
|
|
130
129
|
}
|
|
131
130
|
}
|
|
132
131
|
}
|
|
@@ -183,7 +182,7 @@ class MenuBarView {
|
|
|
183
182
|
this.menu.style.top = top + 'px';
|
|
184
183
|
this.menu.style.position = 'fixed';
|
|
185
184
|
this.spacer = document.createElement('div');
|
|
186
|
-
this.spacer.classList.add(
|
|
185
|
+
this.spacer.classList.add(CSS_PREFIX + '__spacer');
|
|
187
186
|
this.spacer.style.height = `${menuRect.height}px`;
|
|
188
187
|
parent.insertBefore(this.spacer, this.menu);
|
|
189
188
|
}
|
|
@@ -9,6 +9,7 @@ export interface MenuElement {
|
|
|
9
9
|
}
|
|
10
10
|
export declare class MenuItem implements MenuElement {
|
|
11
11
|
readonly spec: MenuItemSpec;
|
|
12
|
+
CSS_PREFIX: string;
|
|
12
13
|
constructor(spec: MenuItemSpec);
|
|
13
14
|
render(view: EditorView): {
|
|
14
15
|
dom: any;
|
|
@@ -44,6 +45,7 @@ export declare class Dropdown implements MenuElement {
|
|
|
44
45
|
class?: string;
|
|
45
46
|
css?: string;
|
|
46
47
|
};
|
|
48
|
+
CSS_PREFIX: string;
|
|
47
49
|
content: readonly MenuElement[];
|
|
48
50
|
constructor(content: readonly MenuElement[] | MenuElement, options?: {
|
|
49
51
|
label?: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"menu.d.ts","sourceRoot":"","sources":["../../../src/extension-menu/src/menu.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAC9C,OAAO,EAAE,WAAW,EAAiB,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAC5E,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AAcpD,MAAM,WAAW,WAAW;IAK1B,MAAM,CACJ,EAAE,EAAE,UAAU,GACb;QAAE,GAAG,EAAE,WAAW,CAAC;QAAC,MAAM,EAAE,CAAC,KAAK,EAAE,WAAW,KAAK,OAAO,CAAA;KAAE,CAAC;CAClE;
|
|
1
|
+
{"version":3,"file":"menu.d.ts","sourceRoot":"","sources":["../../../src/extension-menu/src/menu.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAC9C,OAAO,EAAE,WAAW,EAAiB,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAC5E,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AAcpD,MAAM,WAAW,WAAW;IAK1B,MAAM,CACJ,EAAE,EAAE,UAAU,GACb;QAAE,GAAG,EAAE,WAAW,CAAC;QAAC,MAAM,EAAE,CAAC,KAAK,EAAE,WAAW,KAAK,OAAO,CAAA;KAAE,CAAC;CAClE;AAGD,qBAAa,QAAS,YAAW,WAAW;IAMxC,QAAQ,CAAC,IAAI,EAAE,YAAY;IAL7B,UAAU,SAAqB;gBAKpB,IAAI,EAAE,YAAY;IAM7B,MAAM,CAAC,IAAI,EAAE,UAAU;;wBAmDE,WAAW;;CAsBrC;AAgBD,MAAM,MAAM,QAAQ,GAAG;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,GAAG;IACvE,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,CAAC,EAAE,MAAM,CAAC;CACd,GAAG;IAAE,GAAG,EAAE,IAAI,CAAA;CAAE,CAAC;AAGlB,MAAM,WAAW,YAAY;IAE3B,GAAG,EAAE,CAAC,KAAK,EAAE,WAAW,EAAE,QAAQ,EAAE,CAAC,EAAE,EAAE,WAAW,KAAK,IAAI,KAAK,OAAO,CAAC;IAI1E,MAAM,CAAC,EAAE,CAAC,KAAK,EAAE,WAAW,KAAK,OAAO,CAAC;IAKzC,MAAM,CAAC,EAAE,CAAC,KAAK,EAAE,WAAW,KAAK,OAAO,CAAC;IAKzC,MAAM,CAAC,EAAE,CAAC,KAAK,EAAE,WAAW,KAAK,OAAO,CAAC;IAIzC,MAAM,CAAC,EAAE,CAAC,IAAI,EAAE,UAAU,KAAK,WAAW,CAAC;IAG3C,IAAI,CAAC,EAAE,QAAQ,CAAC;IAKhB,KAAK,CAAC,EAAE,MAAM,CAAC;IAGf,KAAK,CAAC,EAAE,MAAM,GAAG,CAAC,CAAC,KAAK,EAAE,WAAW,KAAK,MAAM,CAAC,CAAC;IAGlD,KAAK,CAAC,EAAE,MAAM,CAAC;IAIf,GAAG,CAAC,EAAE,MAAM,CAAC;CACd;AAiBD,qBAAa,QAAS,YAAW,WAAW;IASxC,QAAQ,CAAC,OAAO,EAAE;QAEhB,KAAK,CAAC,EAAE,MAAM,CAAC;QAKf,KAAK,CAAC,EAAE,MAAM,CAAC;QAGf,KAAK,CAAC,EAAE,MAAM,CAAC;QAGf,GAAG,CAAC,EAAE,MAAM,CAAC;KACd;IAtBH,UAAU,SAAiB;IAE3B,OAAO,EAAE,SAAS,WAAW,EAAE,CAAC;gBAI9B,OAAO,EAAE,SAAS,WAAW,EAAE,GAAG,WAAW,EAEpC,OAAO,GAAE;QAEhB,KAAK,CAAC,EAAE,MAAM,CAAC;QAKf,KAAK,CAAC,EAAE,MAAM,CAAC;QAGf,KAAK,CAAC,EAAE,MAAM,CAAC;QAGf,GAAG,CAAC,EAAE,MAAM,CAAC;KACT;IAOR,MAAM,CAAC,IAAI,EAAE,UAAU;;wBAsDE,WAAW;;IAUpC,MAAM,CAAC,GAAG,EAAE,WAAW,EAAE,KAAK,EAAE,SAAS,IAAI,EAAE;qBAU3B,OAAO;;;CAS5B;AAgCD,qBAAa,eAAgB,YAAW,WAAW;IAS/C,QAAQ,CAAC,OAAO,EAAE;QAEhB,KAAK,CAAC,EAAE,MAAM,CAAC;KAChB;IAVH,OAAO,EAAE,SAAS,WAAW,EAAE,CAAC;gBAK9B,OAAO,EAAE,SAAS,WAAW,EAAE,GAAG,WAAW,EAEpC,OAAO,GAAE;QAEhB,KAAK,CAAC,EAAE,MAAM,CAAC;KACX;IAMR,MAAM,CAAC,IAAI,EAAE,UAAU;;wBAwCE,WAAW;;CAOrC;AAMD,wBAAgB,aAAa,CAC3B,IAAI,EAAE,UAAU,EAChB,OAAO,EAAE,SAAS,CAAC,SAAS,WAAW,EAAE,CAAC,EAAE;;oBAwBrB,WAAW;EAanC;AAYD,wBAAgB,QAAQ,CACtB,QAAQ,EAAE,QAAQ,EAClB,OAAO,EAAE,OAAO,CAAC,YAAY,CAAC,GAAG;IAAE,KAAK,CAAC,EAAE,KAAK,GAAG,IAAI,CAAA;CAAE,YAc1D;AAMD,wBAAgB,aAAa,CAC3B,QAAQ,EAAE,QAAQ,EAClB,OAAO,EAAE,OAAO,CAAC,YAAY,CAAC,GAAG;IAAE,KAAK,CAAC,EAAE,KAAK,GAAG,IAAI,CAAA;CAAE,YAmB1D"}
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { setBlockType, wrapIn, } from '../../editor/src/commands/mod.js';
|
|
2
2
|
import { getIcon } from './icons.js';
|
|
3
|
-
const prefix = 'ProseMirror-menu';
|
|
4
3
|
/// An icon or label that, when clicked, executes a command.
|
|
5
4
|
export class MenuItem {
|
|
6
5
|
/// Create a menu item.
|
|
@@ -13,6 +12,12 @@ export class MenuItem {
|
|
|
13
12
|
writable: true,
|
|
14
13
|
value: spec
|
|
15
14
|
});
|
|
15
|
+
Object.defineProperty(this, "CSS_PREFIX", {
|
|
16
|
+
enumerable: true,
|
|
17
|
+
configurable: true,
|
|
18
|
+
writable: true,
|
|
19
|
+
value: 'kb-menu__button'
|
|
20
|
+
});
|
|
16
21
|
}
|
|
17
22
|
/// Renders the icon according to its [display
|
|
18
23
|
/// spec](#menu.MenuItemSpec.display), and adds an event handler which
|
|
@@ -20,20 +25,35 @@ export class MenuItem {
|
|
|
20
25
|
render(view) {
|
|
21
26
|
let spec = this.spec;
|
|
22
27
|
let dom = spec.render ? spec.render(view) : null;
|
|
23
|
-
if (!dom
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
dom.
|
|
28
|
+
if (!dom) {
|
|
29
|
+
// Create a proper button element for better accessibility
|
|
30
|
+
dom = document.createElement('button');
|
|
31
|
+
dom.setAttribute('type', 'button');
|
|
32
|
+
// Add our new CSS classes while maintaining backward compatibility
|
|
33
|
+
dom.classList.add(this.CSS_PREFIX);
|
|
34
|
+
if (spec.icon) {
|
|
35
|
+
const icon = getIcon(view.root, spec.icon);
|
|
36
|
+
dom.appendChild(icon);
|
|
37
|
+
dom.classList.add(this.CSS_PREFIX + '--icon-only');
|
|
38
|
+
}
|
|
39
|
+
if (spec.label) {
|
|
40
|
+
const labelSpan = document.createElement('span');
|
|
41
|
+
labelSpan.appendChild(document.createTextNode(translate(view, spec.label)));
|
|
42
|
+
dom.appendChild(labelSpan);
|
|
43
|
+
if (spec.icon) {
|
|
44
|
+
dom.classList.remove(this.CSS_PREFIX + '--icon-only');
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
if (!spec.icon && !spec.label) {
|
|
48
|
+
throw new RangeError('MenuItem without icon or label property');
|
|
49
|
+
}
|
|
29
50
|
}
|
|
30
|
-
if (!dom)
|
|
31
|
-
throw new RangeError('MenuItem without icon or label property');
|
|
32
51
|
if (spec.title) {
|
|
33
52
|
const title = typeof spec.title === 'function'
|
|
34
53
|
? spec.title(view.state)
|
|
35
54
|
: spec.title;
|
|
36
55
|
dom.setAttribute('title', translate(view, title));
|
|
56
|
+
dom.setAttribute('aria-label', translate(view, title));
|
|
37
57
|
}
|
|
38
58
|
if (spec.class)
|
|
39
59
|
dom.classList.add(spec.class);
|
|
@@ -41,7 +61,7 @@ export class MenuItem {
|
|
|
41
61
|
dom.style.cssText += spec.css;
|
|
42
62
|
dom.addEventListener('mousedown', (e) => {
|
|
43
63
|
e.preventDefault();
|
|
44
|
-
if (!dom.classList.contains(
|
|
64
|
+
if (!dom.classList.contains(this.CSS_PREFIX + '--disabled')) {
|
|
45
65
|
spec.run(view.state, view.dispatch);
|
|
46
66
|
}
|
|
47
67
|
});
|
|
@@ -55,11 +75,13 @@ export class MenuItem {
|
|
|
55
75
|
let enabled = true;
|
|
56
76
|
if (spec.enable) {
|
|
57
77
|
enabled = spec.enable(state) || false;
|
|
58
|
-
setClass(dom,
|
|
78
|
+
setClass(dom, this.CSS_PREFIX + '--disabled', !enabled);
|
|
79
|
+
dom.setAttribute('aria-disabled', (!enabled).toString());
|
|
59
80
|
}
|
|
60
81
|
if (spec.active) {
|
|
61
82
|
let active = enabled && spec.active(state) || false;
|
|
62
|
-
setClass(dom,
|
|
83
|
+
setClass(dom, this.CSS_PREFIX + '--active', active);
|
|
84
|
+
dom.setAttribute('aria-pressed', active.toString());
|
|
63
85
|
}
|
|
64
86
|
return true;
|
|
65
87
|
}
|
|
@@ -96,6 +118,12 @@ export class Dropdown {
|
|
|
96
118
|
writable: true,
|
|
97
119
|
value: options
|
|
98
120
|
});
|
|
121
|
+
Object.defineProperty(this, "CSS_PREFIX", {
|
|
122
|
+
enumerable: true,
|
|
123
|
+
configurable: true,
|
|
124
|
+
writable: true,
|
|
125
|
+
value: 'kb-dropdown'
|
|
126
|
+
});
|
|
99
127
|
/// @internal
|
|
100
128
|
Object.defineProperty(this, "content", {
|
|
101
129
|
enumerable: true,
|
|
@@ -110,8 +138,10 @@ export class Dropdown {
|
|
|
110
138
|
render(view) {
|
|
111
139
|
let content = renderDropdownItems(this.content, view);
|
|
112
140
|
let win = view.dom.ownerDocument.defaultView;
|
|
113
|
-
|
|
114
|
-
label.
|
|
141
|
+
// Create a button element instead of div for better accessibility
|
|
142
|
+
let label = document.createElement('button');
|
|
143
|
+
label.setAttribute('type', 'button');
|
|
144
|
+
label.classList.add(this.CSS_PREFIX + '__label');
|
|
115
145
|
if (this.options.class) {
|
|
116
146
|
label.classList.add(this.options.class);
|
|
117
147
|
}
|
|
@@ -119,10 +149,15 @@ export class Dropdown {
|
|
|
119
149
|
label.setAttribute('style', this.options.css);
|
|
120
150
|
label.appendChild(document.createTextNode(translate(view, this.options.label || '')));
|
|
121
151
|
if (this.options.title) {
|
|
122
|
-
|
|
152
|
+
const title = translate(view, this.options.title);
|
|
153
|
+
label.setAttribute('title', title);
|
|
154
|
+
label.setAttribute('aria-label', title);
|
|
123
155
|
}
|
|
156
|
+
// Set ARIA attributes for accessibility
|
|
157
|
+
label.setAttribute('aria-haspopup', 'true');
|
|
158
|
+
label.setAttribute('aria-expanded', 'false');
|
|
124
159
|
let wrap = document.createElement('div');
|
|
125
|
-
wrap.classList.add(
|
|
160
|
+
wrap.classList.add(this.CSS_PREFIX);
|
|
126
161
|
wrap.appendChild(label);
|
|
127
162
|
let open = null;
|
|
128
163
|
let listeningOnClose = null;
|
|
@@ -137,9 +172,11 @@ export class Dropdown {
|
|
|
137
172
|
markMenuEvent(e);
|
|
138
173
|
if (open) {
|
|
139
174
|
close();
|
|
175
|
+
wrap.classList.remove('kb-dropdown--open');
|
|
140
176
|
}
|
|
141
177
|
else {
|
|
142
178
|
open = this.expand(wrap, content.dom);
|
|
179
|
+
wrap.classList.add('kb-dropdown--open');
|
|
143
180
|
win.addEventListener('mousedown', listeningOnClose = () => {
|
|
144
181
|
if (!isMenuEvent(wrap))
|
|
145
182
|
close();
|
|
@@ -156,7 +193,8 @@ export class Dropdown {
|
|
|
156
193
|
/// @internal
|
|
157
194
|
expand(dom, items) {
|
|
158
195
|
const menuDOM = document.createElement('div');
|
|
159
|
-
menuDOM.classList.add(
|
|
196
|
+
menuDOM.classList.add('kb-dropdown__menu');
|
|
197
|
+
menuDOM.setAttribute('role', 'menu');
|
|
160
198
|
if (this.options.class) {
|
|
161
199
|
menuDOM.classList.add(this.options.class);
|
|
162
200
|
}
|
|
@@ -178,7 +216,7 @@ function renderDropdownItems(items, view) {
|
|
|
178
216
|
for (let i = 0; i < items.length; i++) {
|
|
179
217
|
let { dom, update } = items[i].render(view);
|
|
180
218
|
const item = document.createElement('div');
|
|
181
|
-
item.classList.add(
|
|
219
|
+
item.classList.add('kb-dropdown__item');
|
|
182
220
|
item.appendChild(dom);
|
|
183
221
|
rendered.push(item);
|
|
184
222
|
updates.push(update);
|
|
@@ -222,27 +260,28 @@ export class DropdownSubmenu {
|
|
|
222
260
|
}
|
|
223
261
|
/// Renders the submenu.
|
|
224
262
|
render(view) {
|
|
263
|
+
const CSS_PREFIX = 'kb-submenu';
|
|
225
264
|
const items = renderDropdownItems(this.content, view);
|
|
226
265
|
const win = view.dom.ownerDocument.defaultView;
|
|
266
|
+
const wrap = document.createElement('div');
|
|
267
|
+
wrap.classList.add(CSS_PREFIX);
|
|
227
268
|
const label = document.createElement('div');
|
|
228
|
-
label.classList.add(
|
|
269
|
+
label.classList.add(CSS_PREFIX + '__label');
|
|
229
270
|
label.appendChild(document.createTextNode(translate(view, this.options.label || '')));
|
|
230
|
-
const wrap = document.createElement('div');
|
|
231
|
-
wrap.classList.add(prefix + '-submenu-wrap');
|
|
232
271
|
wrap.appendChild(label);
|
|
233
272
|
const submenu = document.createElement('div');
|
|
234
|
-
submenu.classList.add(
|
|
273
|
+
submenu.classList.add(CSS_PREFIX + '__content');
|
|
235
274
|
items.dom.forEach((item) => submenu.appendChild(item));
|
|
236
275
|
wrap.appendChild(submenu);
|
|
237
276
|
let listeningOnClose = null;
|
|
238
277
|
label.addEventListener('mousedown', (e) => {
|
|
239
278
|
e.preventDefault();
|
|
240
279
|
markMenuEvent(e);
|
|
241
|
-
setClass(wrap,
|
|
280
|
+
setClass(wrap, CSS_PREFIX + '--open', false);
|
|
242
281
|
if (!listeningOnClose) {
|
|
243
282
|
win.addEventListener('mousedown', listeningOnClose = () => {
|
|
244
283
|
if (!isMenuEvent(wrap)) {
|
|
245
|
-
wrap.classList.remove(
|
|
284
|
+
wrap.classList.remove(CSS_PREFIX + '--open');
|
|
246
285
|
win.removeEventListener('mousedown', listeningOnClose);
|
|
247
286
|
listeningOnClose = null;
|
|
248
287
|
}
|
|
@@ -269,7 +308,7 @@ export function renderGrouped(view, content) {
|
|
|
269
308
|
for (let j = 0; j < items.length; j++) {
|
|
270
309
|
let { dom, update } = items[j].render(view);
|
|
271
310
|
let span = document.createElement('span');
|
|
272
|
-
span.classList.add(
|
|
311
|
+
span.classList.add('kb-menu__item');
|
|
273
312
|
span.appendChild(dom);
|
|
274
313
|
result.appendChild(span);
|
|
275
314
|
localNodes.push(span);
|
|
@@ -299,7 +338,7 @@ export function renderGrouped(view, content) {
|
|
|
299
338
|
}
|
|
300
339
|
function separator() {
|
|
301
340
|
const elem = document.createElement('div');
|
|
302
|
-
elem.classList.add(
|
|
341
|
+
elem.classList.add('kb-menu__separator');
|
|
303
342
|
return elem;
|
|
304
343
|
}
|
|
305
344
|
/// Build a menu item for wrapping the selection in a given node type.
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
const
|
|
1
|
+
const CSS_PREFIX = 'kb-prompt';
|
|
2
2
|
export function openPrompt(options) {
|
|
3
3
|
let wrapper = document.body.appendChild(document.createElement('div'));
|
|
4
|
-
wrapper.className =
|
|
4
|
+
wrapper.className = CSS_PREFIX;
|
|
5
5
|
let mouseOutside = (e) => {
|
|
6
6
|
if (!wrapper.contains(e.target))
|
|
7
7
|
close();
|
|
@@ -18,11 +18,11 @@ export function openPrompt(options) {
|
|
|
18
18
|
}
|
|
19
19
|
let submitButton = document.createElement('button');
|
|
20
20
|
submitButton.type = 'submit';
|
|
21
|
-
submitButton.className =
|
|
21
|
+
submitButton.className = CSS_PREFIX + '--submit';
|
|
22
22
|
submitButton.textContent = 'OK';
|
|
23
23
|
let cancelButton = document.createElement('button');
|
|
24
24
|
cancelButton.type = 'button';
|
|
25
|
-
cancelButton.className =
|
|
25
|
+
cancelButton.className = CSS_PREFIX + '--cancel';
|
|
26
26
|
cancelButton.textContent = 'Cancel';
|
|
27
27
|
cancelButton.addEventListener('click', close);
|
|
28
28
|
let form = wrapper.appendChild(document.createElement('form'));
|
|
@@ -33,7 +33,7 @@ export function openPrompt(options) {
|
|
|
33
33
|
form.appendChild(document.createElement('div')).appendChild(field);
|
|
34
34
|
});
|
|
35
35
|
let buttons = form.appendChild(document.createElement('div'));
|
|
36
|
-
buttons.className =
|
|
36
|
+
buttons.className = CSS_PREFIX + '__buttons';
|
|
37
37
|
buttons.appendChild(submitButton);
|
|
38
38
|
buttons.appendChild(document.createTextNode(' '));
|
|
39
39
|
buttons.appendChild(cancelButton);
|
|
@@ -90,7 +90,7 @@ function reportInvalid(dom, message) {
|
|
|
90
90
|
let msg = parent.appendChild(document.createElement('div'));
|
|
91
91
|
msg.style.left = (dom.offsetLeft + dom.offsetWidth + 2) + 'px';
|
|
92
92
|
msg.style.top = (dom.offsetTop - 5) + 'px';
|
|
93
|
-
msg.className = '
|
|
93
|
+
msg.className = 'kb-invalid';
|
|
94
94
|
msg.textContent = message;
|
|
95
95
|
setTimeout(() => parent.removeChild(msg), 1500);
|
|
96
96
|
}
|