autumnnote 2.1.0 → 2.3.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 +74 -6
- package/dist/autumnnote.cjs +27 -22
- package/dist/autumnnote.es.js +474 -591
- package/dist/autumnnote.es.js.map +1 -1
- package/dist/autumnnote.min.js +27 -22
- package/dist/autumnnote.umd.js +27 -22
- package/dist/autumnnote.umd.js.map +1 -1
- package/dist/icon-data-V0Xqv-wX.js +255 -0
- package/dist/icon-data-V0Xqv-wX.js.map +1 -0
- package/package.json +12 -3
- package/types/index.d.ts +8 -0
- package/src/js/Context.js +0 -854
- package/src/js/core/detectLang.js +0 -98
- package/src/js/core/dom.js +0 -372
- package/src/js/core/env.js +0 -38
- package/src/js/core/key.js +0 -66
- package/src/js/core/lists.js +0 -121
- package/src/js/core/markdown.js +0 -695
- package/src/js/core/range.js +0 -194
- package/src/js/core/sanitise.js +0 -304
- package/src/js/editing/History.js +0 -266
- package/src/js/editing/Style.js +0 -812
- package/src/js/editing/Table.js +0 -105
- package/src/js/editing/Typing.js +0 -397
- package/src/js/index.js +0 -193
- package/src/js/index.umd.js +0 -17
- package/src/js/module/AutoSaveRestore.js +0 -125
- package/src/js/module/BaseDialog.js +0 -133
- package/src/js/module/BaseMediaTooltip.js +0 -142
- package/src/js/module/BaseResizer.js +0 -322
- package/src/js/module/BubbleToolbar.js +0 -483
- package/src/js/module/Buttons.js +0 -399
- package/src/js/module/Clipboard.js +0 -579
- package/src/js/module/CodeTooltip.js +0 -493
- package/src/js/module/Codeview.js +0 -125
- package/src/js/module/ContextMenu.js +0 -621
- package/src/js/module/Editor.js +0 -747
- package/src/js/module/EmojiDialog.js +0 -254
- package/src/js/module/FindReplace.js +0 -512
- package/src/js/module/Fullscreen.js +0 -80
- package/src/js/module/IconDialog.js +0 -618
- package/src/js/module/ImageCropOverlay.js +0 -586
- package/src/js/module/ImageDialog.js +0 -193
- package/src/js/module/ImageResizer.js +0 -42
- package/src/js/module/ImageTooltip.js +0 -285
- package/src/js/module/LinkDialog.js +0 -145
- package/src/js/module/LinkTooltip.js +0 -250
- package/src/js/module/MarkdownShortcuts.js +0 -250
- package/src/js/module/Mention.js +0 -365
- package/src/js/module/Placeholder.js +0 -51
- package/src/js/module/ShortcutsDialog.js +0 -111
- package/src/js/module/SlashMenu.js +0 -376
- package/src/js/module/Statusbar.js +0 -246
- package/src/js/module/TableTooltip.js +0 -1392
- package/src/js/module/Toolbar.js +0 -855
- package/src/js/module/VideoDialog.js +0 -193
- package/src/js/module/VideoResizer.js +0 -66
- package/src/js/module/VideoTooltip.js +0 -248
- package/src/js/module/emoji-data.js +0 -496
- package/src/js/module/table-grid.js +0 -102
- package/src/js/module/table-icons.js +0 -33
- package/src/js/renderer.js +0 -120
- package/src/js/settings.js +0 -214
- package/src/styles/_variables.scss +0 -48
- package/src/styles/autumnnote.scss +0 -2877
|
@@ -1,322 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* BaseResizer.js — Shared drag-to-resize overlay for selectable embeds.
|
|
3
|
-
*
|
|
4
|
-
* ImageResizer and VideoResizer were ~28% duplicate: identical overlay
|
|
5
|
-
* construction, selection tracking, scroll/resize repositioning and drag maths,
|
|
6
|
-
* differing only in what counts as a target and how the new size is applied.
|
|
7
|
-
* Subclasses now supply just those differences via the hooks below.
|
|
8
|
-
*
|
|
9
|
-
* Mirrors the existing BaseDialog pattern used by the dialog modules.
|
|
10
|
-
*/
|
|
11
|
-
|
|
12
|
-
import { on } from '../core/dom.js';
|
|
13
|
-
|
|
14
|
-
/**
|
|
15
|
-
* Eight handle positions. 'pos' is used as CSS class suffix and to determine
|
|
16
|
-
* which axis/direction is being dragged.
|
|
17
|
-
*
|
|
18
|
-
* Pos length 2 → corner handle → maintain aspect ratio.
|
|
19
|
-
* Pos length 1 → edge handle → single-axis resize.
|
|
20
|
-
*/
|
|
21
|
-
const HANDLE_DEFS = [
|
|
22
|
-
{ pos: 'nw', cursor: 'nw-resize' },
|
|
23
|
-
{ pos: 'n', cursor: 'n-resize' },
|
|
24
|
-
{ pos: 'ne', cursor: 'ne-resize' },
|
|
25
|
-
{ pos: 'e', cursor: 'e-resize' },
|
|
26
|
-
{ pos: 'se', cursor: 'se-resize' },
|
|
27
|
-
{ pos: 's', cursor: 's-resize' },
|
|
28
|
-
{ pos: 'sw', cursor: 'sw-resize' },
|
|
29
|
-
{ pos: 'w', cursor: 'w-resize' },
|
|
30
|
-
];
|
|
31
|
-
|
|
32
|
-
export class BaseResizer {
|
|
33
|
-
/** @param {import('../Context.js').Context} context */
|
|
34
|
-
constructor(context) {
|
|
35
|
-
this.context = context;
|
|
36
|
-
/** @type {HTMLElement|null} Currently selected element */
|
|
37
|
-
this._active = null;
|
|
38
|
-
/** @type {HTMLElement|null} */
|
|
39
|
-
this._overlay = null;
|
|
40
|
-
this._disposers = [];
|
|
41
|
-
this._positionRaf = null;
|
|
42
|
-
/** @type {{l:number,t:number,w:number,h:number}|null} Last written overlay box */
|
|
43
|
-
this._lastOverlayPos = null;
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
// ---------------------------------------------------------------------------
|
|
47
|
-
// Subclass hooks
|
|
48
|
-
// ---------------------------------------------------------------------------
|
|
49
|
-
|
|
50
|
-
/** CSS class for the overlay element. @returns {string} */
|
|
51
|
-
get _overlayClass() { return 'an-resizer'; }
|
|
52
|
-
|
|
53
|
-
/** CSS class applied to the selected element. @returns {string} */
|
|
54
|
-
get _selectedClass() { return 'an-selected'; }
|
|
55
|
-
|
|
56
|
-
/**
|
|
57
|
-
* Resolves an event target to a resizable element.
|
|
58
|
-
* @param {EventTarget|null} _el
|
|
59
|
-
* @returns {HTMLElement|null}
|
|
60
|
-
*/
|
|
61
|
-
_findTarget(_el) { return null; }
|
|
62
|
-
|
|
63
|
-
/**
|
|
64
|
-
* Natural starting dimensions of the target, used as the drag baseline.
|
|
65
|
-
* @param {HTMLElement} _target
|
|
66
|
-
* @returns {{ w: number, h: number }}
|
|
67
|
-
*/
|
|
68
|
-
_getStartSize(_target) { return { w: 0, h: 0 }; }
|
|
69
|
-
|
|
70
|
-
/** Smallest allowed dimensions. @returns {{ minW: number, minH: number }} */
|
|
71
|
-
_getMinSize() { return { minW: 20, minH: 20 }; }
|
|
72
|
-
|
|
73
|
-
/**
|
|
74
|
-
* Writes the new size to the target (and any inner embed).
|
|
75
|
-
* @param {HTMLElement} _target
|
|
76
|
-
* @param {number} _w
|
|
77
|
-
* @param {number} _h
|
|
78
|
-
*/
|
|
79
|
-
_applySize(_target, _w, _h) {}
|
|
80
|
-
|
|
81
|
-
/**
|
|
82
|
-
* Additional listeners a subclass needs; the returned disposers are torn down
|
|
83
|
-
* with the rest in destroy().
|
|
84
|
-
* @returns {Array<() => void>}
|
|
85
|
-
*/
|
|
86
|
-
_extraListeners() { return []; }
|
|
87
|
-
|
|
88
|
-
// ---------------------------------------------------------------------------
|
|
89
|
-
// Lifecycle
|
|
90
|
-
// ---------------------------------------------------------------------------
|
|
91
|
-
|
|
92
|
-
initialize() {
|
|
93
|
-
this._overlay = this._buildOverlay();
|
|
94
|
-
const container = this.context.layoutInfo.editable.closest('.an-container') || document.body;
|
|
95
|
-
container.appendChild(this._overlay);
|
|
96
|
-
this._container = container;
|
|
97
|
-
|
|
98
|
-
const editable = this.context.layoutInfo.editable;
|
|
99
|
-
|
|
100
|
-
// Debounce window resize — _updateOverlayPosition already has rAF gating but
|
|
101
|
-
// every call cancels + re-schedules it; a debounce reduces that churn.
|
|
102
|
-
let resizeDebounce = null;
|
|
103
|
-
const onWindowResize = () => {
|
|
104
|
-
clearTimeout(resizeDebounce);
|
|
105
|
-
resizeDebounce = setTimeout(() => this._updateOverlayPosition(), 100);
|
|
106
|
-
};
|
|
107
|
-
|
|
108
|
-
this._disposers.push(
|
|
109
|
-
on(editable, 'click', (e) => this._onEditorClick(e)),
|
|
110
|
-
// Also select on right-click so the highlight shows before the context menu
|
|
111
|
-
on(editable, 'contextmenu', (e) => {
|
|
112
|
-
if (this.context.layoutInfo.container.classList.contains('an-disabled')) return;
|
|
113
|
-
const target = this._findTarget(e.target);
|
|
114
|
-
if (target) this._select(target);
|
|
115
|
-
}),
|
|
116
|
-
on(document, 'click', (e) => this._onDocClick(e)),
|
|
117
|
-
on(globalThis, 'scroll', () => this._updateOverlayPosition(), { passive: true }),
|
|
118
|
-
on(globalThis, 'resize', onWindowResize, { passive: true }),
|
|
119
|
-
on(editable, 'scroll', () => this._updateOverlayPosition(), { passive: true }),
|
|
120
|
-
...this._extraListeners(),
|
|
121
|
-
);
|
|
122
|
-
|
|
123
|
-
return this;
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
destroy() {
|
|
127
|
-
this._disposers.forEach((d) => d());
|
|
128
|
-
this._disposers = [];
|
|
129
|
-
if (this._dragDisposers) {
|
|
130
|
-
this._dragDisposers.forEach((d) => d());
|
|
131
|
-
this._dragDisposers = null;
|
|
132
|
-
}
|
|
133
|
-
if (this._positionRaf) {
|
|
134
|
-
cancelAnimationFrame(this._positionRaf);
|
|
135
|
-
this._positionRaf = null;
|
|
136
|
-
}
|
|
137
|
-
this._deselect();
|
|
138
|
-
this._overlay?.remove();
|
|
139
|
-
this._overlay = null;
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
// ---------------------------------------------------------------------------
|
|
143
|
-
// Public API used by other modules
|
|
144
|
-
// ---------------------------------------------------------------------------
|
|
145
|
-
|
|
146
|
-
/** Re-sync overlay position (call after external size changes). */
|
|
147
|
-
updateOverlay() {
|
|
148
|
-
this._updateOverlayPosition();
|
|
149
|
-
}
|
|
150
|
-
|
|
151
|
-
/** Programmatically clear the current selection. */
|
|
152
|
-
deselect() {
|
|
153
|
-
this._deselect();
|
|
154
|
-
}
|
|
155
|
-
|
|
156
|
-
// ---------------------------------------------------------------------------
|
|
157
|
-
// Internal
|
|
158
|
-
// ---------------------------------------------------------------------------
|
|
159
|
-
|
|
160
|
-
_buildOverlay() {
|
|
161
|
-
const overlay = document.createElement('div');
|
|
162
|
-
overlay.className = this._overlayClass;
|
|
163
|
-
overlay.style.display = 'none';
|
|
164
|
-
|
|
165
|
-
HANDLE_DEFS.forEach(({ pos }) => {
|
|
166
|
-
const h = document.createElement('div');
|
|
167
|
-
h.className = `an-resize-handle an-resize-${pos}`;
|
|
168
|
-
h.dataset.handle = pos;
|
|
169
|
-
// Attach handle listeners here so they're torn down in destroy() via _disposers
|
|
170
|
-
this._disposers.push(
|
|
171
|
-
// Pointer events rather than mouse events, so the same code path serves
|
|
172
|
-
// mouse, touch and pen. The handles also set `touch-action: none` in
|
|
173
|
-
// CSS — without it a touch drag is claimed by the browser as a scroll
|
|
174
|
-
// gesture and the pointer stream is cancelled before it starts.
|
|
175
|
-
on(h, 'pointerdown', (e) => {
|
|
176
|
-
e.preventDefault();
|
|
177
|
-
e.stopPropagation();
|
|
178
|
-
this._startResize(e, pos);
|
|
179
|
-
}),
|
|
180
|
-
);
|
|
181
|
-
overlay.appendChild(h);
|
|
182
|
-
});
|
|
183
|
-
|
|
184
|
-
return overlay;
|
|
185
|
-
}
|
|
186
|
-
|
|
187
|
-
_onEditorClick(e) {
|
|
188
|
-
if (this.context.layoutInfo.container.classList.contains('an-disabled')) return;
|
|
189
|
-
const target = this._findTarget(e.target);
|
|
190
|
-
if (target) {
|
|
191
|
-
// Prevent the browser from dropping the text selection / showing its own
|
|
192
|
-
// native resize affordance.
|
|
193
|
-
e.preventDefault();
|
|
194
|
-
this._select(target);
|
|
195
|
-
}
|
|
196
|
-
}
|
|
197
|
-
|
|
198
|
-
_onDocClick(e) {
|
|
199
|
-
if (!this._active) return;
|
|
200
|
-
if (this._active.contains(e.target)) return;
|
|
201
|
-
if (this._overlay?.contains(e.target)) return;
|
|
202
|
-
// Don't deselect while interacting with the context menu
|
|
203
|
-
if (e.target.closest?.('.an-contextmenu')) return;
|
|
204
|
-
this._deselect();
|
|
205
|
-
}
|
|
206
|
-
|
|
207
|
-
_select(target) {
|
|
208
|
-
if (this._active && this._active !== target) {
|
|
209
|
-
this._active.classList.remove(this._selectedClass);
|
|
210
|
-
}
|
|
211
|
-
this._active = target;
|
|
212
|
-
this._lastOverlayPos = null; // invalidate position cache on new selection
|
|
213
|
-
target.classList.add(this._selectedClass);
|
|
214
|
-
this._updateOverlayPosition();
|
|
215
|
-
this._overlay.style.display = 'block';
|
|
216
|
-
}
|
|
217
|
-
|
|
218
|
-
_deselect() {
|
|
219
|
-
if (this._active) {
|
|
220
|
-
this._active.classList.remove(this._selectedClass);
|
|
221
|
-
this._active = null;
|
|
222
|
-
}
|
|
223
|
-
if (this._overlay) this._overlay.style.display = 'none';
|
|
224
|
-
}
|
|
225
|
-
|
|
226
|
-
_updateOverlayPosition() {
|
|
227
|
-
if (this._positionRaf) cancelAnimationFrame(this._positionRaf);
|
|
228
|
-
this._positionRaf = requestAnimationFrame(() => {
|
|
229
|
-
this._positionRaf = null;
|
|
230
|
-
this._updateOverlayPositionNow();
|
|
231
|
-
});
|
|
232
|
-
}
|
|
233
|
-
|
|
234
|
-
_updateOverlayPositionNow() {
|
|
235
|
-
if (!this._active || !this._overlay) return;
|
|
236
|
-
const offsetParent = this._overlay.offsetParent || this._container;
|
|
237
|
-
const containerRect = offsetParent.getBoundingClientRect();
|
|
238
|
-
const rect = this._active.getBoundingClientRect();
|
|
239
|
-
|
|
240
|
-
// Skip DOM writes when position hasn't changed (common during non-scroll rAF ticks)
|
|
241
|
-
const p = this._lastOverlayPos;
|
|
242
|
-
if (p?.l === rect.left && p.t === rect.top && p.w === rect.width && p.h === rect.height) return;
|
|
243
|
-
this._lastOverlayPos = { l: rect.left, t: rect.top, w: rect.width, h: rect.height };
|
|
244
|
-
|
|
245
|
-
const left = rect.left - containerRect.left + offsetParent.scrollLeft;
|
|
246
|
-
const top = rect.top - containerRect.top + offsetParent.scrollTop;
|
|
247
|
-
this._overlay.style.left = `${left}px`;
|
|
248
|
-
this._overlay.style.top = `${top}px`;
|
|
249
|
-
this._overlay.style.width = `${rect.width}px`;
|
|
250
|
-
this._overlay.style.height = `${rect.height}px`;
|
|
251
|
-
}
|
|
252
|
-
|
|
253
|
-
_startResize(e, pos) {
|
|
254
|
-
const target = this._active;
|
|
255
|
-
if (!target) return;
|
|
256
|
-
|
|
257
|
-
const startX = e.clientX;
|
|
258
|
-
const startY = e.clientY;
|
|
259
|
-
const { w: startW, h: startH } = this._getStartSize(target);
|
|
260
|
-
const { minW, minH } = this._getMinSize();
|
|
261
|
-
const aspectRatio = startW / (startH || 1);
|
|
262
|
-
const isCorner = pos.length === 2; // 'nw','ne','se','sw'
|
|
263
|
-
|
|
264
|
-
const editable = this.context.layoutInfo.editable;
|
|
265
|
-
let raf = null; // rAF handle — ensures at most one write per paint frame
|
|
266
|
-
|
|
267
|
-
const onMove = (me) => {
|
|
268
|
-
if (raf !== null) return; // frame already pending, discard this event
|
|
269
|
-
const clientX = me.clientX;
|
|
270
|
-
const clientY = me.clientY;
|
|
271
|
-
raf = requestAnimationFrame(() => {
|
|
272
|
-
raf = null;
|
|
273
|
-
const dx = clientX - startX;
|
|
274
|
-
const dy = clientY - startY;
|
|
275
|
-
const maxW = editable.clientWidth || Infinity;
|
|
276
|
-
let newW = startW;
|
|
277
|
-
let newH = startH;
|
|
278
|
-
|
|
279
|
-
if (pos.includes('e')) newW = Math.max(minW, startW + dx);
|
|
280
|
-
if (pos.includes('w')) newW = Math.max(minW, startW - dx);
|
|
281
|
-
if (pos.includes('s')) newH = Math.max(minH, startH + dy);
|
|
282
|
-
if (pos.includes('n')) newH = Math.max(minH, startH - dy);
|
|
283
|
-
|
|
284
|
-
newW = Math.min(newW, maxW);
|
|
285
|
-
|
|
286
|
-
if (isCorner) {
|
|
287
|
-
if (Math.abs(dx) >= Math.abs(dy)) {
|
|
288
|
-
newH = Math.max(minH, Math.round(newW / aspectRatio));
|
|
289
|
-
} else {
|
|
290
|
-
newW = Math.min(Math.max(minW, Math.round(newH * aspectRatio)), maxW);
|
|
291
|
-
newH = Math.max(minH, Math.round(newW / aspectRatio));
|
|
292
|
-
}
|
|
293
|
-
}
|
|
294
|
-
|
|
295
|
-
this._applySize(target, newW, newH);
|
|
296
|
-
this._updateOverlayPosition();
|
|
297
|
-
});
|
|
298
|
-
};
|
|
299
|
-
|
|
300
|
-
const stop = () => {
|
|
301
|
-
document.removeEventListener('pointermove', onMove);
|
|
302
|
-
document.removeEventListener('pointerup', onUp);
|
|
303
|
-
document.removeEventListener('pointercancel', onUp);
|
|
304
|
-
};
|
|
305
|
-
|
|
306
|
-
const onUp = () => {
|
|
307
|
-
if (raf !== null) { cancelAnimationFrame(raf); raf = null; }
|
|
308
|
-
stop();
|
|
309
|
-
this._dragDisposers = null;
|
|
310
|
-
this.context.invoke('editor.afterCommand');
|
|
311
|
-
};
|
|
312
|
-
|
|
313
|
-
document.addEventListener('pointermove', onMove);
|
|
314
|
-
document.addEventListener('pointerup', onUp);
|
|
315
|
-
// A touch drag interrupted by the system (incoming call, gesture takeover)
|
|
316
|
-
// ends with pointercancel and no pointerup, which would otherwise leave the
|
|
317
|
-
// move listener attached for the rest of the session.
|
|
318
|
-
document.addEventListener('pointercancel', onUp);
|
|
319
|
-
// Track these so destroy() can clean them up if called during an active drag
|
|
320
|
-
this._dragDisposers = [stop];
|
|
321
|
-
}
|
|
322
|
-
}
|