@threadlabs/looma 0.29.3 → 0.29.4
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/mobile-dock.d.ts +29 -0
- package/package.json +1 -1
- package/vue/editor/index.js +51 -13
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import type { ViewportRect } from "./viewport.js";
|
|
2
|
+
/** The widest viewport, in CSS pixels, that gets the editing dock; the slash and mention menus use the same width. */
|
|
3
|
+
export declare const LOOMA_MOBILE_DOCK_MAX_WIDTH = 767;
|
|
4
|
+
/** Whether a viewport this wide gets the editing dock rather than floating tools. */
|
|
5
|
+
export declare const usesMobileDock: (viewportWidth: number) => boolean;
|
|
6
|
+
/**
|
|
7
|
+
* Where the dock sits: across the visual viewport, against its bottom edge, so an on-screen keyboard
|
|
8
|
+
* pushes it up. It never rises above the viewport's top.
|
|
9
|
+
*/
|
|
10
|
+
export declare function mobileDockPlacement(viewport: ViewportRect, dockHeight: number): {
|
|
11
|
+
left: number;
|
|
12
|
+
top: number;
|
|
13
|
+
width: number;
|
|
14
|
+
};
|
|
15
|
+
export type LoomaMobileDockMode = "formatting" | "table";
|
|
16
|
+
/**
|
|
17
|
+
* Which controls the dock shows. A table holding the selection shows its controls, until the author
|
|
18
|
+
* goes back to formatting; that choice lasts until no table is active.
|
|
19
|
+
*
|
|
20
|
+
* @ownership The host reports table activity and renders the mode; this owns the choice.
|
|
21
|
+
*/
|
|
22
|
+
export interface LoomaMobileDock {
|
|
23
|
+
readonly mode: LoomaMobileDockMode;
|
|
24
|
+
tableActive(): void;
|
|
25
|
+
showFormatting(): void;
|
|
26
|
+
tableInactive(): void;
|
|
27
|
+
}
|
|
28
|
+
/** Calls `onChange` with the new mode whenever it changes. */
|
|
29
|
+
export declare function createMobileDock(onChange: (mode: LoomaMobileDockMode) => void): LoomaMobileDock;
|
package/package.json
CHANGED
package/vue/editor/index.js
CHANGED
|
@@ -1810,6 +1810,45 @@ function selectionActionDetail(state, id) {
|
|
|
1810
1810
|
after: doc.textBetween(to, Math.min(doc.content.size, to + CONTEXT), "\n")
|
|
1811
1811
|
};
|
|
1812
1812
|
}
|
|
1813
|
+
/** Whether a viewport this wide gets the editing dock rather than floating tools. */
|
|
1814
|
+
var usesMobileDock = (viewportWidth) => viewportWidth <= 767;
|
|
1815
|
+
/**
|
|
1816
|
+
* Where the dock sits: across the visual viewport, against its bottom edge, so an on-screen keyboard
|
|
1817
|
+
* pushes it up. It never rises above the viewport's top.
|
|
1818
|
+
*/
|
|
1819
|
+
function mobileDockPlacement(viewport, dockHeight) {
|
|
1820
|
+
return {
|
|
1821
|
+
left: viewport.left,
|
|
1822
|
+
top: Math.max(viewport.top, viewport.bottom - dockHeight),
|
|
1823
|
+
width: viewport.width
|
|
1824
|
+
};
|
|
1825
|
+
}
|
|
1826
|
+
/** Calls `onChange` with the new mode whenever it changes. */
|
|
1827
|
+
function createMobileDock(onChange) {
|
|
1828
|
+
let mode = "formatting";
|
|
1829
|
+
let formattingChosen = false;
|
|
1830
|
+
const set = (next) => {
|
|
1831
|
+
if (next === mode) return;
|
|
1832
|
+
mode = next;
|
|
1833
|
+
onChange(mode);
|
|
1834
|
+
};
|
|
1835
|
+
return {
|
|
1836
|
+
get mode() {
|
|
1837
|
+
return mode;
|
|
1838
|
+
},
|
|
1839
|
+
tableActive() {
|
|
1840
|
+
if (!formattingChosen) set("table");
|
|
1841
|
+
},
|
|
1842
|
+
showFormatting() {
|
|
1843
|
+
formattingChosen = true;
|
|
1844
|
+
set("formatting");
|
|
1845
|
+
},
|
|
1846
|
+
tableInactive() {
|
|
1847
|
+
formattingChosen = false;
|
|
1848
|
+
set("formatting");
|
|
1849
|
+
}
|
|
1850
|
+
};
|
|
1851
|
+
}
|
|
1813
1852
|
//#endregion
|
|
1814
1853
|
//#region src/editor/extensions/relative-links.ts
|
|
1815
1854
|
/** Keep other origins and non-web schemes intact; same-origin links retain path, query, and fragment. */
|
|
@@ -3508,7 +3547,7 @@ var LoomaEditor = defineComponent({
|
|
|
3508
3547
|
});
|
|
3509
3548
|
const tablePickerOpen = ref(false);
|
|
3510
3549
|
const mobileToolbarStyle = ref({});
|
|
3511
|
-
const mobile = ref(typeof window !== "undefined" && window.innerWidth
|
|
3550
|
+
const mobile = ref(typeof window !== "undefined" && usesMobileDock(window.innerWidth));
|
|
3512
3551
|
const editorFocused = ref(false);
|
|
3513
3552
|
let formatting;
|
|
3514
3553
|
let formattingPopup = null;
|
|
@@ -3520,10 +3559,12 @@ var LoomaEditor = defineComponent({
|
|
|
3520
3559
|
const formattingActive = () => formatting?.active() ?? false;
|
|
3521
3560
|
const editorStateVersion = ref(0);
|
|
3522
3561
|
const mobileToolbarMode = ref("formatting");
|
|
3562
|
+
const mobileDock = createMobileDock((mode) => {
|
|
3563
|
+
mobileToolbarMode.value = mode;
|
|
3564
|
+
});
|
|
3523
3565
|
let dragLeaveTimer = null;
|
|
3524
3566
|
let tableResizeActive = false;
|
|
3525
3567
|
let tableInteractionActive = false;
|
|
3526
|
-
let mobileTableControlsDismissed = false;
|
|
3527
3568
|
let hoveredTableCell = null;
|
|
3528
3569
|
let overlayTableElement = null;
|
|
3529
3570
|
let tablePointerFrame = null;
|
|
@@ -3993,22 +4034,20 @@ var LoomaEditor = defineComponent({
|
|
|
3993
4034
|
tableUi.geometry = null;
|
|
3994
4035
|
tableUi.capabilities = { ...EMPTY_CAPABILITIES };
|
|
3995
4036
|
overlayTableElement = null;
|
|
3996
|
-
|
|
3997
|
-
mobileToolbarMode.value = "formatting";
|
|
4037
|
+
mobileDock.tableInactive();
|
|
3998
4038
|
};
|
|
3999
4039
|
const updateMobileViewport = () => {
|
|
4000
|
-
mobile.value = window.innerWidth
|
|
4040
|
+
mobile.value = usesMobileDock(window.innerWidth);
|
|
4001
4041
|
if (!mobile.value) {
|
|
4002
4042
|
mobileToolbarStyle.value = {};
|
|
4003
4043
|
return;
|
|
4004
4044
|
}
|
|
4005
4045
|
nextTick(() => {
|
|
4006
|
-
const
|
|
4007
|
-
const toolbarHeight = mobileToolbarShell.value?.getBoundingClientRect().height || 56;
|
|
4046
|
+
const placement = mobileDockPlacement(getVisualViewportRect(window), mobileToolbarShell.value?.getBoundingClientRect().height || 56);
|
|
4008
4047
|
mobileToolbarStyle.value = {
|
|
4009
|
-
left: `${
|
|
4010
|
-
top: `${
|
|
4011
|
-
width: `${
|
|
4048
|
+
left: `${placement.left}px`,
|
|
4049
|
+
top: `${placement.top}px`,
|
|
4050
|
+
width: `${placement.width}px`
|
|
4012
4051
|
};
|
|
4013
4052
|
});
|
|
4014
4053
|
};
|
|
@@ -4098,7 +4137,7 @@ var LoomaEditor = defineComponent({
|
|
|
4098
4137
|
}
|
|
4099
4138
|
const selectedTableIsActive = state.active && selectedTable === table;
|
|
4100
4139
|
overlayTableElement = table;
|
|
4101
|
-
if (selectedTableIsActive
|
|
4140
|
+
if (selectedTableIsActive) mobileDock.tableActive();
|
|
4102
4141
|
const rect = table.getBoundingClientRect();
|
|
4103
4142
|
const maxToolbarWidth = Math.min(420, window.innerWidth - 24);
|
|
4104
4143
|
const toolbarLeft = Math.min(Math.max(12, rect.left + (rect.width - maxToolbarWidth) / 2), Math.max(12, window.innerWidth - maxToolbarWidth - 12));
|
|
@@ -4853,8 +4892,7 @@ var LoomaEditor = defineComponent({
|
|
|
4853
4892
|
type: "button",
|
|
4854
4893
|
"aria-label": "Formatting tools",
|
|
4855
4894
|
onClick: () => {
|
|
4856
|
-
|
|
4857
|
-
mobileToolbarMode.value = "formatting";
|
|
4895
|
+
mobileDock.showFormatting();
|
|
4858
4896
|
editor.value?.commands.focus();
|
|
4859
4897
|
nextTick(updateMobileViewport);
|
|
4860
4898
|
}
|