@threadlabs/looma 0.31.1 → 0.31.2
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/components/shared/tooltip.js +7 -0
- package/components/ui-tooltip/ui-tooltip.js +4 -1
- package/editor/chunks/extensions.js +21 -0
- package/editor/table-ui.d.ts +2 -11
- package/editor/toolbar-tooltip.d.ts +1 -1
- package/package.json +1 -1
- package/vue/components.css +25 -10
- package/vue/editor/index.js +36 -38
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/** Resolve the inherited pointer-intent delay; CSS time values and millisecond numbers are accepted. */
|
|
2
|
+
export function tooltipShowDelay(element, fallback = 500) {
|
|
3
|
+
if (!element) return fallback;
|
|
4
|
+
const value = element.ownerDocument.defaultView.getComputedStyle(element).getPropertyValue("--ui-tooltip-show-delay").trim();
|
|
5
|
+
const match = /^([0-9]+(?:\.[0-9]+)?)(ms|s)?$/.exec(value);
|
|
6
|
+
return match ? Number(match[1]) * (match[2] === "s" ? 1000 : 1) : fallback;
|
|
7
|
+
}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { tooltipShowDelay } from "../shared/tooltip.js";
|
|
1
2
|
import { closeOverlay, createAnchoredSurface, createIdResolver, onOverlayOpen, openOverlay } from "../shared/overlay.js";
|
|
2
3
|
|
|
3
4
|
const warmTooltips = new WeakMap();
|
|
@@ -61,7 +62,7 @@ export function connect(host) {
|
|
|
61
62
|
showTimer = setTimeout(() => {
|
|
62
63
|
showTimer = null;
|
|
63
64
|
setOpen(true, "pointer");
|
|
64
|
-
}, warm.active > 0 || warm.until > Date.now() ? 0 : Math.max(0, Number(host.props.showDelay.value
|
|
65
|
+
}, warm.active > 0 || warm.until > Date.now() ? 0 : Math.max(0, host.props.showDelay.inputValue != null ? Number(host.props.showDelay.value) : tooltipShowDelay(element)));
|
|
65
66
|
};
|
|
66
67
|
const onLeave = () => {
|
|
67
68
|
clearShow();
|
|
@@ -134,6 +135,8 @@ export function connect(host) {
|
|
|
134
135
|
if (how === "hover") {
|
|
135
136
|
trigger.addEventListener("pointerenter", onEnter);
|
|
136
137
|
trigger.addEventListener("pointerleave", onLeave);
|
|
138
|
+
// Editor decorations can acquire their tooltip after the pointer has already entered.
|
|
139
|
+
if (trigger.matches(":hover")) onEnter({ pointerType: "mouse" });
|
|
137
140
|
}
|
|
138
141
|
trigger.addEventListener("focusin", onFocusin);
|
|
139
142
|
trigger.addEventListener("focusout", onFocusout);
|
|
@@ -11155,6 +11155,26 @@ var TableHeader = Node$1.create({
|
|
|
11155
11155
|
});
|
|
11156
11156
|
//#endregion
|
|
11157
11157
|
//#region src/editor/extensions/table-formatting.ts
|
|
11158
|
+
/** Table chrome lives outside the horizontal scroller, within the table's document block. */
|
|
11159
|
+
var LoomaTableView = class extends TableView {
|
|
11160
|
+
toolbarHost;
|
|
11161
|
+
constructor(node, cellMinWidth) {
|
|
11162
|
+
super(node, cellMinWidth);
|
|
11163
|
+
const scroller = this.dom;
|
|
11164
|
+
this.dom = document.createElement("div");
|
|
11165
|
+
this.dom.dataset.loomaTableBlock = "";
|
|
11166
|
+
this.toolbarHost = document.createElement("div");
|
|
11167
|
+
this.toolbarHost.dataset.loomaTableToolbarHost = "";
|
|
11168
|
+
this.toolbarHost.contentEditable = "false";
|
|
11169
|
+
this.dom.append(scroller, this.toolbarHost);
|
|
11170
|
+
}
|
|
11171
|
+
ignoreMutation(mutation) {
|
|
11172
|
+
return mutation.type !== "selection" && this.toolbarHost.contains(mutation.target) || super.ignoreMutation(mutation);
|
|
11173
|
+
}
|
|
11174
|
+
stopEvent(event) {
|
|
11175
|
+
return event.target instanceof globalThis.Node && this.toolbarHost.contains(event.target);
|
|
11176
|
+
}
|
|
11177
|
+
};
|
|
11158
11178
|
/**
|
|
11159
11179
|
* Looma's table behavior policy: resizable columns, stable minimum cell width,
|
|
11160
11180
|
* and no independently resizable trailing column. The narrow handle is also a
|
|
@@ -11165,6 +11185,7 @@ var TableHeader = Node$1.create({
|
|
|
11165
11185
|
*/
|
|
11166
11186
|
var LoomaTable = Table.configure({
|
|
11167
11187
|
resizable: true,
|
|
11188
|
+
View: LoomaTableView,
|
|
11168
11189
|
handleWidth: 3,
|
|
11169
11190
|
cellMinWidth: 112,
|
|
11170
11191
|
lastColumnResizable: false
|
package/editor/table-ui.d.ts
CHANGED
|
@@ -17,17 +17,8 @@ export declare const LOOMA_TABLE_CONTROLS_CLOSED: LoomaTableControls;
|
|
|
17
17
|
* with nothing selected; narrow screens use the editing dock instead of the toolbar and overlay.
|
|
18
18
|
*/
|
|
19
19
|
export declare function tableControls(state: ActiveTableUiState, selectionInTable: boolean, narrow: boolean): LoomaTableControls;
|
|
20
|
-
/**
|
|
21
|
-
|
|
22
|
-
* above the table when there is room and below it otherwise.
|
|
23
|
-
*/
|
|
24
|
-
export declare function tableToolbarPlacement(table: DOMRect, viewportWidth: number): {
|
|
25
|
-
top: string;
|
|
26
|
-
left: string;
|
|
27
|
-
maxWidth: string;
|
|
28
|
-
};
|
|
29
|
-
/** The overlay covers the table exactly. */
|
|
30
|
-
export declare const tableOverlayPlacement: (table: DOMRect) => {
|
|
20
|
+
/** Inline controls cover the table in the editor's coordinate system. */
|
|
21
|
+
export declare const tableOverlayPlacement: (table: DOMRect, editor: DOMRect) => {
|
|
31
22
|
top: string;
|
|
32
23
|
left: string;
|
|
33
24
|
width: string;
|
|
@@ -22,4 +22,4 @@ export interface LoomaToolbarTooltip {
|
|
|
22
22
|
destroy(): void;
|
|
23
23
|
}
|
|
24
24
|
/** Calls `onChange` after every state change. */
|
|
25
|
-
export declare function createToolbarTooltip(onChange: (state: LoomaToolbarTooltipState) => void): LoomaToolbarTooltip;
|
|
25
|
+
export declare function createToolbarTooltip(onChange: (state: LoomaToolbarTooltipState) => void, delay?: () => number): LoomaToolbarTooltip;
|
package/package.json
CHANGED
package/vue/components.css
CHANGED
|
@@ -10438,6 +10438,30 @@ html[data-ui-input-modality="touch"]
|
|
|
10438
10438
|
:is([data-component~="ui-editor-surface"], .ui-editor-surface) .ProseMirror[data-link-navigation] a[href] {
|
|
10439
10439
|
cursor: pointer;
|
|
10440
10440
|
}
|
|
10441
|
+
|
|
10442
|
+
/* Inline table affordances share the document's scroll chain; popups use the top layer. */
|
|
10443
|
+
.looma-editor__table-overlay-shell {
|
|
10444
|
+
position: absolute;
|
|
10445
|
+
z-index: var(--ui-editor-overlay-z-index, 299);
|
|
10446
|
+
overflow: visible;
|
|
10447
|
+
pointer-events: none;
|
|
10448
|
+
}
|
|
10449
|
+
|
|
10450
|
+
/* The toolbar follows its table, lifting inside the document scroller only when needed. */
|
|
10451
|
+
[data-looma-table-toolbar-host] { display: contents; }
|
|
10452
|
+
.looma-editor__table-toolbar-shell {
|
|
10453
|
+
position: sticky;
|
|
10454
|
+
bottom: var(--ui-space-3);
|
|
10455
|
+
z-index: var(--ui-editor-popover-z-index, 300);
|
|
10456
|
+
width: max-content;
|
|
10457
|
+
max-width: 100%;
|
|
10458
|
+
margin: var(--ui-space-3) auto 0;
|
|
10459
|
+
overflow-x: auto;
|
|
10460
|
+
}
|
|
10461
|
+
|
|
10462
|
+
.looma-editor .ProseMirror [data-looma-table-block] + p {
|
|
10463
|
+
margin-top: var(--ui-editor-table-following-gap, var(--ui-space-4));
|
|
10464
|
+
}
|
|
10441
10465
|
/**
|
|
10442
10466
|
* Looma editor styles (tokens-based).
|
|
10443
10467
|
* Tables, context menu, insert-table grid, slash menu. Use with ProseMirror/Tiptap content.
|
|
@@ -10738,7 +10762,6 @@ html[data-ui-input-modality="touch"]
|
|
|
10738
10762
|
|
|
10739
10763
|
.looma-editor__table-picker-popover,
|
|
10740
10764
|
.looma-editor__chip-popover,
|
|
10741
|
-
.looma-editor__table-toolbar-shell,
|
|
10742
10765
|
.looma-editor__table-menu-shell {
|
|
10743
10766
|
z-index: var(--ui-editor-popover-z-index, 300);
|
|
10744
10767
|
}
|
|
@@ -10768,9 +10791,7 @@ html[data-ui-input-modality="touch"]
|
|
|
10768
10791
|
outline-offset: var(--ui-focus-width);
|
|
10769
10792
|
}
|
|
10770
10793
|
|
|
10771
|
-
.looma-editor__table-
|
|
10772
|
-
.looma-editor__table-menu-shell,
|
|
10773
|
-
.looma-editor__table-overlay-shell {
|
|
10794
|
+
.looma-editor__table-menu-shell {
|
|
10774
10795
|
position: fixed;
|
|
10775
10796
|
}
|
|
10776
10797
|
|
|
@@ -10836,12 +10857,6 @@ html[data-ui-input-modality="touch"]
|
|
|
10836
10857
|
color: var(--ui-text-primary, #111827);
|
|
10837
10858
|
}
|
|
10838
10859
|
|
|
10839
|
-
.looma-editor__table-overlay-shell {
|
|
10840
|
-
z-index: var(--ui-editor-overlay-z-index, 299);
|
|
10841
|
-
overflow: visible;
|
|
10842
|
-
pointer-events: none;
|
|
10843
|
-
}
|
|
10844
|
-
|
|
10845
10860
|
.looma-editor .ProseMirror .looma-mention {
|
|
10846
10861
|
padding: 0.08em 0.28em;
|
|
10847
10862
|
color: var(--ui-editor-mention-color, var(--ui-accent-active, var(--ui-accent-solid)));
|
package/vue/editor/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { computed, defineComponent, h, nextTick, onBeforeUnmount, onMounted, onUpdated, reactive, ref, shallowRef, useId, watch } from "vue";
|
|
1
|
+
import { Teleport, computed, defineComponent, h, nextTick, onBeforeUnmount, onMounted, onUpdated, reactive, ref, shallowRef, useId, watch } from "vue";
|
|
2
2
|
import { DEFAULT_MENTION_RESULT_LIMIT, LOOMA_ICONS, createLoomaMentionExtension, createLoomaSlashCommandExtension, getActiveTableUiState, getDefaultEditorExtensions, getDefaultSlashCommands, getTableOfContentsEntries, getVisualViewportRect, handleTableAction, handleTableOverlayAction, measureTableOverlayGeometry, normalizeActiveTableColumnWidths, normalizeTableOfContentsConfig } from "@threadlabs/looma/editor";
|
|
3
3
|
import { Button, Card, EditorBlockActions, EditorChipEditor, EditorCodeLanguage, EditorFootnoteEditor, EditorImageToolbar, EditorInsertTableGrid, EditorLinkCard, EditorLinkForm, EditorMentionMenu, EditorMentionMenuItem, EditorSlashMenu, EditorSlashMenuGroup, EditorSlashMenuItem, EditorSurface, EditorTableContextMenu, EditorTableOverlay, EditorTableToolbar, EditorToolbar, IconButton, Popover, Stack, StatusMessage, Text, Tooltip } from "@threadlabs/looma/vue";
|
|
4
4
|
import { Editor, Extension, InputRule, Node as Node$1, PasteRule, getText, getTextSerializersFromSchema, isNodeSelection, mergeAttributes, nodeInputRule, posToDOMRect } from "@tiptap/core";
|
|
@@ -2291,25 +2291,10 @@ function tableControls(state, selectionInTable, narrow) {
|
|
|
2291
2291
|
capabilities: state.capabilities
|
|
2292
2292
|
};
|
|
2293
2293
|
}
|
|
2294
|
-
/**
|
|
2295
|
-
var
|
|
2296
|
-
|
|
2297
|
-
|
|
2298
|
-
* above the table when there is room and below it otherwise.
|
|
2299
|
-
*/
|
|
2300
|
-
function tableToolbarPlacement(table, viewportWidth) {
|
|
2301
|
-
const width = Math.min(420, viewportWidth - 24);
|
|
2302
|
-
const left = Math.min(Math.max(12, table.left + (table.width - width) / 2), Math.max(12, viewportWidth - width - 12));
|
|
2303
|
-
return {
|
|
2304
|
-
top: `${table.top > ROOM_ABOVE$1 ? table.top - 52 : table.bottom + 12}px`,
|
|
2305
|
-
left: `${left}px`,
|
|
2306
|
-
maxWidth: `${width}px`
|
|
2307
|
-
};
|
|
2308
|
-
}
|
|
2309
|
-
/** The overlay covers the table exactly. */
|
|
2310
|
-
var tableOverlayPlacement = (table) => ({
|
|
2311
|
-
top: `${table.top}px`,
|
|
2312
|
-
left: `${table.left}px`,
|
|
2294
|
+
/** Inline controls cover the table in the editor's coordinate system. */
|
|
2295
|
+
var tableOverlayPlacement = (table, editor) => ({
|
|
2296
|
+
top: `${table.top - editor.top}px`,
|
|
2297
|
+
left: `${table.left - editor.left}px`,
|
|
2313
2298
|
width: `${table.width}px`,
|
|
2314
2299
|
height: `${table.height}px`
|
|
2315
2300
|
});
|
|
@@ -3114,8 +3099,17 @@ function formatEditorShortcut(keys, apple) {
|
|
|
3114
3099
|
].filter(Boolean).join("+");
|
|
3115
3100
|
}
|
|
3116
3101
|
var isApplePlatform = () => typeof navigator !== "undefined" && /mac|iphone|ipad|ipod/i.test(navigator.userAgentData?.platform || navigator.platform || navigator.userAgent);
|
|
3102
|
+
//#endregion
|
|
3103
|
+
//#region src/components/shared/tooltip.js
|
|
3104
|
+
/** Resolve the inherited pointer-intent delay; CSS time values and millisecond numbers are accepted. */
|
|
3105
|
+
function tooltipShowDelay$1(element, fallback = 500) {
|
|
3106
|
+
if (!element) return fallback;
|
|
3107
|
+
const value = element.ownerDocument.defaultView.getComputedStyle(element).getPropertyValue("--ui-tooltip-show-delay").trim();
|
|
3108
|
+
const match = /^([0-9]+(?:\.[0-9]+)?)(ms|s)?$/.exec(value);
|
|
3109
|
+
return match ? Number(match[1]) * (match[2] === "s" ? 1e3 : 1) : fallback;
|
|
3110
|
+
}
|
|
3117
3111
|
/** Calls `onChange` after every state change. */
|
|
3118
|
-
function createToolbarTooltip(onChange) {
|
|
3112
|
+
function createToolbarTooltip(onChange, delay = () => 400) {
|
|
3119
3113
|
let state = {
|
|
3120
3114
|
for: "",
|
|
3121
3115
|
label: "",
|
|
@@ -3150,7 +3144,7 @@ function createToolbarTooltip(onChange) {
|
|
|
3150
3144
|
if (!open) timer = setTimeout(() => {
|
|
3151
3145
|
timer = void 0;
|
|
3152
3146
|
set({ open: true });
|
|
3153
|
-
},
|
|
3147
|
+
}, delay());
|
|
3154
3148
|
},
|
|
3155
3149
|
hide() {
|
|
3156
3150
|
clear();
|
|
@@ -10530,6 +10524,15 @@ defineComponent$1("ui-text", createUiText, [
|
|
|
10530
10524
|
"wrap"
|
|
10531
10525
|
]);
|
|
10532
10526
|
//#endregion
|
|
10527
|
+
//#region components/shared/tooltip.js
|
|
10528
|
+
/** Resolve the inherited pointer-intent delay; CSS time values and millisecond numbers are accepted. */
|
|
10529
|
+
function tooltipShowDelay(element, fallback = 500) {
|
|
10530
|
+
if (!element) return fallback;
|
|
10531
|
+
const value = element.ownerDocument.defaultView.getComputedStyle(element).getPropertyValue("--ui-tooltip-show-delay").trim();
|
|
10532
|
+
const match = /^([0-9]+(?:\.[0-9]+)?)(ms|s)?$/.exec(value);
|
|
10533
|
+
return match ? Number(match[1]) * (match[2] === "s" ? 1e3 : 1) : fallback;
|
|
10534
|
+
}
|
|
10535
|
+
//#endregion
|
|
10533
10536
|
//#region components/ui-tooltip/ui-tooltip.js
|
|
10534
10537
|
var ui_tooltip_exports = /* @__PURE__ */ __exportAll({ connect: () => connect$4 });
|
|
10535
10538
|
var warmTooltips = /* @__PURE__ */ new WeakMap();
|
|
@@ -10606,7 +10609,7 @@ function connect$4(host) {
|
|
|
10606
10609
|
showTimer = setTimeout(() => {
|
|
10607
10610
|
showTimer = null;
|
|
10608
10611
|
setOpen(true, "pointer");
|
|
10609
|
-
}, warm.active > 0 || warm.until > Date.now() ? 0 : Math.max(0, Number(host.props.showDelay.value
|
|
10612
|
+
}, warm.active > 0 || warm.until > Date.now() ? 0 : Math.max(0, host.props.showDelay.inputValue != null ? Number(host.props.showDelay.value) : tooltipShowDelay(element)));
|
|
10610
10613
|
};
|
|
10611
10614
|
const onLeave = () => {
|
|
10612
10615
|
clearShow();
|
|
@@ -10676,6 +10679,7 @@ function connect$4(host) {
|
|
|
10676
10679
|
if (how === "hover") {
|
|
10677
10680
|
trigger.addEventListener("pointerenter", onEnter);
|
|
10678
10681
|
trigger.addEventListener("pointerleave", onLeave);
|
|
10682
|
+
if (trigger.matches(":hover")) onEnter({ pointerType: "mouse" });
|
|
10679
10683
|
}
|
|
10680
10684
|
trigger.addEventListener("focusin", onFocusin);
|
|
10681
10685
|
trigger.addEventListener("focusout", onFocusout);
|
|
@@ -14758,7 +14762,7 @@ var LoomaEditor = defineComponent({
|
|
|
14758
14762
|
const toolbarScope = `looma-editor-tool-${useId().replace(/[^a-zA-Z0-9_-]/g, "")}`;
|
|
14759
14763
|
const toolbarTooltip = createToolbarTooltip((state) => {
|
|
14760
14764
|
tooltip.value = state;
|
|
14761
|
-
});
|
|
14765
|
+
}, () => tooltipShowDelay$1(root.value));
|
|
14762
14766
|
const tooltip = shallowRef(toolbarTooltip.state);
|
|
14763
14767
|
const resizeHintFor = ref("");
|
|
14764
14768
|
let resizeHintSequence = 0;
|
|
@@ -14830,7 +14834,7 @@ var LoomaEditor = defineComponent({
|
|
|
14830
14834
|
rows: 0,
|
|
14831
14835
|
cols: 0,
|
|
14832
14836
|
geometry: null,
|
|
14833
|
-
|
|
14837
|
+
toolbarTarget: null,
|
|
14834
14838
|
overlayStyle: {},
|
|
14835
14839
|
menuStyle: {},
|
|
14836
14840
|
capabilities: LOOMA_TABLE_CONTROLS_CLOSED.capabilities
|
|
@@ -15362,8 +15366,8 @@ var LoomaEditor = defineComponent({
|
|
|
15362
15366
|
tableUi.rows = Math.max(0, geometry.rowBoundaries.length - 1);
|
|
15363
15367
|
tableUi.cols = Math.max(0, geometry.columnBoundaries.length - 1);
|
|
15364
15368
|
tableUi.geometry = geometry;
|
|
15365
|
-
tableUi.
|
|
15366
|
-
tableUi.overlayStyle = tableOverlayPlacement(rect);
|
|
15369
|
+
tableUi.toolbarTarget = table.closest("[data-looma-table-block]")?.querySelector("[data-looma-table-toolbar-host]") ?? null;
|
|
15370
|
+
tableUi.overlayStyle = tableOverlayPlacement(rect, root.value.getBoundingClientRect());
|
|
15367
15371
|
};
|
|
15368
15372
|
const onEditorFocus = () => {
|
|
15369
15373
|
editorFocused.value = true;
|
|
@@ -15429,13 +15433,10 @@ var LoomaEditor = defineComponent({
|
|
|
15429
15433
|
presentation?.show();
|
|
15430
15434
|
};
|
|
15431
15435
|
};
|
|
15432
|
-
const tableToolbarRef = popupRef(tableToolbarShell);
|
|
15433
15436
|
const codeLanguageRef = popupRef(codeLanguageShell, true);
|
|
15434
15437
|
const mobileToolbarRef = popupRef(mobileToolbarShell, true);
|
|
15435
|
-
const presentTableOverlay = popupRef(tableOverlayShell);
|
|
15436
15438
|
const tableOverlayRef = (node) => {
|
|
15437
|
-
|
|
15438
|
-
if (node instanceof HTMLElement) node.hidden = !tableUi.overlayOpen;
|
|
15439
|
+
tableOverlayShell.value = node instanceof HTMLElement ? node : null;
|
|
15439
15440
|
};
|
|
15440
15441
|
const onDocumentPointerDown = (event) => {
|
|
15441
15442
|
const path = typeof event.composedPath === "function" ? event.composedPath() : [];
|
|
@@ -16048,8 +16049,6 @@ var LoomaEditor = defineComponent({
|
|
|
16048
16049
|
}, [
|
|
16049
16050
|
resizeHintFor.value ? h(Tooltip, {
|
|
16050
16051
|
for: resizeHintFor.value,
|
|
16051
|
-
open: true,
|
|
16052
|
-
trigger: "focus",
|
|
16053
16052
|
placement: "top",
|
|
16054
16053
|
inverse: true
|
|
16055
16054
|
}, () => "Drag to resize column") : null,
|
|
@@ -16263,12 +16262,11 @@ var LoomaEditor = defineComponent({
|
|
|
16263
16262
|
mention.select?.(event.detail.index);
|
|
16264
16263
|
}
|
|
16265
16264
|
}) : null,
|
|
16266
|
-
tableUi.toolbarOpen ? h("div", {
|
|
16265
|
+
tableUi.toolbarOpen && tableUi.toolbarTarget ? h(Teleport, { to: tableUi.toolbarTarget }, [h("div", {
|
|
16267
16266
|
key: "looma-table-toolbar-shell",
|
|
16268
|
-
ref:
|
|
16269
|
-
class: "looma-editor__table-toolbar-shell"
|
|
16270
|
-
|
|
16271
|
-
}, [h(EditorTableToolbar, tableProps)]) : null,
|
|
16267
|
+
ref: tableToolbarShell,
|
|
16268
|
+
class: "looma-editor__table-toolbar-shell"
|
|
16269
|
+
}, [h(EditorTableToolbar, tableProps)])]) : null,
|
|
16272
16270
|
instance && props.editable && !mobile.value ? h("div", {
|
|
16273
16271
|
key: "looma-table-overlay-shell",
|
|
16274
16272
|
ref: tableOverlayRef,
|