@threadlabs/looma 0.31.0 → 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/icons.js +1 -0
- package/components/shared/tooltip.js +7 -0
- package/components/ui-editor-footnote-editor/ui-editor-footnote-editor.html +57 -0
- package/components/ui-editor-footnote-editor/ui-editor-footnote-editor.js +38 -0
- package/components/ui-icon/ui-icon.html +1 -0
- package/components/ui-tooltip/ui-tooltip.js +4 -1
- package/dist/index.js +37 -36
- package/editor/chunks/extensions.js +363 -20
- package/editor/expressmark.js +1 -1
- package/editor/extensions/footnote.d.ts +40 -7
- package/editor/extensions/index.d.ts +1 -1
- package/editor/extensions/index.js +2 -2
- package/editor/footnote-editing.d.ts +46 -0
- package/editor/icons.d.ts +1 -0
- package/editor/index.js +4 -3
- package/editor/table-ui.d.ts +2 -11
- package/editor/toolbar-tooltip.d.ts +1 -1
- package/package.json +1 -1
- package/styles/ui-editor-footnote-editor.css +1 -0
- package/vanilla/UiEditorFootnoteEditor.d.ts +30 -0
- package/vanilla/UiEditorFootnoteEditor.js +101 -0
- package/vanilla/UiIcon.js +1 -1
- package/vanilla/index.js +1 -0
- package/vue/UiEditorFootnoteEditor.d.ts +57 -0
- package/vue/UiEditorFootnoteEditor.js +2 -0
- package/vue/UiEditorFootnoteEditor.vue +304 -0
- package/vue/UiIcon.vue +4 -0
- package/vue/chunks/UiEditorFootnoteEditor.js +306 -0
- package/vue/chunks/UiEditorImageToolbar.js +1 -1
- package/vue/chunks/UiEditorLinkForm.js +1 -1
- package/vue/chunks/UiIcon.js +15 -1
- package/vue/components.css +590 -575
- package/vue/editor/index.js +643 -45
- package/vue/editor/primitives.d.ts +3 -1
- package/vue/index.d.ts +1 -0
- package/vue/index.js +5 -4
|
@@ -63,6 +63,7 @@ export const icons = {
|
|
|
63
63
|
"settings": [["path",{"d":"M9.671 4.136a2.34 2.34 0 0 1 4.659 0 2.34 2.34 0 0 0 3.319 1.915 2.34 2.34 0 0 1 2.33 4.033 2.34 2.34 0 0 0 0 3.831 2.34 2.34 0 0 1-2.33 4.033 2.34 2.34 0 0 0-3.319 1.915 2.34 2.34 0 0 1-4.659 0 2.34 2.34 0 0 0-3.32-1.915 2.34 2.34 0 0 1-2.33-4.033 2.34 2.34 0 0 0 0-3.831A2.34 2.34 0 0 1 6.35 6.051a2.34 2.34 0 0 0 3.319-1.915"}],["circle",{"cx":"12","cy":"12","r":"3"}]],
|
|
64
64
|
"split": [["path",{"d":"M16 3h5v5"}],["path",{"d":"M8 3H3v5"}],["path",{"d":"M12 22v-8.3a4 4 0 0 0-1.172-2.872L3 3"}],["path",{"d":"m15 9 6-6"}]],
|
|
65
65
|
"strikethrough": [["path",{"d":"M16 4H9a3 3 0 0 0-2.83 4"}],["path",{"d":"M14 12a4 4 0 0 1 0 8H6"}],["line",{"x1":"4","x2":"20","y1":"12","y2":"12"}]],
|
|
66
|
+
"superscript": [["path",{"d":"m4 19 8-8"}],["path",{"d":"m12 19-8-8"}],["path",{"d":"M20 12h-4c0-1.5.442-2 1.5-2.5S20 8.334 20 7.002c0-.472-.17-.93-.484-1.29a2.105 2.105 0 0 0-2.617-.436c-.42.239-.738.614-.899 1.06"}]],
|
|
66
67
|
"table": [["path",{"d":"M9 3H5a2 2 0 0 0-2 2v4m6-6h10a2 2 0 0 1 2 2v4M9 3v18m0 0h10a2 2 0 0 0 2-2V9M9 21H5a2 2 0 0 1-2-2V9m0 0h18"}]],
|
|
67
68
|
"tag": [["path",{"d":"M12.586 2.586A2 2 0 0 0 11.172 2H4a2 2 0 0 0-2 2v7.172a2 2 0 0 0 .586 1.414l8.704 8.704a2.426 2.426 0 0 0 3.42 0l6.58-6.58a2.426 2.426 0 0 0 0-3.42z"}],["circle",{"cx":"7.5","cy":"7.5","r":".5","fill":"currentColor"}]],
|
|
68
69
|
"trash": [["path",{"d":"M10 11v6"}],["path",{"d":"M14 11v6"}],["path",{"d":"M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6"}],["path",{"d":"M3 6h18"}],["path",{"d":"M8 6V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2"}]],
|
|
@@ -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
|
+
}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
<link rel="component" href="../ui-stack/ui-stack.html">
|
|
2
|
+
<link rel="component" href="../ui-form-field/ui-form-field.html">
|
|
3
|
+
<link rel="component" href="../ui-input-group/ui-input-group.html">
|
|
4
|
+
<link rel="component" href="../ui-input/ui-input.html">
|
|
5
|
+
<link rel="component" href="../ui-textarea/ui-textarea.html">
|
|
6
|
+
<link rel="component" href="../ui-button/ui-button.html">
|
|
7
|
+
<template component="ui-editor-footnote-editor" module="./ui-editor-footnote-editor.js">
|
|
8
|
+
<defs>
|
|
9
|
+
<prop name="label" type="string" default="">The footnote's label, which its references and its note share, shown between [^ and ].</prop>
|
|
10
|
+
<prop name="note" type="string" default="">The note's text, shown in the note field, with each block of a longer note on its own line.</prop>
|
|
11
|
+
<prop name="editable" type="boolean" default="false"
|
|
12
|
+
>Whether the note's text can be edited here. A note with formatting or more than one block shows its text read-only; Go to note edits it in the
|
|
13
|
+
document.</prop>
|
|
14
|
+
<prop name="error" type="string" default="">Why the label field's label was not used. While set, the field is invalid and shows it.</prop>
|
|
15
|
+
<state name="base" type="string" value="ui-editor-footnote-editor"></state>
|
|
16
|
+
<event name="text" type="object">
|
|
17
|
+
<prop name="text" required type="string"></prop>
|
|
18
|
+
The note's text changed.
|
|
19
|
+
</event>
|
|
20
|
+
<event name="label" type="object">
|
|
21
|
+
<prop name="label" required type="string"></prop>
|
|
22
|
+
A new label was committed: the label field changed and lost focus, or Enter was pressed in it.
|
|
23
|
+
</event>
|
|
24
|
+
<event name="go" type="object">Go to note was pressed.</event>
|
|
25
|
+
<event name="done" type="object">Enter or Escape was pressed in a field, to close the editor and return to the reference.</event>
|
|
26
|
+
</defs>
|
|
27
|
+
<div role="dialog" aria-label="Edit footnote">
|
|
28
|
+
<ui-stack gap="s">
|
|
29
|
+
<ui-form-field from:invalid="$error != ''">
|
|
30
|
+
<label slot="label" from:for="concat($base, '-label')">Label</label>
|
|
31
|
+
<ui-input-group>
|
|
32
|
+
<span slot="prefix">[^</span>
|
|
33
|
+
<ui-input data-footnote-label from:id="concat($base, '-label')" size="sm" autocomplete="off" from:value="$label"></ui-input>
|
|
34
|
+
<span slot="suffix">]</span>
|
|
35
|
+
</ui-input-group>
|
|
36
|
+
<span slot="error">{$error}</span>
|
|
37
|
+
</ui-form-field>
|
|
38
|
+
<ui-form-field>
|
|
39
|
+
<label slot="label" from:for="concat($base, '-note')">Note</label>
|
|
40
|
+
<ui-input-group multiline>
|
|
41
|
+
<ui-textarea
|
|
42
|
+
data-footnote-note
|
|
43
|
+
from:id="concat($base, '-note')"
|
|
44
|
+
size="sm"
|
|
45
|
+
rows="2"
|
|
46
|
+
autosize
|
|
47
|
+
placeholder="Write the note"
|
|
48
|
+
from:readonly="not $editable"
|
|
49
|
+
from:value="$note"
|
|
50
|
+
></ui-textarea>
|
|
51
|
+
<ui-button slot="action" size="sm" data-footnote-go>Go to note</ui-button>
|
|
52
|
+
</ui-input-group>
|
|
53
|
+
<span $if="not $editable" slot="help">This note has formatting, so it is edited in the document.</span>
|
|
54
|
+
</ui-form-field>
|
|
55
|
+
</ui-stack>
|
|
56
|
+
</div>
|
|
57
|
+
</template>
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
// Gives each editor its own field ids, reports the note's text as it changes and a label when it is
|
|
2
|
+
// committed, Go to note when pressed, and Enter or Escape in a field as done.
|
|
3
|
+
export function connect(host) {
|
|
4
|
+
const element = host.element;
|
|
5
|
+
if (host.state.base === "ui-editor-footnote-editor") host.state.base = `ui-editor-footnote-editor-${Math.random().toString(36).slice(2, 11)}`;
|
|
6
|
+
const within = (event, selector) => {
|
|
7
|
+
const match = event.target.closest?.(selector);
|
|
8
|
+
return match && element.contains(match) ? match : null;
|
|
9
|
+
};
|
|
10
|
+
const onInput = (event) => {
|
|
11
|
+
if (within(event, "[data-footnote-note]")) host.dispatch("text", { text: event.target.value });
|
|
12
|
+
};
|
|
13
|
+
const onChange = (event) => {
|
|
14
|
+
if (within(event, "[data-footnote-label]") && typeof event.target.value === "string") host.dispatch("label", { label: event.target.value.trim() });
|
|
15
|
+
};
|
|
16
|
+
const onClick = (event) => {
|
|
17
|
+
if (within(event, "[data-footnote-go]")) host.dispatch("go", {});
|
|
18
|
+
};
|
|
19
|
+
// The editor handles Enter and Escape itself, so the overlay around it does not also act on them.
|
|
20
|
+
const onKeyDown = (event) => {
|
|
21
|
+
const label = within(event, "[data-footnote-label]");
|
|
22
|
+
if ((event.key !== "Enter" && event.key !== "Escape") || !(label || within(event, "[data-footnote-note]"))) return;
|
|
23
|
+
event.preventDefault();
|
|
24
|
+
event.stopPropagation();
|
|
25
|
+
if (label && event.key === "Enter") host.dispatch("label", { label: event.target.value.trim() });
|
|
26
|
+
host.dispatch("done", {});
|
|
27
|
+
};
|
|
28
|
+
element.addEventListener("input", onInput);
|
|
29
|
+
element.addEventListener("change", onChange);
|
|
30
|
+
element.addEventListener("click", onClick);
|
|
31
|
+
element.addEventListener("keydown", onKeyDown);
|
|
32
|
+
return () => {
|
|
33
|
+
element.removeEventListener("input", onInput);
|
|
34
|
+
element.removeEventListener("change", onChange);
|
|
35
|
+
element.removeEventListener("click", onClick);
|
|
36
|
+
element.removeEventListener("keydown", onKeyDown);
|
|
37
|
+
};
|
|
38
|
+
}
|
|
@@ -72,6 +72,7 @@
|
|
|
72
72
|
'settings': [{ tag: 'path', d: 'M9.671 4.136a2.34 2.34 0 0 1 4.659 0 2.34 2.34 0 0 0 3.319 1.915 2.34 2.34 0 0 1 2.33 4.033 2.34 2.34 0 0 0 0 3.831 2.34 2.34 0 0 1-2.33 4.033 2.34 2.34 0 0 0-3.319 1.915 2.34 2.34 0 0 1-4.659 0 2.34 2.34 0 0 0-3.32-1.915 2.34 2.34 0 0 1-2.33-4.033 2.34 2.34 0 0 0 0-3.831A2.34 2.34 0 0 1 6.35 6.051a2.34 2.34 0 0 0 3.319-1.915' }, { tag: 'circle', cx: '12', cy: '12', r: '3' }],
|
|
73
73
|
'split': [{ tag: 'path', d: 'M16 3h5v5' }, { tag: 'path', d: 'M8 3H3v5' }, { tag: 'path', d: 'M12 22v-8.3a4 4 0 0 0-1.172-2.872L3 3' }, { tag: 'path', d: 'm15 9 6-6' }],
|
|
74
74
|
'strikethrough': [{ tag: 'path', d: 'M16 4H9a3 3 0 0 0-2.83 4' }, { tag: 'path', d: 'M14 12a4 4 0 0 1 0 8H6' }, { tag: 'line', x1: '4', x2: '20', y1: '12', y2: '12' }],
|
|
75
|
+
'superscript': [{ tag: 'path', d: 'm4 19 8-8' }, { tag: 'path', d: 'm12 19-8-8' }, { tag: 'path', d: 'M20 12h-4c0-1.5.442-2 1.5-2.5S20 8.334 20 7.002c0-.472-.17-.93-.484-1.29a2.105 2.105 0 0 0-2.617-.436c-.42.239-.738.614-.899 1.06' }],
|
|
75
76
|
'table': [{ tag: 'path', d: 'M9 3H5a2 2 0 0 0-2 2v4m6-6h10a2 2 0 0 1 2 2v4M9 3v18m0 0h10a2 2 0 0 0 2-2V9M9 21H5a2 2 0 0 1-2-2V9m0 0h18' }],
|
|
76
77
|
'tag': [{ tag: 'path', d: 'M12.586 2.586A2 2 0 0 0 11.172 2H4a2 2 0 0 0-2 2v7.172a2 2 0 0 0 .586 1.414l8.704 8.704a2.426 2.426 0 0 0 3.42 0l6.58-6.58a2.426 2.426 0 0 0 0-3.42z' }, { tag: 'circle', cx: '7.5', cy: '7.5', r: '.5', fill: 'currentColor' }],
|
|
77
78
|
'trash': [{ tag: 'path', d: 'M10 11v6' }, { tag: 'path', d: 'M14 11v6' }, { tag: 'path', d: 'M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6' }, { tag: 'path', d: 'M3 6h18' }, { tag: 'path', d: 'M8 6V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2' }],
|
|
@@ -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);
|