@threadlabs/looma 0.28.12 → 0.28.13
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/editor/formatting-selection.d.ts +49 -0
- package/package.json +1 -1
- package/vue/editor/index.js +108 -65
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import type { Editor } from "@tiptap/core";
|
|
2
|
+
import { TextSelection, type Selection } from "@tiptap/pm/state";
|
|
3
|
+
export interface LoomaFormattingSelectionOptions {
|
|
4
|
+
editor: Editor;
|
|
5
|
+
/** Whether a press held on the text may open the tools: floating tools, an editable document, no resize in progress. */
|
|
6
|
+
canHold: () => boolean;
|
|
7
|
+
/** Whether a slash or mention menu is open, which a completed hold leaves alone. */
|
|
8
|
+
menuOpen: () => boolean;
|
|
9
|
+
/** Whether something other than a selection, such as a range action at the caret, shows the tools. */
|
|
10
|
+
shownAtCaret: () => boolean;
|
|
11
|
+
/** Opens the tools at the caret a press was held on. */
|
|
12
|
+
onHold: (selection: TextSelection) => void;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Which selection the editor's floating formatting tools belong to: a text selection, a caret the
|
|
16
|
+
* reader pressed and held, never one the reader dismissed with Escape.
|
|
17
|
+
*
|
|
18
|
+
* @ownership The host owns the tools' surface and the document listeners that feed `press`; this
|
|
19
|
+
* owns the dismissed and held selections and the hold gesture's timer.
|
|
20
|
+
* @lifecycle `destroy()` cancels a pending hold.
|
|
21
|
+
*/
|
|
22
|
+
export interface LoomaFormattingSelection {
|
|
23
|
+
/** Whether the current selection shows the tools. */
|
|
24
|
+
active(): boolean;
|
|
25
|
+
/** Whether `selection` is the one the reader dismissed. */
|
|
26
|
+
dismissed(selection: Selection): boolean;
|
|
27
|
+
/**
|
|
28
|
+
* Hides the tools for the current selection, or for `selection`, until the reader selects again.
|
|
29
|
+
* Without an argument only a text or whole-document selection is remembered.
|
|
30
|
+
*/
|
|
31
|
+
dismiss(selection?: Selection | null): void;
|
|
32
|
+
/** Forgets a dismissal, as when the reader clicks a link. */
|
|
33
|
+
undismiss(): void;
|
|
34
|
+
/** Forgets a held caret. */
|
|
35
|
+
release(): void;
|
|
36
|
+
/** Forgets a dismissed or held selection that no longer matches the editor's. */
|
|
37
|
+
selectionChanged(): void;
|
|
38
|
+
/** Feeds the hold gesture: a still press for half a second on the text opens the tools at its caret. */
|
|
39
|
+
readonly press: {
|
|
40
|
+
down(event: PointerEvent): void;
|
|
41
|
+
move(event: PointerEvent): void;
|
|
42
|
+
end(event: PointerEvent): void;
|
|
43
|
+
cancel(): void;
|
|
44
|
+
/** A viewport change after the press began cancels it; the shared pass may report one from before. */
|
|
45
|
+
viewportChanged(event?: Event): void;
|
|
46
|
+
};
|
|
47
|
+
destroy(): void;
|
|
48
|
+
}
|
|
49
|
+
export declare function createFormattingSelection(options: LoomaFormattingSelectionOptions): LoomaFormattingSelection;
|
package/package.json
CHANGED
package/vue/editor/index.js
CHANGED
|
@@ -1131,6 +1131,76 @@ function runBlockAction(editor, action) {
|
|
|
1131
1131
|
return true;
|
|
1132
1132
|
}
|
|
1133
1133
|
//#endregion
|
|
1134
|
+
//#region src/editor/formatting-selection.ts
|
|
1135
|
+
var HOLD_MS = 500;
|
|
1136
|
+
var HOLD_SLOP_PX = 8;
|
|
1137
|
+
function createFormattingSelection(options) {
|
|
1138
|
+
const { editor } = options;
|
|
1139
|
+
let dismissedSelection = null;
|
|
1140
|
+
let heldSelection = null;
|
|
1141
|
+
let held = null;
|
|
1142
|
+
let timer;
|
|
1143
|
+
const cancel = () => {
|
|
1144
|
+
clearTimeout(timer);
|
|
1145
|
+
timer = void 0;
|
|
1146
|
+
held = null;
|
|
1147
|
+
};
|
|
1148
|
+
return {
|
|
1149
|
+
active() {
|
|
1150
|
+
const selection = editor.state.selection;
|
|
1151
|
+
return (selection instanceof TextSelection || selection instanceof AllSelection && Boolean(editor.state.doc.textContent)) && !dismissedSelection?.eq(selection) && (!selection.empty || Boolean(heldSelection?.eq(selection)) || options.shownAtCaret());
|
|
1152
|
+
},
|
|
1153
|
+
dismissed: (selection) => Boolean(dismissedSelection?.eq(selection)),
|
|
1154
|
+
dismiss(selection) {
|
|
1155
|
+
const current = editor.state.selection;
|
|
1156
|
+
dismissedSelection = selection !== void 0 ? selection : current instanceof TextSelection || current instanceof AllSelection ? current : null;
|
|
1157
|
+
heldSelection = null;
|
|
1158
|
+
},
|
|
1159
|
+
undismiss() {
|
|
1160
|
+
dismissedSelection = null;
|
|
1161
|
+
},
|
|
1162
|
+
release() {
|
|
1163
|
+
heldSelection = null;
|
|
1164
|
+
},
|
|
1165
|
+
selectionChanged() {
|
|
1166
|
+
const selection = editor.state.selection;
|
|
1167
|
+
if (!dismissedSelection?.eq(selection)) dismissedSelection = null;
|
|
1168
|
+
if (!heldSelection?.eq(selection)) heldSelection = null;
|
|
1169
|
+
},
|
|
1170
|
+
press: {
|
|
1171
|
+
down(event) {
|
|
1172
|
+
cancel();
|
|
1173
|
+
if (!options.canHold() || editor.isDestroyed || event.button !== 0 || !event.isPrimary || !(event.target instanceof Element) || !editor.view.dom.contains(event.target) || event.target.closest("button, input, select, textarea, [data-looma-image-node]")) return;
|
|
1174
|
+
held = {
|
|
1175
|
+
id: event.pointerId,
|
|
1176
|
+
x: event.clientX,
|
|
1177
|
+
y: event.clientY,
|
|
1178
|
+
time: event.timeStamp
|
|
1179
|
+
};
|
|
1180
|
+
timer = setTimeout(() => {
|
|
1181
|
+
timer = void 0;
|
|
1182
|
+
const selection = editor.state.selection;
|
|
1183
|
+
if (!held || !options.canHold() || !editor.isFocused || options.menuOpen() || !(selection instanceof TextSelection)) return;
|
|
1184
|
+
dismissedSelection = null;
|
|
1185
|
+
heldSelection = selection;
|
|
1186
|
+
options.onHold(selection);
|
|
1187
|
+
}, HOLD_MS);
|
|
1188
|
+
},
|
|
1189
|
+
move(event) {
|
|
1190
|
+
if (held?.id === event.pointerId && Math.hypot(event.clientX - held.x, event.clientY - held.y) > HOLD_SLOP_PX) cancel();
|
|
1191
|
+
},
|
|
1192
|
+
end(event) {
|
|
1193
|
+
if (held?.id === event.pointerId) cancel();
|
|
1194
|
+
},
|
|
1195
|
+
cancel,
|
|
1196
|
+
viewportChanged(event) {
|
|
1197
|
+
if (!event || !held || event.timeStamp >= held.time) cancel();
|
|
1198
|
+
}
|
|
1199
|
+
},
|
|
1200
|
+
destroy: cancel
|
|
1201
|
+
};
|
|
1202
|
+
}
|
|
1203
|
+
//#endregion
|
|
1134
1204
|
//#region src/editor/table-overlay.ts
|
|
1135
1205
|
function mapTableCells(table) {
|
|
1136
1206
|
const rows = Array.from(table.rows);
|
|
@@ -2908,29 +2978,18 @@ var LoomaEditor = defineComponent({
|
|
|
2908
2978
|
const mobileToolbarStyle = ref({});
|
|
2909
2979
|
const mobile = ref(typeof window !== "undefined" && window.innerWidth <= 767);
|
|
2910
2980
|
const editorFocused = ref(false);
|
|
2911
|
-
let
|
|
2912
|
-
let heldFormattingSelection = null;
|
|
2981
|
+
let formatting;
|
|
2913
2982
|
let formattingPopup = null;
|
|
2914
2983
|
let linkPopup = null;
|
|
2915
2984
|
let imagePopup = null;
|
|
2916
|
-
let heldPressTimer;
|
|
2917
|
-
let heldPress = null;
|
|
2918
2985
|
const floatingFormattingMode = () => props.toolbarMode !== "sticky" && !(props.toolbarMode === "popover" && props.toolbarOpen) && !mobile.value;
|
|
2919
2986
|
const formattingPickerOpen = () => linkState.value.surface === "popover" || tablePickerOpen.value || formatOpen.value;
|
|
2920
|
-
const cancelHeldPress = () => {
|
|
2921
|
-
clearTimeout(heldPressTimer);
|
|
2922
|
-
heldPressTimer = void 0;
|
|
2923
|
-
heldPress = null;
|
|
2924
|
-
};
|
|
2925
2987
|
const activeRangeActions = (instance) => {
|
|
2926
2988
|
const selection = instance.state.selection;
|
|
2927
2989
|
if (!(selection instanceof TextSelection) || !selection.empty) return [];
|
|
2928
2990
|
return props.rangeActions.filter((action) => Number.isSafeInteger(action.from) && Number.isSafeInteger(action.to) && action.from >= 0 && action.to > action.from && action.to <= instance.state.doc.content.size && action.from <= selection.from && selection.from <= action.to);
|
|
2929
2991
|
};
|
|
2930
|
-
const
|
|
2931
|
-
const selection = instance.state.selection;
|
|
2932
|
-
return (selection instanceof TextSelection || selection instanceof AllSelection && Boolean(instance.state.doc.textContent)) && !dismissedFormattingSelection?.eq(selection) && (!selection.empty || Boolean(heldFormattingSelection?.eq(selection)) || activeRangeActions(instance).length > 0);
|
|
2933
|
-
};
|
|
2992
|
+
const formattingActive = () => formatting?.active() ?? false;
|
|
2934
2993
|
const editorStateVersion = ref(0);
|
|
2935
2994
|
const mobileToolbarMode = ref("formatting");
|
|
2936
2995
|
let dragLeaveTimer = null;
|
|
@@ -3100,7 +3159,7 @@ var LoomaEditor = defineComponent({
|
|
|
3100
3159
|
window.open(href, "_blank", "noopener,noreferrer");
|
|
3101
3160
|
return true;
|
|
3102
3161
|
}
|
|
3103
|
-
|
|
3162
|
+
formatting?.undismiss();
|
|
3104
3163
|
requestAnimationFrame(() => {
|
|
3105
3164
|
if (view.isDestroyed) return;
|
|
3106
3165
|
editorStateVersion.value += 1;
|
|
@@ -3123,10 +3182,9 @@ var LoomaEditor = defineComponent({
|
|
|
3123
3182
|
onSelectionUpdate: ({ editor: instance }) => {
|
|
3124
3183
|
rememberSelection(instance);
|
|
3125
3184
|
if (floatingFormattingMode()) {
|
|
3126
|
-
|
|
3127
|
-
|
|
3128
|
-
if (!
|
|
3129
|
-
if (!formattingSelectionActive(instance)) formattingPopup?.hide();
|
|
3185
|
+
instance.state.selection;
|
|
3186
|
+
formatting?.selectionChanged();
|
|
3187
|
+
if (!formattingActive()) formattingPopup?.hide();
|
|
3130
3188
|
}
|
|
3131
3189
|
},
|
|
3132
3190
|
onUpdate: ({ editor: instance }) => {
|
|
@@ -3149,6 +3207,17 @@ var LoomaEditor = defineComponent({
|
|
|
3149
3207
|
linkState.value = engine.state;
|
|
3150
3208
|
});
|
|
3151
3209
|
linkEditing = engine;
|
|
3210
|
+
const instance = session.editor;
|
|
3211
|
+
formatting = createFormattingSelection({
|
|
3212
|
+
editor: instance,
|
|
3213
|
+
canHold: () => floatingFormattingMode() && !tableResizeActive && props.editable,
|
|
3214
|
+
menuOpen: () => slash.active || mention.active,
|
|
3215
|
+
shownAtCaret: () => activeRangeActions(instance).length > 0,
|
|
3216
|
+
onHold: (selection) => {
|
|
3217
|
+
formattingPopup?.setAnchor(() => posToDOMRect(instance.view, selection.from, selection.to));
|
|
3218
|
+
formattingPopup?.show();
|
|
3219
|
+
}
|
|
3220
|
+
});
|
|
3152
3221
|
});
|
|
3153
3222
|
const attachDocument = (element) => {
|
|
3154
3223
|
if (element instanceof HTMLElement) session?.attach(element);
|
|
@@ -3170,7 +3239,7 @@ var LoomaEditor = defineComponent({
|
|
|
3170
3239
|
const to = selection?.to ?? current.to;
|
|
3171
3240
|
linkEditing?.open(from, to, context ? "context" : "popover");
|
|
3172
3241
|
nextTick(() => {
|
|
3173
|
-
if (context) (props.toolbarMode === "contextual" && floatingFormattingMode() &&
|
|
3242
|
+
if (context) (props.toolbarMode === "contextual" && floatingFormattingMode() && formattingActive() ? formattingPopup : linkPopup)?.setAnchor(() => posToDOMRect(instance.view, instance.state.selection.from, instance.state.selection.to));
|
|
3174
3243
|
(linkState.value.mode === "url" ? linkDestinationInput() : linkFormRoot.value?.querySelector("[data-link-search]"))?.focus();
|
|
3175
3244
|
});
|
|
3176
3245
|
};
|
|
@@ -3178,8 +3247,7 @@ var LoomaEditor = defineComponent({
|
|
|
3178
3247
|
linkEditing?.close();
|
|
3179
3248
|
const range = linkState.value.range;
|
|
3180
3249
|
if (restoreFocus && range) editor.value?.chain().focus().setTextSelection(range.to).run();
|
|
3181
|
-
|
|
3182
|
-
heldFormattingSelection = null;
|
|
3250
|
+
formatting?.dismiss(editor.value?.state.selection ?? null);
|
|
3183
3251
|
linkPopup?.hide();
|
|
3184
3252
|
formattingPopup?.hide();
|
|
3185
3253
|
};
|
|
@@ -3248,8 +3316,8 @@ var LoomaEditor = defineComponent({
|
|
|
3248
3316
|
editor.value?.commands.dismissLoomaSlashMenu();
|
|
3249
3317
|
});
|
|
3250
3318
|
watch(() => props.editable, (editable) => {
|
|
3251
|
-
|
|
3252
|
-
|
|
3319
|
+
formatting?.press.cancel();
|
|
3320
|
+
formatting?.release();
|
|
3253
3321
|
editor.value?.setEditable(editable);
|
|
3254
3322
|
if (!editable) formattingPopup?.hide();
|
|
3255
3323
|
if (editor.value) imageDelivery.reset(editor.value);
|
|
@@ -3264,7 +3332,7 @@ var LoomaEditor = defineComponent({
|
|
|
3264
3332
|
formatOpen
|
|
3265
3333
|
], ([linking, table, format]) => {
|
|
3266
3334
|
if (linking || table || format || !floatingFormattingMode() || editor.value?.isFocused || formattingPopup?.element.contains(document.activeElement)) return;
|
|
3267
|
-
|
|
3335
|
+
formatting?.release();
|
|
3268
3336
|
formattingPopup?.hide();
|
|
3269
3337
|
});
|
|
3270
3338
|
watch(() => props.rangeActions, () => {
|
|
@@ -3440,12 +3508,12 @@ var LoomaEditor = defineComponent({
|
|
|
3440
3508
|
updateMobileViewport();
|
|
3441
3509
|
};
|
|
3442
3510
|
const onEditorBlur = () => {
|
|
3443
|
-
|
|
3511
|
+
formatting?.press.cancel();
|
|
3444
3512
|
queueMicrotask(updateTableUi);
|
|
3445
3513
|
updateCodeUi();
|
|
3446
3514
|
setTimeout(() => {
|
|
3447
3515
|
if (!tableInteractionActive && !editor.value?.isFocused && !mobileToolbarShell.value?.contains(document.activeElement)) editorFocused.value = false;
|
|
3448
|
-
if (!editor.value?.isFocused && !formattingPickerOpen() && !formattingPopup?.element.contains(document.activeElement))
|
|
3516
|
+
if (!editor.value?.isFocused && !formattingPickerOpen() && !formattingPopup?.element.contains(document.activeElement)) formatting?.release();
|
|
3449
3517
|
}, 0);
|
|
3450
3518
|
};
|
|
3451
3519
|
const bindEditorUi = (instance) => {
|
|
@@ -3471,15 +3539,15 @@ var LoomaEditor = defineComponent({
|
|
|
3471
3539
|
}, { immediate: true });
|
|
3472
3540
|
const onViewportChange = (event) => {
|
|
3473
3541
|
if (event?.type === "scroll" && event.target instanceof Node && (tableToolbarShell.value?.contains(event.target) || tableMenuShell.value?.contains(event.target))) return;
|
|
3474
|
-
|
|
3542
|
+
formatting?.press.viewportChanged(event);
|
|
3475
3543
|
const wasMobile = mobile.value;
|
|
3476
3544
|
if (slash.active && slash.getRect) slash.rect = slash.getRect();
|
|
3477
3545
|
if (mention.active && mention.getRect) mention.rect = mention.getRect();
|
|
3478
3546
|
updateMobileViewport();
|
|
3479
|
-
if (wasMobile !== mobile.value)
|
|
3547
|
+
if (wasMobile !== mobile.value) formatting?.release();
|
|
3480
3548
|
updateTableUi();
|
|
3481
3549
|
updateCodeUi();
|
|
3482
|
-
if (floatingFormattingMode() && editor.value && !
|
|
3550
|
+
if (floatingFormattingMode() && editor.value && !formattingActive()) formattingPopup?.hide();
|
|
3483
3551
|
tableUi.menuOpen = false;
|
|
3484
3552
|
};
|
|
3485
3553
|
let stopViewport;
|
|
@@ -3516,42 +3584,17 @@ var LoomaEditor = defineComponent({
|
|
|
3516
3584
|
}, 0);
|
|
3517
3585
|
if ((tableUi.toolbarOpen || tableUi.overlayOpen || tableUi.menuOpen) && !inElement(root.value) && !inTableUi) closeTableUi();
|
|
3518
3586
|
};
|
|
3519
|
-
const onFormattingPointerDown = (event) =>
|
|
3520
|
-
|
|
3521
|
-
|
|
3522
|
-
if (!floatingFormattingMode() || tableResizeActive || !props.editable || !instance || event.button !== 0 || !event.isPrimary || !(event.target instanceof Element) || !instance.view.dom.contains(event.target) || event.target.closest("button, input, select, textarea, [data-looma-image-node]")) return;
|
|
3523
|
-
heldPress = {
|
|
3524
|
-
id: event.pointerId,
|
|
3525
|
-
x: event.clientX,
|
|
3526
|
-
y: event.clientY,
|
|
3527
|
-
time: event.timeStamp
|
|
3528
|
-
};
|
|
3529
|
-
heldPressTimer = setTimeout(() => {
|
|
3530
|
-
heldPressTimer = void 0;
|
|
3531
|
-
const selection = instance.state.selection;
|
|
3532
|
-
if (!heldPress || !floatingFormattingMode() || tableResizeActive || !props.editable || !instance.isFocused || slash.active || mention.active || !(selection instanceof TextSelection)) return;
|
|
3533
|
-
dismissedFormattingSelection = null;
|
|
3534
|
-
heldFormattingSelection = selection;
|
|
3535
|
-
formattingPopup?.setAnchor(() => posToDOMRect(instance.view, selection.from, selection.to));
|
|
3536
|
-
formattingPopup?.show();
|
|
3537
|
-
}, 500);
|
|
3538
|
-
};
|
|
3539
|
-
const onFormattingPointerMove = (event) => {
|
|
3540
|
-
if (heldPress?.id === event.pointerId && Math.hypot(event.clientX - heldPress.x, event.clientY - heldPress.y) > 8) cancelHeldPress();
|
|
3541
|
-
};
|
|
3542
|
-
const onFormattingPointerEnd = (event) => {
|
|
3543
|
-
if (heldPress?.id === event.pointerId) cancelHeldPress();
|
|
3544
|
-
};
|
|
3587
|
+
const onFormattingPointerDown = (event) => formatting?.press.down(event);
|
|
3588
|
+
const onFormattingPointerMove = (event) => formatting?.press.move(event);
|
|
3589
|
+
const onFormattingPointerEnd = (event) => formatting?.press.end(event);
|
|
3545
3590
|
const onFormattingKeyDown = (event) => {
|
|
3546
|
-
|
|
3591
|
+
formatting?.press.cancel();
|
|
3547
3592
|
if (event.key !== "Escape" || !(event.target instanceof Node) || !(root.value?.contains(event.target) || formattingPopup?.element.contains(event.target) || linkPopup?.element.contains(event.target)) || !(formatOpen.value || formattingPopup?.isOpen() || linkPopup?.isOpen())) return false;
|
|
3548
3593
|
dismissFormatting();
|
|
3549
3594
|
return true;
|
|
3550
3595
|
};
|
|
3551
3596
|
const dismissFormatting = () => {
|
|
3552
|
-
|
|
3553
|
-
dismissedFormattingSelection = selection instanceof TextSelection || selection instanceof AllSelection ? selection : null;
|
|
3554
|
-
heldFormattingSelection = null;
|
|
3597
|
+
formatting?.dismiss();
|
|
3555
3598
|
formatOpen.value = false;
|
|
3556
3599
|
formattingPopup?.hide();
|
|
3557
3600
|
linkPopup?.hide();
|
|
@@ -3574,10 +3617,10 @@ var LoomaEditor = defineComponent({
|
|
|
3574
3617
|
editor: instance,
|
|
3575
3618
|
element,
|
|
3576
3619
|
pluginKey: "looma-text-formatting-menu",
|
|
3577
|
-
shouldShow: ({ editor: menuEditor }) => (props.toolbarMode !== "popover" || !props.toolbarOpen) && !slash.active && !mention.active && (!props.editable && (props.selectionActions.length > 0 || props.rangeActions.length > 0) || menuEditor.isFocused || formattingPopup?.element.contains(document.activeElement) || linkState.value.surface === "context" || formattingPickerOpen()) &&
|
|
3620
|
+
shouldShow: ({ editor: menuEditor }) => (props.toolbarMode !== "popover" || !props.toolbarOpen) && !slash.active && !mention.active && (!props.editable && (props.selectionActions.length > 0 || props.rangeActions.length > 0) || menuEditor.isFocused || formattingPopup?.element.contains(document.activeElement) || linkState.value.surface === "context" || formattingPickerOpen()) && formattingActive(),
|
|
3578
3621
|
boundary: () => props.toolbarMode === "contextual" ? root.value : null,
|
|
3579
3622
|
related: editorRoot,
|
|
3580
|
-
onHide: () => instance.isEditable && floatingFormattingMode() && formattingPickerOpen() &&
|
|
3623
|
+
onHide: () => instance.isEditable && floatingFormattingMode() && formattingPickerOpen() && formattingActive() ? false : void 0,
|
|
3581
3624
|
onDismiss: (reason) => reason === "escape" ? dismissFormatting() : formattingPopup?.hide()
|
|
3582
3625
|
}));
|
|
3583
3626
|
const linkSurfaceRef = surfaceRef((surface) => {
|
|
@@ -3586,7 +3629,7 @@ var LoomaEditor = defineComponent({
|
|
|
3586
3629
|
editor: instance,
|
|
3587
3630
|
element,
|
|
3588
3631
|
pluginKey: "looma-link-context-menu",
|
|
3589
|
-
shouldShow: ({ editor: menuEditor, from, to }) => from === to && menuEditor.isActive("link") && linkState.value.surface !== "popover" && !
|
|
3632
|
+
shouldShow: ({ editor: menuEditor, from, to }) => from === to && menuEditor.isActive("link") && linkState.value.surface !== "popover" && !formatting?.dismissed(menuEditor.state.selection) && Boolean(menuEditor.isFocused || linkState.value.surface === "context" || linkPopup?.element.contains(document.activeElement)) && !(props.toolbarMode === "contextual" && floatingFormattingMode() && formattingActive()),
|
|
3590
3633
|
maxWidth: () => Math.min(480, window.innerWidth - 24),
|
|
3591
3634
|
related: editorRoot,
|
|
3592
3635
|
onDismiss: (reason) => reason === "escape" ? dismissFormatting() : linkPopup?.hide()
|
|
@@ -3753,7 +3796,7 @@ var LoomaEditor = defineComponent({
|
|
|
3753
3796
|
window.removeEventListener("keyup", onLinkNavigationModifier);
|
|
3754
3797
|
window.removeEventListener("pointermove", onLinkNavigationModifier);
|
|
3755
3798
|
window.removeEventListener("blur", clearLinkNavigationModifier);
|
|
3756
|
-
|
|
3799
|
+
formatting?.destroy();
|
|
3757
3800
|
formattingPopup = null;
|
|
3758
3801
|
document.removeEventListener("pointerdown", onDocumentPointerDown, true);
|
|
3759
3802
|
document.removeEventListener("pointerdown", onFormattingPointerDown);
|
|
@@ -4183,12 +4226,12 @@ var LoomaEditor = defineComponent({
|
|
|
4183
4226
|
ref: formattingSurfaceRef,
|
|
4184
4227
|
class: "looma-editor__floating-shell looma-editor__formatting-shell",
|
|
4185
4228
|
hidden: true
|
|
4186
|
-
}, [props.toolbarMode === "contextual" ? h(Stack, { gap: "xs" }, () => [renderToolbar(instance, true), (linkState.value.surface === "context" || instance.state.selection.empty && instance.isActive("link")) && linkState.value.surface !== "popover" &&
|
|
4229
|
+
}, [props.toolbarMode === "contextual" ? h(Stack, { gap: "xs" }, () => [renderToolbar(instance, true), (linkState.value.surface === "context" || instance.state.selection.empty && instance.isActive("link")) && linkState.value.surface !== "popover" && formattingActive() ? renderLinkContextCard(instance) : null]) : renderToolbar(instance, true, props.toolbarMode === "popover")])]) : null,
|
|
4187
4230
|
instance && props.editable ? h("div", { key: "looma-link-host" }, [h("div", {
|
|
4188
4231
|
ref: linkSurfaceRef,
|
|
4189
4232
|
class: "looma-editor__floating-shell looma-editor__link-shell",
|
|
4190
4233
|
hidden: true
|
|
4191
|
-
}, [props.toolbarMode === "contextual" && floatingFormattingMode() &&
|
|
4234
|
+
}, [props.toolbarMode === "contextual" && floatingFormattingMode() && formattingActive() ? null : renderLinkContextCard(instance)])]) : null,
|
|
4192
4235
|
instance && props.editable && !mobile.value && props.toolbarMode === "popover" && props.toolbarTriggerId ? h(Popover, {
|
|
4193
4236
|
class: "looma-editor__formatting-popover",
|
|
4194
4237
|
role: "region",
|