autumnnote 1.6.2 → 1.6.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/autumnnote.es.js +31 -142
- package/dist/autumnnote.es.js.map +1 -1
- package/dist/autumnnote.umd.js +31 -142
- package/dist/autumnnote.umd.js.map +1 -1
- package/package.json +1 -1
- package/src/js/index.js +1 -1
- package/src/js/module/EmojiDialog.js +7 -44
- package/src/js/module/FindReplace.js +4 -18
- package/src/js/module/IconDialog.js +9 -41
- package/src/js/module/ShortcutsDialog.js +20 -49
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "autumnnote",
|
|
3
|
-
"version": "1.6.
|
|
3
|
+
"version": "1.6.3",
|
|
4
4
|
"description": "WYSIWYG rich-text editor built with vanilla JavaScript — zero dependencies, no jQuery. Dark mode, @mention, markdown shortcuts, bubble toolbar. React and Vue 3 wrappers included.",
|
|
5
5
|
"main": "dist/autumnnote.umd.js",
|
|
6
6
|
"module": "dist/autumnnote.es.js",
|
package/src/js/index.js
CHANGED
|
@@ -141,7 +141,7 @@ const AutumnNote = {
|
|
|
141
141
|
registerButton(btnDef) { registerButton(btnDef); return this; },
|
|
142
142
|
|
|
143
143
|
/** Library version */
|
|
144
|
-
version: '1.6.
|
|
144
|
+
version: '1.6.3',
|
|
145
145
|
};
|
|
146
146
|
|
|
147
147
|
// ---------------------------------------------------------------------------
|
|
@@ -3,8 +3,8 @@
|
|
|
3
3
|
* Click an emoji to insert it directly at the caret — no extra "Insert" step.
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
|
-
import { createElement, on,
|
|
7
|
-
import {
|
|
6
|
+
import { createElement, on, makeDraggable } from '../core/dom.js';
|
|
7
|
+
import { BaseDialog } from './BaseDialog.js';
|
|
8
8
|
|
|
9
9
|
// ---------------------------------------------------------------------------
|
|
10
10
|
// Emoji catalogue
|
|
@@ -500,37 +500,18 @@ const EMOJI_LIST = [
|
|
|
500
500
|
// Dialog class
|
|
501
501
|
// ---------------------------------------------------------------------------
|
|
502
502
|
|
|
503
|
-
export class EmojiDialog {
|
|
504
|
-
|
|
505
|
-
* @param {import('../Context.js').Context} context
|
|
506
|
-
*/
|
|
507
|
-
constructor(context) {
|
|
508
|
-
this.context = context;
|
|
509
|
-
/** @type {HTMLElement|null} */
|
|
510
|
-
this._dialog = null;
|
|
511
|
-
this._disposers = [];
|
|
512
|
-
this._savedRange = null;
|
|
513
|
-
this._activeCat = 'all';
|
|
514
|
-
}
|
|
503
|
+
export class EmojiDialog extends BaseDialog {
|
|
504
|
+
_activeCat = 'all';
|
|
515
505
|
|
|
516
506
|
// ---------------------------------------------------------------------------
|
|
517
507
|
// Lifecycle
|
|
518
508
|
// ---------------------------------------------------------------------------
|
|
519
509
|
|
|
520
510
|
initialize() {
|
|
521
|
-
//
|
|
511
|
+
// Grid is built lazily in show() to avoid ~500 DOM nodes at load time.
|
|
522
512
|
return this;
|
|
523
513
|
}
|
|
524
514
|
|
|
525
|
-
destroy() {
|
|
526
|
-
this._disposers.forEach((d) => d());
|
|
527
|
-
this._disposers = [];
|
|
528
|
-
if (this._dialog && this._dialog.parentNode) {
|
|
529
|
-
this._dialog.remove();
|
|
530
|
-
}
|
|
531
|
-
this._dialog = null;
|
|
532
|
-
}
|
|
533
|
-
|
|
534
515
|
// ---------------------------------------------------------------------------
|
|
535
516
|
// Public API
|
|
536
517
|
// ---------------------------------------------------------------------------
|
|
@@ -540,9 +521,7 @@ export class EmojiDialog {
|
|
|
540
521
|
this._dialog = this._buildDialog();
|
|
541
522
|
document.body.appendChild(this._dialog);
|
|
542
523
|
}
|
|
543
|
-
|
|
544
|
-
this._savedRange = range;
|
|
545
|
-
});
|
|
524
|
+
this._saveRange();
|
|
546
525
|
this._activeCat = 'all';
|
|
547
526
|
this._searchInput.value = '';
|
|
548
527
|
this._updateCatTabs();
|
|
@@ -612,6 +591,7 @@ export class EmojiDialog {
|
|
|
612
591
|
grid.appendChild(cell);
|
|
613
592
|
});
|
|
614
593
|
this._grid = grid;
|
|
594
|
+
this._firstInput = searchInput;
|
|
615
595
|
|
|
616
596
|
// Cancel only — clicking an emoji inserts immediately
|
|
617
597
|
const btnRow = createElement('div', { class: 'an-dialog-actions' });
|
|
@@ -724,21 +704,4 @@ export class EmojiDialog {
|
|
|
724
704
|
this.context.invoke('editor.afterCommand');
|
|
725
705
|
}
|
|
726
706
|
|
|
727
|
-
// ---------------------------------------------------------------------------
|
|
728
|
-
// Open / Close
|
|
729
|
-
// ---------------------------------------------------------------------------
|
|
730
|
-
|
|
731
|
-
_open() {
|
|
732
|
-
if (this._dialog) {
|
|
733
|
-
this._dialog.style.display = 'flex';
|
|
734
|
-
this._removeTrap = trapFocus(this._dialog, () => this._close());
|
|
735
|
-
setTimeout(() => this._searchInput?.focus(), 50);
|
|
736
|
-
}
|
|
737
|
-
}
|
|
738
|
-
|
|
739
|
-
_close() {
|
|
740
|
-
if (this._dialog) this._dialog.style.display = 'none';
|
|
741
|
-
if (this._removeTrap) { this._removeTrap(); this._removeTrap = null; }
|
|
742
|
-
this._savedRange = null;
|
|
743
|
-
}
|
|
744
707
|
}
|
|
@@ -8,14 +8,13 @@
|
|
|
8
8
|
*/
|
|
9
9
|
|
|
10
10
|
import { createElement, on, trapFocus, makeDraggable } from '../core/dom.js';
|
|
11
|
+
import { BaseDialog } from './BaseDialog.js';
|
|
11
12
|
|
|
12
|
-
export class FindReplace {
|
|
13
|
+
export class FindReplace extends BaseDialog {
|
|
13
14
|
/** @param {import('../Context.js').Context} context */
|
|
14
15
|
constructor(context) {
|
|
15
|
-
|
|
16
|
+
super(context);
|
|
16
17
|
|
|
17
|
-
/** @type {HTMLElement|null} */
|
|
18
|
-
this._dialog = null;
|
|
19
18
|
/** @type {HTMLInputElement|null} */
|
|
20
19
|
this._findInput = null;
|
|
21
20
|
/** @type {HTMLInputElement|null} */
|
|
@@ -39,8 +38,6 @@ export class FindReplace {
|
|
|
39
38
|
this._lastQuery = null;
|
|
40
39
|
this._lastCaseSensitive = null;
|
|
41
40
|
|
|
42
|
-
this._disposers = [];
|
|
43
|
-
this._removeTrap = null;
|
|
44
41
|
this._focusTimer = null;
|
|
45
42
|
}
|
|
46
43
|
|
|
@@ -48,22 +45,11 @@ export class FindReplace {
|
|
|
48
45
|
// Lifecycle
|
|
49
46
|
// ---------------------------------------------------------------------------
|
|
50
47
|
|
|
51
|
-
initialize() {
|
|
52
|
-
this._dialog = this._buildDialog();
|
|
53
|
-
document.body.appendChild(this._dialog);
|
|
54
|
-
return this;
|
|
55
|
-
}
|
|
56
|
-
|
|
57
48
|
destroy() {
|
|
58
49
|
clearTimeout(this._focusTimer);
|
|
59
50
|
this._focusTimer = null;
|
|
60
51
|
this._clearHighlights();
|
|
61
|
-
|
|
62
|
-
this._disposers = [];
|
|
63
|
-
if (this._dialog && this._dialog.parentNode) {
|
|
64
|
-
this._dialog.remove();
|
|
65
|
-
}
|
|
66
|
-
this._dialog = null;
|
|
52
|
+
super.destroy();
|
|
67
53
|
}
|
|
68
54
|
|
|
69
55
|
// ---------------------------------------------------------------------------
|
|
@@ -2,8 +2,8 @@
|
|
|
2
2
|
* IconDialog.js - Browse and insert FontAwesome Free icons
|
|
3
3
|
*/
|
|
4
4
|
|
|
5
|
-
import { createElement, on,
|
|
6
|
-
import {
|
|
5
|
+
import { createElement, on, makeDraggable } from '../core/dom.js';
|
|
6
|
+
import { BaseDialog } from './BaseDialog.js';
|
|
7
7
|
|
|
8
8
|
// ---------------------------------------------------------------------------
|
|
9
9
|
// Icon catalogue — FA 6 Free Solid slug names, grouped by category
|
|
@@ -247,19 +247,9 @@ const ICON_LIST = [
|
|
|
247
247
|
['puzzle-piece', 'objects'],
|
|
248
248
|
];
|
|
249
249
|
|
|
250
|
-
export class IconDialog {
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
*/
|
|
254
|
-
constructor(context) {
|
|
255
|
-
this.context = context;
|
|
256
|
-
/** @type {HTMLElement|null} */
|
|
257
|
-
this._dialog = null;
|
|
258
|
-
this._disposers = [];
|
|
259
|
-
this._savedRange = null;
|
|
260
|
-
this._selectedIcon = null;
|
|
261
|
-
this._activeCat = 'all';
|
|
262
|
-
}
|
|
250
|
+
export class IconDialog extends BaseDialog {
|
|
251
|
+
_selectedIcon = null;
|
|
252
|
+
_activeCat = 'all';
|
|
263
253
|
|
|
264
254
|
// ---------------------------------------------------------------------------
|
|
265
255
|
// Lifecycle
|
|
@@ -267,7 +257,7 @@ export class IconDialog {
|
|
|
267
257
|
|
|
268
258
|
initialize() {
|
|
269
259
|
this._ensureFontAwesome();
|
|
270
|
-
//
|
|
260
|
+
// Grid is built lazily in show() to avoid ~250 icon cells at load time.
|
|
271
261
|
return this;
|
|
272
262
|
}
|
|
273
263
|
|
|
@@ -294,13 +284,6 @@ export class IconDialog {
|
|
|
294
284
|
document.head.appendChild(link);
|
|
295
285
|
}
|
|
296
286
|
|
|
297
|
-
destroy() {
|
|
298
|
-
this._disposers.forEach((d) => d());
|
|
299
|
-
this._disposers = [];
|
|
300
|
-
this._dialog?.remove();
|
|
301
|
-
this._dialog = null;
|
|
302
|
-
}
|
|
303
|
-
|
|
304
287
|
// ---------------------------------------------------------------------------
|
|
305
288
|
// Public API
|
|
306
289
|
// ---------------------------------------------------------------------------
|
|
@@ -310,9 +293,7 @@ export class IconDialog {
|
|
|
310
293
|
this._dialog = this._buildDialog();
|
|
311
294
|
document.body.appendChild(this._dialog);
|
|
312
295
|
}
|
|
313
|
-
|
|
314
|
-
this._savedRange = range;
|
|
315
|
-
});
|
|
296
|
+
this._saveRange();
|
|
316
297
|
this._selectedIcon = null;
|
|
317
298
|
this._activeCat = 'all';
|
|
318
299
|
this._searchInput.value = '';
|
|
@@ -360,6 +341,7 @@ export class IconDialog {
|
|
|
360
341
|
autocomplete: 'off',
|
|
361
342
|
}));
|
|
362
343
|
this._searchInput = searchInput;
|
|
344
|
+
this._firstInput = searchInput;
|
|
363
345
|
|
|
364
346
|
// Category tabs
|
|
365
347
|
const catBar = createElement('div', { class: 'an-icon-cats' });
|
|
@@ -629,22 +611,8 @@ export class IconDialog {
|
|
|
629
611
|
this.context.invoke('editor.afterCommand');
|
|
630
612
|
}
|
|
631
613
|
|
|
632
|
-
// ---------------------------------------------------------------------------
|
|
633
|
-
// Open / Close
|
|
634
|
-
// ---------------------------------------------------------------------------
|
|
635
|
-
|
|
636
|
-
_open() {
|
|
637
|
-
if (this._dialog) {
|
|
638
|
-
this._dialog.style.display = 'flex';
|
|
639
|
-
this._removeTrap = trapFocus(this._dialog, () => this._close());
|
|
640
|
-
setTimeout(() => this._searchInput?.focus(), 50);
|
|
641
|
-
}
|
|
642
|
-
}
|
|
643
|
-
|
|
644
614
|
_close() {
|
|
645
|
-
if (this._dialog) this._dialog.style.display = 'none';
|
|
646
|
-
if (this._removeTrap) { this._removeTrap(); this._removeTrap = null; }
|
|
647
|
-
this._savedRange = null;
|
|
648
615
|
this._selectedIcon = null;
|
|
616
|
+
super._close();
|
|
649
617
|
}
|
|
650
618
|
}
|
|
@@ -3,7 +3,8 @@
|
|
|
3
3
|
* Opened via the toolbar '?' button or Shift+? inside the editor.
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
|
-
import { createElement, on
|
|
6
|
+
import { createElement, on } from '../core/dom.js';
|
|
7
|
+
import { BaseDialog } from './BaseDialog.js';
|
|
7
8
|
|
|
8
9
|
const SHORTCUTS = [
|
|
9
10
|
{
|
|
@@ -51,64 +52,37 @@ const SHORTCUTS = [
|
|
|
51
52
|
},
|
|
52
53
|
];
|
|
53
54
|
|
|
54
|
-
|
|
55
|
-
/** @param {import('../Context.js').Context} context */
|
|
56
|
-
constructor(context) {
|
|
57
|
-
this.context = context;
|
|
58
|
-
this._dialog = null;
|
|
59
|
-
this._closeBtn = null;
|
|
60
|
-
this._disposers = [];
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
initialize() {
|
|
64
|
-
this._dialog = this._buildDialog();
|
|
65
|
-
document.body.appendChild(this._dialog);
|
|
66
|
-
return this;
|
|
67
|
-
}
|
|
55
|
+
const ICON_SVG = `<svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect x="2" y="7" width="20" height="14" rx="2"/><path d="M6 11h.01M10 11h.01M14 11h.01M18 11h.01M6 15h.01M18 15h.01M10 15h4"/><path d="M7 3l5 4 5-4"/></svg>`;
|
|
68
56
|
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
this._dialog = null;
|
|
74
|
-
}
|
|
57
|
+
export class ShortcutsDialog extends BaseDialog {
|
|
58
|
+
// ---------------------------------------------------------------------------
|
|
59
|
+
// Public API
|
|
60
|
+
// ---------------------------------------------------------------------------
|
|
75
61
|
|
|
76
62
|
show() {
|
|
77
|
-
|
|
78
|
-
this._dialog.style.display = 'flex';
|
|
79
|
-
this._removeTrap = trapFocus(this._dialog, () => this._close());
|
|
80
|
-
setTimeout(() => this._closeBtn?.focus(), 50);
|
|
81
|
-
}
|
|
63
|
+
this._open();
|
|
82
64
|
}
|
|
83
65
|
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
}
|
|
66
|
+
// ---------------------------------------------------------------------------
|
|
67
|
+
// Build dialog
|
|
68
|
+
// ---------------------------------------------------------------------------
|
|
88
69
|
|
|
89
70
|
_buildDialog() {
|
|
90
|
-
const
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
'aria-modal': 'true',
|
|
94
|
-
'aria-label': this.context.locale.shortcutsDialog.ariaLabel,
|
|
95
|
-
});
|
|
71
|
+
const L = this.context.locale.shortcutsDialog;
|
|
72
|
+
const { overlay, box } = this._buildDialogShell(L.ariaLabel, ICON_SVG, L.title);
|
|
73
|
+
box.classList.add('an-shortcuts-box');
|
|
96
74
|
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
// Title row with close button
|
|
100
|
-
const titleRow = createElement('div', { class: 'an-icon-title-row' });
|
|
101
|
-
const title = createElement('h3', { class: 'an-dialog-title' });
|
|
102
|
-
title.textContent = this.context.locale.shortcutsDialog.title;
|
|
75
|
+
// Close button pinned to the right of the header row
|
|
103
76
|
const closeBtn = createElement('button', {
|
|
104
77
|
type: 'button',
|
|
105
78
|
class: 'an-icon-close',
|
|
106
|
-
'aria-label':
|
|
79
|
+
'aria-label': L.close,
|
|
80
|
+
style: 'margin-left:auto',
|
|
107
81
|
});
|
|
108
82
|
closeBtn.textContent = '×';
|
|
109
83
|
this._closeBtn = closeBtn;
|
|
110
|
-
|
|
111
|
-
box.appendChild(
|
|
84
|
+
this._firstInput = closeBtn;
|
|
85
|
+
box.querySelector('.an-dialog-header').appendChild(closeBtn);
|
|
112
86
|
|
|
113
87
|
const shortcuts = this.context.locale.shortcutsDialog.shortcuts || SHORTCUTS;
|
|
114
88
|
shortcuts.forEach(({ category, items }) => {
|
|
@@ -129,11 +103,8 @@ export class ShortcutsDialog {
|
|
|
129
103
|
box.appendChild(table);
|
|
130
104
|
});
|
|
131
105
|
|
|
132
|
-
overlay.appendChild(box);
|
|
133
|
-
|
|
134
106
|
const d1 = on(closeBtn, 'click', () => this._close());
|
|
135
|
-
|
|
136
|
-
this._disposers.push(d1, d2);
|
|
107
|
+
this._disposers.push(d1);
|
|
137
108
|
|
|
138
109
|
return overlay;
|
|
139
110
|
}
|