@threadlabs/looma 0.7.4 → 0.8.1
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/ui-avatar/ui-avatar.html +1 -1
- package/components/ui-avatar-group/ui-avatar-group.html +1 -1
- package/components/ui-button/ui-button.html +2 -2
- package/components/ui-combobox/ui-combobox.html +1 -1
- package/components/ui-editor-slash-menu/ui-editor-slash-menu.html +1 -1
- package/components/ui-editor-table-context-menu/ui-editor-table-context-menu.html +1 -1
- package/components/ui-editor-table-toolbar/ui-editor-table-toolbar.html +1 -1
- package/components/ui-form-field/ui-form-field.html +3 -3
- package/components/ui-tree-item/ui-tree-item.html +1 -1
- package/dist/index.js +1 -1
- package/editor/chunks/extensions.js +89 -38
- package/editor/extensions/active-block.d.ts +23 -7
- package/editor/extensions/index.d.ts +1 -1
- package/editor/extensions/index.js +2 -2
- package/editor/index.js +2 -2
- package/package.json +1 -1
- package/styles/ui-avatar-group.css +1 -1
- package/styles/ui-avatar.css +1 -1
- package/styles/ui-button.css +2 -2
- package/styles/ui-combobox.css +1 -1
- package/styles/ui-editor-slash-menu.css +1 -1
- package/styles/ui-editor-table-context-menu.css +1 -1
- package/styles/ui-editor-table-toolbar.css +1 -1
- package/styles/ui-form-field.css +3 -3
- package/styles/ui-tree-item.css +1 -1
- package/tokens.css +2 -3
- package/vue/UiAvatar.vue +1 -1
- package/vue/UiAvatarGroup.vue +1 -1
- package/vue/UiButton.vue +2 -2
- package/vue/UiCombobox.vue +1 -1
- package/vue/UiEditorSlashMenu.vue +1 -1
- package/vue/UiEditorTableContextMenu.vue +1 -1
- package/vue/UiEditorTableToolbar.vue +1 -1
- package/vue/UiFormField.vue +3 -3
- package/vue/UiTreeItem.vue +1 -1
- package/vue/chunks/UiAvatar.js +1 -1
- package/vue/chunks/UiAvatarGroup.js +1 -1
- package/vue/chunks/UiButton.js +1 -1
- package/vue/chunks/UiCombobox.js +1 -1
- package/vue/chunks/UiEditorSlashMenu.js +1 -1
- package/vue/chunks/UiEditorTableContextMenu.js +1 -1
- package/vue/chunks/UiEditorTableToolbar.js +1 -1
- package/vue/chunks/UiFormField.js +1 -1
- package/vue/chunks/UiTreeItem.js +1 -1
- package/vue/components.css +238 -230
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import { n as TABLE_CELL_BACKGROUND_PRESETS } from "./table-backgrounds.js";
|
|
2
|
-
import { Extension, Mark, Node, callOrReturn, canInsertNode, combineTransactionSteps, escapeForRegEx, findChildren, findChildrenInRange, findParentNodeClosestToPos, getAttributes, getChangedRanges, getExtensionField, getMarksBetween, isNodeEmpty, isNodeSelection, markInputRule, markPasteRule, mergeAttributes, nodeInputRule, textInputRule, textblockTypeInputRule, wrappingInputRule } from "@tiptap/core";
|
|
2
|
+
import { Extension, Mark, Node as Node$1, callOrReturn, canInsertNode, combineTransactionSteps, escapeForRegEx, findChildren, findChildrenInRange, findParentNodeClosestToPos, getAttributes, getChangedRanges, getExtensionField, getMarksBetween, isNodeEmpty, isNodeSelection, markInputRule, markPasteRule, mergeAttributes, nodeInputRule, textInputRule, textblockTypeInputRule, wrappingInputRule } from "@tiptap/core";
|
|
3
3
|
import { NodeSelection, Plugin, PluginKey, Selection, TextSelection } from "@tiptap/pm/state";
|
|
4
4
|
import { Decoration, DecorationSet } from "@tiptap/pm/view";
|
|
5
5
|
import { history, redo, undo } from "@tiptap/pm/history";
|
|
6
6
|
import { dropCursor } from "@tiptap/pm/dropcursor";
|
|
7
7
|
import { gapCursor } from "@tiptap/pm/gapcursor";
|
|
8
8
|
import { common, createLowlight } from "lowlight";
|
|
9
|
-
import { DOMParser, Node as Node$
|
|
9
|
+
import { DOMParser, Node as Node$2 } from "@tiptap/pm/model";
|
|
10
10
|
import MarkdownIt from "markdown-it";
|
|
11
11
|
import { CellSelection, TableMap, addColumn, addColumnAfter, addColumnBefore, addRow, addRowAfter, addRowBefore, cellAround, columnResizing, deleteCellSelection, deleteColumn, deleteRow, deleteTable, fixTables, goToNextCell, mergeCells, setCellAttr, splitCell, tableEditing, toggleHeader, toggleHeaderCell } from "@tiptap/pm/tables";
|
|
12
12
|
//#region src/editor/extensions/active-block.ts
|
|
@@ -19,23 +19,42 @@ import { CellSelection, TableMap, addColumn, addColumnAfter, addColumnBefore, ad
|
|
|
19
19
|
* wrap and every arrow key, and one that tracked a nested list item would step
|
|
20
20
|
* in and out of the list's inset. The outermost block is the stable answer to
|
|
21
21
|
* "where am I", which is the question the marker exists to answer.
|
|
22
|
+
*
|
|
23
|
+
* The marker is a cue for finding your place, so it stays out of the way while
|
|
24
|
+
* the place is obvious: it is absent while text is being typed and returns once
|
|
25
|
+
* typing pauses, and a focus change that stays within the editor (the toolbar,
|
|
26
|
+
* a menu) or that returns at once does not blink it off.
|
|
22
27
|
*/
|
|
23
28
|
/** Class applied to the decorated block; `looma-editor.css` owns its appearance. */
|
|
24
29
|
var LOOMA_ACTIVE_BLOCK_CLASS = "looma-active-block";
|
|
25
|
-
/**
|
|
30
|
+
/** How long typing must pause before the marker returns. */
|
|
31
|
+
var LOOMA_ACTIVE_BLOCK_TYPING_IDLE_MS = 800;
|
|
32
|
+
/** How long focus may be away before the marker treats the editor as unfocused. */
|
|
33
|
+
var LOOMA_ACTIVE_BLOCK_BLUR_GRACE_MS = 200;
|
|
34
|
+
/** Plugin state is the editor's focus and whether text is being typed. */
|
|
26
35
|
var LoomaActiveBlockPluginKey = new PluginKey("loomaActiveBlock");
|
|
36
|
+
var blurTimers = /* @__PURE__ */ new WeakMap();
|
|
37
|
+
function setActiveBlockState(view, next) {
|
|
38
|
+
view.dispatch(view.state.tr.setMeta(LoomaActiveBlockPluginKey, next));
|
|
39
|
+
}
|
|
40
|
+
function cancelPendingBlur(view) {
|
|
41
|
+
clearTimeout(blurTimers.get(view));
|
|
42
|
+
blurTimers.delete(view);
|
|
43
|
+
}
|
|
27
44
|
/**
|
|
28
45
|
* Decorates the outermost block containing the selection head while the editor
|
|
29
|
-
* has focus.
|
|
46
|
+
* has focus and text is not being typed.
|
|
30
47
|
*
|
|
31
48
|
* @contract Adds `LOOMA_ACTIVE_BLOCK_CLASS` to at most one top-level block, and
|
|
32
|
-
* nothing at all when the editor is unfocused
|
|
33
|
-
* never modified.
|
|
49
|
+
* nothing at all when the editor is unfocused, not editable, or being typed in.
|
|
50
|
+
* The document is never modified.
|
|
34
51
|
* @invariant Focus is tracked in plugin state rather than read from the editor,
|
|
35
52
|
* so the decoration recomputes on focus and blur even when neither changes the
|
|
36
|
-
* selection.
|
|
53
|
+
* selection. A blur only takes effect once focus has stayed away for
|
|
54
|
+
* `LOOMA_ACTIVE_BLOCK_BLUR_GRACE_MS`, and never when focus moved to an element
|
|
55
|
+
* inside the editor's own root.
|
|
37
56
|
* @ownership The consuming stylesheet owns every visual property; this extension
|
|
38
|
-
* owns only which block carries the class.
|
|
57
|
+
* owns only which block carries the class, and when.
|
|
39
58
|
*/
|
|
40
59
|
var LoomaActiveBlock = Extension.create({
|
|
41
60
|
name: "loomaActiveBlock",
|
|
@@ -43,25 +62,57 @@ var LoomaActiveBlock = Extension.create({
|
|
|
43
62
|
return [new Plugin({
|
|
44
63
|
key: LoomaActiveBlockPluginKey,
|
|
45
64
|
state: {
|
|
46
|
-
init: () =>
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
65
|
+
init: () => ({
|
|
66
|
+
focused: false,
|
|
67
|
+
typing: false
|
|
68
|
+
}),
|
|
69
|
+
apply: (transaction, previous) => {
|
|
70
|
+
const meta = transaction.getMeta(LoomaActiveBlockPluginKey);
|
|
71
|
+
const next = {
|
|
72
|
+
...previous,
|
|
73
|
+
...meta
|
|
74
|
+
};
|
|
75
|
+
if (transaction.docChanged && meta?.typing === void 0) next.typing = true;
|
|
76
|
+
return next.focused === previous.focused && next.typing === previous.typing ? previous : next;
|
|
50
77
|
}
|
|
51
78
|
},
|
|
79
|
+
view: () => {
|
|
80
|
+
let idleTimer;
|
|
81
|
+
return {
|
|
82
|
+
update: (view, previousState) => {
|
|
83
|
+
if (!LoomaActiveBlockPluginKey.getState(view.state)?.typing) {
|
|
84
|
+
clearTimeout(idleTimer);
|
|
85
|
+
return;
|
|
86
|
+
}
|
|
87
|
+
if (view.state.doc.eq(previousState.doc)) return;
|
|
88
|
+
clearTimeout(idleTimer);
|
|
89
|
+
idleTimer = setTimeout(() => setActiveBlockState(view, { typing: false }), 800);
|
|
90
|
+
},
|
|
91
|
+
destroy: () => clearTimeout(idleTimer)
|
|
92
|
+
};
|
|
93
|
+
},
|
|
52
94
|
props: {
|
|
53
95
|
handleDOMEvents: {
|
|
54
96
|
focus: (view) => {
|
|
55
|
-
|
|
97
|
+
cancelPendingBlur(view);
|
|
98
|
+
if (!LoomaActiveBlockPluginKey.getState(view.state)?.focused) setActiveBlockState(view, { focused: true });
|
|
56
99
|
return false;
|
|
57
100
|
},
|
|
58
|
-
blur: (view) => {
|
|
59
|
-
|
|
101
|
+
blur: (view, event) => {
|
|
102
|
+
const destination = event.relatedTarget;
|
|
103
|
+
const root = view.dom.closest(".looma-editor") ?? view.dom.parentElement;
|
|
104
|
+
if (destination instanceof Node && root?.contains(destination)) return false;
|
|
105
|
+
cancelPendingBlur(view);
|
|
106
|
+
blurTimers.set(view, setTimeout(() => {
|
|
107
|
+
blurTimers.delete(view);
|
|
108
|
+
if (!view.isDestroyed && !view.hasFocus()) setActiveBlockState(view, { focused: false });
|
|
109
|
+
}, 200));
|
|
60
110
|
return false;
|
|
61
111
|
}
|
|
62
112
|
},
|
|
63
113
|
decorations: (state) => {
|
|
64
|
-
|
|
114
|
+
const active = LoomaActiveBlockPluginKey.getState(state);
|
|
115
|
+
if (!active?.focused || active.typing) return null;
|
|
65
116
|
const { $head } = state.selection;
|
|
66
117
|
if ($head.depth === 0) return null;
|
|
67
118
|
const from = $head.before(1);
|
|
@@ -90,7 +141,7 @@ function normalizeCalloutTone(value) {
|
|
|
90
141
|
* @invariant Parsed and rendered `data-tone` values always belong to
|
|
91
142
|
* `LOOMA_CALLOUT_TONES`; missing or unknown values round-trip as `note`.
|
|
92
143
|
*/
|
|
93
|
-
var LoomaCallout = Node.create({
|
|
144
|
+
var LoomaCallout = Node$1.create({
|
|
94
145
|
name: "loomaCallout",
|
|
95
146
|
group: "block",
|
|
96
147
|
content: "block+",
|
|
@@ -126,7 +177,7 @@ var LoomaCallout = Node.create({
|
|
|
126
177
|
* The default document node which represents the top level node of the editor.
|
|
127
178
|
* @see https://tiptap.dev/api/nodes/document
|
|
128
179
|
*/
|
|
129
|
-
var Document = Node.create({
|
|
180
|
+
var Document = Node$1.create({
|
|
130
181
|
name: "doc",
|
|
131
182
|
topNode: true,
|
|
132
183
|
content: "block+"
|
|
@@ -137,7 +188,7 @@ var Document = Node.create({
|
|
|
137
188
|
* This extension allows you to create paragraphs.
|
|
138
189
|
* @see https://www.tiptap.dev/api/nodes/paragraph
|
|
139
190
|
*/
|
|
140
|
-
var Paragraph = Node.create({
|
|
191
|
+
var Paragraph = Node$1.create({
|
|
141
192
|
name: "paragraph",
|
|
142
193
|
priority: 1e3,
|
|
143
194
|
addOptions() {
|
|
@@ -170,7 +221,7 @@ var Paragraph = Node.create({
|
|
|
170
221
|
* This extension allows you to create text nodes.
|
|
171
222
|
* @see https://www.tiptap.dev/api/nodes/text
|
|
172
223
|
*/
|
|
173
|
-
var Text$1 = Node.create({
|
|
224
|
+
var Text$1 = Node$1.create({
|
|
174
225
|
name: "text",
|
|
175
226
|
group: "inline"
|
|
176
227
|
});
|
|
@@ -467,7 +518,7 @@ var Underline = Mark.create({
|
|
|
467
518
|
* This extension allows you to create headings.
|
|
468
519
|
* @see https://www.tiptap.dev/api/nodes/heading
|
|
469
520
|
*/
|
|
470
|
-
var Heading = Node.create({
|
|
521
|
+
var Heading = Node$1.create({
|
|
471
522
|
name: "heading",
|
|
472
523
|
addOptions() {
|
|
473
524
|
return {
|
|
@@ -546,7 +597,7 @@ var inputRegex$6 = /^\s*([-+*])\s$/;
|
|
|
546
597
|
* @see https://tiptap.dev/api/nodes/bullet-list
|
|
547
598
|
* @see https://tiptap.dev/api/nodes/list-item.
|
|
548
599
|
*/
|
|
549
|
-
var BulletList = Node.create({
|
|
600
|
+
var BulletList = Node$1.create({
|
|
550
601
|
name: "bulletList",
|
|
551
602
|
addOptions() {
|
|
552
603
|
return {
|
|
@@ -611,7 +662,7 @@ var inputRegex$5 = /^(\d+)\.\s$/;
|
|
|
611
662
|
* @see https://www.tiptap.dev/api/nodes/ordered-list
|
|
612
663
|
* @see https://www.tiptap.dev/api/nodes/list-item
|
|
613
664
|
*/
|
|
614
|
-
var OrderedList = Node.create({
|
|
665
|
+
var OrderedList = Node$1.create({
|
|
615
666
|
name: "orderedList",
|
|
616
667
|
addOptions() {
|
|
617
668
|
return {
|
|
@@ -691,7 +742,7 @@ var OrderedList = Node.create({
|
|
|
691
742
|
* This extension allows you to create list items.
|
|
692
743
|
* @see https://www.tiptap.dev/api/nodes/list-item
|
|
693
744
|
*/
|
|
694
|
-
var ListItem = Node.create({
|
|
745
|
+
var ListItem = Node$1.create({
|
|
695
746
|
name: "listItem",
|
|
696
747
|
addOptions() {
|
|
697
748
|
return {
|
|
@@ -726,7 +777,7 @@ var ListItem = Node.create({
|
|
|
726
777
|
* This extension allows you to create task lists.
|
|
727
778
|
* @see https://www.tiptap.dev/api/nodes/task-list
|
|
728
779
|
*/
|
|
729
|
-
var TaskList = Node.create({
|
|
780
|
+
var TaskList = Node$1.create({
|
|
730
781
|
name: "taskList",
|
|
731
782
|
addOptions() {
|
|
732
783
|
return {
|
|
@@ -770,7 +821,7 @@ var inputRegex$4 = /^\s*(\[([( |x])?\])\s$/;
|
|
|
770
821
|
* This extension allows you to create task items.
|
|
771
822
|
* @see https://www.tiptap.dev/api/nodes/task-item
|
|
772
823
|
*/
|
|
773
|
-
var TaskItem = Node.create({
|
|
824
|
+
var TaskItem = Node$1.create({
|
|
774
825
|
name: "taskItem",
|
|
775
826
|
addOptions() {
|
|
776
827
|
return {
|
|
@@ -903,7 +954,7 @@ var inputRegex$3 = /^\s*>\s$/;
|
|
|
903
954
|
* This extension allows you to create blockquotes.
|
|
904
955
|
* @see https://tiptap.dev/api/nodes/blockquote
|
|
905
956
|
*/
|
|
906
|
-
var Blockquote = Node.create({
|
|
957
|
+
var Blockquote = Node$1.create({
|
|
907
958
|
name: "blockquote",
|
|
908
959
|
addOptions() {
|
|
909
960
|
return { HTMLAttributes: {} };
|
|
@@ -950,7 +1001,7 @@ var Blockquote = Node.create({
|
|
|
950
1001
|
* This extension allows you to insert horizontal rules.
|
|
951
1002
|
* @see https://www.tiptap.dev/api/nodes/horizontal-rule
|
|
952
1003
|
*/
|
|
953
|
-
var HorizontalRule = Node.create({
|
|
1004
|
+
var HorizontalRule = Node$1.create({
|
|
954
1005
|
name: "horizontalRule",
|
|
955
1006
|
addOptions() {
|
|
956
1007
|
return { HTMLAttributes: {} };
|
|
@@ -1009,7 +1060,7 @@ var HorizontalRule = Node.create({
|
|
|
1009
1060
|
* This extension allows you to insert hard breaks.
|
|
1010
1061
|
* @see https://www.tiptap.dev/api/nodes/hard-break
|
|
1011
1062
|
*/
|
|
1012
|
-
var HardBreak = Node.create({
|
|
1063
|
+
var HardBreak = Node$1.create({
|
|
1013
1064
|
name: "hardBreak",
|
|
1014
1065
|
addOptions() {
|
|
1015
1066
|
return {
|
|
@@ -2895,7 +2946,7 @@ var inputRegex$2 = /(?:^|\s)(!\[(.+|:?)]\((\S+)(?:(?:\s+)["'](\S+)["'])?\))$/;
|
|
|
2895
2946
|
* This extension allows you to insert images.
|
|
2896
2947
|
* @see https://www.tiptap.dev/api/nodes/image
|
|
2897
2948
|
*/
|
|
2898
|
-
var Image = Node.create({
|
|
2949
|
+
var Image = Node$1.create({
|
|
2899
2950
|
name: "image",
|
|
2900
2951
|
addOptions() {
|
|
2901
2952
|
return {
|
|
@@ -3304,7 +3355,7 @@ var tildeInputRegex = /^~~~([a-z]+)?[\s\n]$/;
|
|
|
3304
3355
|
* This extension allows you to create code blocks.
|
|
3305
3356
|
* @see https://tiptap.dev/api/nodes/code-block
|
|
3306
3357
|
*/
|
|
3307
|
-
var CodeBlock = Node.create({
|
|
3358
|
+
var CodeBlock = Node$1.create({
|
|
3308
3359
|
name: "codeBlock",
|
|
3309
3360
|
addOptions() {
|
|
3310
3361
|
return {
|
|
@@ -5375,7 +5426,7 @@ var CodeBlockLowlight = CodeBlock.extend({
|
|
|
5375
5426
|
* This extension allows you to create table rows.
|
|
5376
5427
|
* @see https://www.tiptap.dev/api/nodes/table-row
|
|
5377
5428
|
*/
|
|
5378
|
-
var TableRow = Node.create({
|
|
5429
|
+
var TableRow = Node$1.create({
|
|
5379
5430
|
name: "tableRow",
|
|
5380
5431
|
addOptions() {
|
|
5381
5432
|
return { HTMLAttributes: {} };
|
|
@@ -5679,7 +5730,7 @@ function getSuggestionFromChar(options, char) {
|
|
|
5679
5730
|
* This extension allows you to insert mentions into the editor.
|
|
5680
5731
|
* @see https://www.tiptap.dev/api/extensions/mention
|
|
5681
5732
|
*/
|
|
5682
|
-
var Mention = Node.create({
|
|
5733
|
+
var Mention = Node$1.create({
|
|
5683
5734
|
name: "mention",
|
|
5684
5735
|
priority: 101,
|
|
5685
5736
|
addOptions() {
|
|
@@ -5789,7 +5840,7 @@ var Mention = Node.create({
|
|
|
5789
5840
|
return false;
|
|
5790
5841
|
}
|
|
5791
5842
|
});
|
|
5792
|
-
let mentionNode = new Node$
|
|
5843
|
+
let mentionNode = new Node$2();
|
|
5793
5844
|
let mentionPos = 0;
|
|
5794
5845
|
state.doc.nodesBetween(anchor - 1, anchor, (node, pos) => {
|
|
5795
5846
|
if (node.type.name === this.name) {
|
|
@@ -6260,7 +6311,7 @@ var deleteTableWhenAllCellsSelected = ({ editor }) => {
|
|
|
6260
6311
|
* This extension allows you to create tables.
|
|
6261
6312
|
* @see https://www.tiptap.dev/api/nodes/table
|
|
6262
6313
|
*/
|
|
6263
|
-
var Table = Node.create({
|
|
6314
|
+
var Table = Node$1.create({
|
|
6264
6315
|
name: "table",
|
|
6265
6316
|
addOptions() {
|
|
6266
6317
|
return {
|
|
@@ -6405,7 +6456,7 @@ var Table = Node.create({
|
|
|
6405
6456
|
* This extension allows you to create table cells.
|
|
6406
6457
|
* @see https://www.tiptap.dev/api/nodes/table-cell
|
|
6407
6458
|
*/
|
|
6408
|
-
var TableCell = Node.create({
|
|
6459
|
+
var TableCell = Node$1.create({
|
|
6409
6460
|
name: "tableCell",
|
|
6410
6461
|
addOptions() {
|
|
6411
6462
|
return { HTMLAttributes: {} };
|
|
@@ -6443,7 +6494,7 @@ var TableCell = Node.create({
|
|
|
6443
6494
|
* This extension allows you to create table headers.
|
|
6444
6495
|
* @see https://www.tiptap.dev/api/nodes/table-header
|
|
6445
6496
|
*/
|
|
6446
|
-
var TableHeader = Node.create({
|
|
6497
|
+
var TableHeader = Node$1.create({
|
|
6447
6498
|
name: "tableHeader",
|
|
6448
6499
|
addOptions() {
|
|
6449
6500
|
return { HTMLAttributes: {} };
|
|
@@ -7330,4 +7381,4 @@ function createLoomaSlashCommandExtension(options = {}) {
|
|
|
7330
7381
|
});
|
|
7331
7382
|
}
|
|
7332
7383
|
//#endregion
|
|
7333
|
-
export {
|
|
7384
|
+
export { LOOMA_ACTIVE_BLOCK_CLASS as A, DEFAULT_MENTION_RESULT_LIMIT as C, LOOMA_CALLOUT_TONES as D, normalizeMentionResultLimit as E, LoomaActiveBlock as M, LoomaActiveBlockPluginKey as N, LoomaCallout as O, createLoomaMentionExtension as S, filterLoomaMentionItems as T, getActiveTableCellBackground as _, handleTableAction as a, LoomaSmartPaste as b, normalizeActiveTableColumnWidths as c, getDefaultEditorExtensions as d, getLoomaTableExtensions as f, getActiveTableCellAlignment as g, LoomaTableHeader as h, getActiveTableUiState as i, LOOMA_ACTIVE_BLOCK_TYPING_IDLE_MS as j, LOOMA_ACTIVE_BLOCK_BLUR_GRACE_MS as k, shouldShowTextFormattingToolbar as l, LoomaTableCell as m, createLoomaSlashCommandExtension as n, handleTableOverlayAction as o, LoomaTable as p, getDefaultSlashCommands as r, insertTableAtRange as s, LoomaSlashCommand as t, LoomaTableKit as u, setActiveTableCellAlignment as v, MAX_MENTION_RESULT_LIMIT as w, LoomaMentionSuggestionPluginKey as x, setActiveTableCellBackground as y };
|
|
@@ -7,24 +7,40 @@
|
|
|
7
7
|
* wrap and every arrow key, and one that tracked a nested list item would step
|
|
8
8
|
* in and out of the list's inset. The outermost block is the stable answer to
|
|
9
9
|
* "where am I", which is the question the marker exists to answer.
|
|
10
|
+
*
|
|
11
|
+
* The marker is a cue for finding your place, so it stays out of the way while
|
|
12
|
+
* the place is obvious: it is absent while text is being typed and returns once
|
|
13
|
+
* typing pauses, and a focus change that stays within the editor (the toolbar,
|
|
14
|
+
* a menu) or that returns at once does not blink it off.
|
|
10
15
|
*/
|
|
11
16
|
import { Extension } from "@tiptap/core";
|
|
12
17
|
import { PluginKey } from "@tiptap/pm/state";
|
|
13
18
|
/** Class applied to the decorated block; `looma-editor.css` owns its appearance. */
|
|
14
19
|
export declare const LOOMA_ACTIVE_BLOCK_CLASS = "looma-active-block";
|
|
15
|
-
/**
|
|
16
|
-
export declare const
|
|
20
|
+
/** How long typing must pause before the marker returns. */
|
|
21
|
+
export declare const LOOMA_ACTIVE_BLOCK_TYPING_IDLE_MS = 800;
|
|
22
|
+
/** How long focus may be away before the marker treats the editor as unfocused. */
|
|
23
|
+
export declare const LOOMA_ACTIVE_BLOCK_BLUR_GRACE_MS = 200;
|
|
24
|
+
interface ActiveBlockState {
|
|
25
|
+
focused: boolean;
|
|
26
|
+
typing: boolean;
|
|
27
|
+
}
|
|
28
|
+
/** Plugin state is the editor's focus and whether text is being typed. */
|
|
29
|
+
export declare const LoomaActiveBlockPluginKey: PluginKey<ActiveBlockState>;
|
|
17
30
|
/**
|
|
18
31
|
* Decorates the outermost block containing the selection head while the editor
|
|
19
|
-
* has focus.
|
|
32
|
+
* has focus and text is not being typed.
|
|
20
33
|
*
|
|
21
34
|
* @contract Adds `LOOMA_ACTIVE_BLOCK_CLASS` to at most one top-level block, and
|
|
22
|
-
* nothing at all when the editor is unfocused
|
|
23
|
-
* never modified.
|
|
35
|
+
* nothing at all when the editor is unfocused, not editable, or being typed in.
|
|
36
|
+
* The document is never modified.
|
|
24
37
|
* @invariant Focus is tracked in plugin state rather than read from the editor,
|
|
25
38
|
* so the decoration recomputes on focus and blur even when neither changes the
|
|
26
|
-
* selection.
|
|
39
|
+
* selection. A blur only takes effect once focus has stayed away for
|
|
40
|
+
* `LOOMA_ACTIVE_BLOCK_BLUR_GRACE_MS`, and never when focus moved to an element
|
|
41
|
+
* inside the editor's own root.
|
|
27
42
|
* @ownership The consuming stylesheet owns every visual property; this extension
|
|
28
|
-
* owns only which block carries the class.
|
|
43
|
+
* owns only which block carries the class, and when.
|
|
29
44
|
*/
|
|
30
45
|
export declare const LoomaActiveBlock: Extension<any, any>;
|
|
46
|
+
export {};
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
* application owns wiring and editor-instance lifetime. Tiptap remains a peer
|
|
7
7
|
* dependency so Looma and the host execute against the same editor runtime.
|
|
8
8
|
*/
|
|
9
|
-
export { LOOMA_ACTIVE_BLOCK_CLASS, LoomaActiveBlock, LoomaActiveBlockPluginKey, } from "./active-block.js";
|
|
9
|
+
export { LOOMA_ACTIVE_BLOCK_BLUR_GRACE_MS, LOOMA_ACTIVE_BLOCK_CLASS, LOOMA_ACTIVE_BLOCK_TYPING_IDLE_MS, LoomaActiveBlock, LoomaActiveBlockPluginKey, } from "./active-block.js";
|
|
10
10
|
export { LoomaCallout, LOOMA_CALLOUT_TONES, type LoomaCalloutTone, } from "./callout.js";
|
|
11
11
|
export { getDefaultEditorExtensions, getLoomaTableExtensions, LoomaTableKit, type DefaultEditorExtensionsOptions, } from "./preset.js";
|
|
12
12
|
export { LoomaSmartPaste } from "./smart-paste.js";
|
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
import { n as TABLE_CELL_BACKGROUND_PRESETS } from "../chunks/table-backgrounds.js";
|
|
2
|
-
import { A as
|
|
3
|
-
export { DEFAULT_MENTION_RESULT_LIMIT, LOOMA_ACTIVE_BLOCK_CLASS, LOOMA_CALLOUT_TONES, LoomaActiveBlock, LoomaActiveBlockPluginKey, LoomaCallout, LoomaMentionSuggestionPluginKey, LoomaSlashCommand, LoomaSmartPaste, LoomaTable, LoomaTableCell, LoomaTableHeader, LoomaTableKit, MAX_MENTION_RESULT_LIMIT, TABLE_CELL_BACKGROUND_PRESETS, createLoomaMentionExtension, createLoomaSlashCommandExtension, filterLoomaMentionItems, getActiveTableCellAlignment, getActiveTableCellBackground, getActiveTableUiState, getDefaultEditorExtensions, getDefaultSlashCommands, getLoomaTableExtensions, handleTableAction, handleTableOverlayAction, insertTableAtRange, normalizeActiveTableColumnWidths, normalizeMentionResultLimit, setActiveTableCellAlignment, setActiveTableCellBackground, shouldShowTextFormattingToolbar };
|
|
2
|
+
import { A as LOOMA_ACTIVE_BLOCK_CLASS, C as DEFAULT_MENTION_RESULT_LIMIT, D as LOOMA_CALLOUT_TONES, E as normalizeMentionResultLimit, M as LoomaActiveBlock, N as LoomaActiveBlockPluginKey, O as LoomaCallout, S as createLoomaMentionExtension, T as filterLoomaMentionItems, _ as getActiveTableCellBackground, a as handleTableAction, b as LoomaSmartPaste, c as normalizeActiveTableColumnWidths, d as getDefaultEditorExtensions, f as getLoomaTableExtensions, g as getActiveTableCellAlignment, h as LoomaTableHeader, i as getActiveTableUiState, j as LOOMA_ACTIVE_BLOCK_TYPING_IDLE_MS, k as LOOMA_ACTIVE_BLOCK_BLUR_GRACE_MS, l as shouldShowTextFormattingToolbar, m as LoomaTableCell, n as createLoomaSlashCommandExtension, o as handleTableOverlayAction, p as LoomaTable, r as getDefaultSlashCommands, s as insertTableAtRange, t as LoomaSlashCommand, u as LoomaTableKit, v as setActiveTableCellAlignment, w as MAX_MENTION_RESULT_LIMIT, x as LoomaMentionSuggestionPluginKey, y as setActiveTableCellBackground } from "../chunks/extensions.js";
|
|
3
|
+
export { DEFAULT_MENTION_RESULT_LIMIT, LOOMA_ACTIVE_BLOCK_BLUR_GRACE_MS, LOOMA_ACTIVE_BLOCK_CLASS, LOOMA_ACTIVE_BLOCK_TYPING_IDLE_MS, LOOMA_CALLOUT_TONES, LoomaActiveBlock, LoomaActiveBlockPluginKey, LoomaCallout, LoomaMentionSuggestionPluginKey, LoomaSlashCommand, LoomaSmartPaste, LoomaTable, LoomaTableCell, LoomaTableHeader, LoomaTableKit, MAX_MENTION_RESULT_LIMIT, TABLE_CELL_BACKGROUND_PRESETS, createLoomaMentionExtension, createLoomaSlashCommandExtension, filterLoomaMentionItems, getActiveTableCellAlignment, getActiveTableCellBackground, getActiveTableUiState, getDefaultEditorExtensions, getDefaultSlashCommands, getLoomaTableExtensions, handleTableAction, handleTableOverlayAction, insertTableAtRange, normalizeActiveTableColumnWidths, normalizeMentionResultLimit, setActiveTableCellAlignment, setActiveTableCellBackground, shouldShowTextFormattingToolbar };
|
package/editor/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { n as TABLE_CELL_BACKGROUND_PRESETS, t as TABLE_CELL_BACKGROUND_OPTIONS } from "./chunks/table-backgrounds.js";
|
|
2
2
|
import { n as resolveTableCellAt, t as measureTableOverlayGeometry } from "./chunks/ui.js";
|
|
3
|
-
import { A as
|
|
3
|
+
import { A as LOOMA_ACTIVE_BLOCK_CLASS, C as DEFAULT_MENTION_RESULT_LIMIT, D as LOOMA_CALLOUT_TONES, E as normalizeMentionResultLimit, M as LoomaActiveBlock, N as LoomaActiveBlockPluginKey, O as LoomaCallout, S as createLoomaMentionExtension, T as filterLoomaMentionItems, _ as getActiveTableCellBackground, a as handleTableAction, b as LoomaSmartPaste, c as normalizeActiveTableColumnWidths, d as getDefaultEditorExtensions, f as getLoomaTableExtensions, g as getActiveTableCellAlignment, h as LoomaTableHeader, i as getActiveTableUiState, j as LOOMA_ACTIVE_BLOCK_TYPING_IDLE_MS, k as LOOMA_ACTIVE_BLOCK_BLUR_GRACE_MS, l as shouldShowTextFormattingToolbar, m as LoomaTableCell, n as createLoomaSlashCommandExtension, o as handleTableOverlayAction, p as LoomaTable, r as getDefaultSlashCommands, s as insertTableAtRange, t as LoomaSlashCommand, u as LoomaTableKit, v as setActiveTableCellAlignment, w as MAX_MENTION_RESULT_LIMIT, x as LoomaMentionSuggestionPluginKey, y as setActiveTableCellBackground } from "./chunks/extensions.js";
|
|
4
4
|
import { AlignCenter, AlignLeft, AlignRight, Bold, Braces, ChevronDown, ChevronLeft, CircleCheck, CircleX, CodeXml, Columns3, Ellipsis, Eraser, GripHorizontal, GripVertical, Heading1, Heading2, Heading3, Highlighter, Image, Info, Italic, List, ListOrdered, ListTodo, Merge, Minus, NotebookPen, PaintBucket, PanelBottom, PanelLeft, PanelRight, PanelTop, Pilcrow, Plus, Quote, Redo2, Rows3, Split, Strikethrough, Table2, Trash2, TriangleAlert, Underline, Undo2 } from "lucide";
|
|
5
5
|
//#region src/editor/icons.ts
|
|
6
6
|
/** The opinionated Lucide set used by Looma's shipped interaction surfaces. */
|
|
@@ -94,4 +94,4 @@ function getVisualViewportRect(owner = window) {
|
|
|
94
94
|
};
|
|
95
95
|
}
|
|
96
96
|
//#endregion
|
|
97
|
-
export { DEFAULT_MENTION_RESULT_LIMIT, LOOMA_ACTIVE_BLOCK_CLASS, LOOMA_CALLOUT_TONES, LOOMA_ICONS, LoomaActiveBlock, LoomaActiveBlockPluginKey, LoomaCallout, LoomaMentionSuggestionPluginKey, LoomaSlashCommand, LoomaSmartPaste, LoomaTable, LoomaTableCell, LoomaTableHeader, LoomaTableKit, MAX_MENTION_RESULT_LIMIT, TABLE_CELL_BACKGROUND_OPTIONS, TABLE_CELL_BACKGROUND_PRESETS, createLoomaMentionExtension, createLoomaSlashCommandExtension, filterLoomaMentionItems, getActiveTableCellAlignment, getActiveTableCellBackground, getActiveTableUiState, getDefaultEditorExtensions, getDefaultSlashCommands, getLoomaTableExtensions, getVisualViewportRect, handleTableAction, handleTableOverlayAction, insertTableAtRange, loomaIconMarkup, measureTableOverlayGeometry, normalizeActiveTableColumnWidths, normalizeMentionResultLimit, resolveTableCellAt, setActiveTableCellAlignment, setActiveTableCellBackground, shouldShowTextFormattingToolbar };
|
|
97
|
+
export { DEFAULT_MENTION_RESULT_LIMIT, LOOMA_ACTIVE_BLOCK_BLUR_GRACE_MS, LOOMA_ACTIVE_BLOCK_CLASS, LOOMA_ACTIVE_BLOCK_TYPING_IDLE_MS, LOOMA_CALLOUT_TONES, LOOMA_ICONS, LoomaActiveBlock, LoomaActiveBlockPluginKey, LoomaCallout, LoomaMentionSuggestionPluginKey, LoomaSlashCommand, LoomaSmartPaste, LoomaTable, LoomaTableCell, LoomaTableHeader, LoomaTableKit, MAX_MENTION_RESULT_LIMIT, TABLE_CELL_BACKGROUND_OPTIONS, TABLE_CELL_BACKGROUND_PRESETS, createLoomaMentionExtension, createLoomaSlashCommandExtension, filterLoomaMentionItems, getActiveTableCellAlignment, getActiveTableCellBackground, getActiveTableUiState, getDefaultEditorExtensions, getDefaultSlashCommands, getLoomaTableExtensions, getVisualViewportRect, handleTableAction, handleTableOverlayAction, insertTableAtRange, loomaIconMarkup, measureTableOverlayGeometry, normalizeActiveTableColumnWidths, normalizeMentionResultLimit, resolveTableCellAt, setActiveTableCellAlignment, setActiveTableCellBackground, shouldShowTextFormattingToolbar };
|
package/package.json
CHANGED
package/styles/ui-avatar.css
CHANGED
package/styles/ui-button.css
CHANGED
|
@@ -65,13 +65,13 @@
|
|
|
65
65
|
:scope[data-ui-button-state~="size=sm"] {
|
|
66
66
|
min-block-size: var(--ui-control-size-sm);
|
|
67
67
|
padding: var(--ui-space-1) var(--ui-space-2);
|
|
68
|
-
font-size:
|
|
68
|
+
font-size: var(--ui-font-size-sm);
|
|
69
69
|
}
|
|
70
70
|
|
|
71
71
|
:scope[data-ui-button-state~="size=lg"] {
|
|
72
72
|
min-block-size: var(--ui-control-size-lg);
|
|
73
73
|
padding: var(--ui-space-3) var(--ui-space-4);
|
|
74
|
-
font-size:
|
|
74
|
+
font-size: var(--ui-font-size-md);
|
|
75
75
|
}
|
|
76
76
|
|
|
77
77
|
/* A link is never :enabled, so interactive states test "not unavailable" instead: for a button that
|
package/styles/ui-combobox.css
CHANGED
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
}
|
|
10
10
|
label {
|
|
11
11
|
color: var(--ui-combobox-label-text, var(--ui-text-primary));
|
|
12
|
-
font-size: var(--ui-combobox-label-font-size,
|
|
12
|
+
font-size: var(--ui-combobox-label-font-size, var(--ui-font-size-sm));
|
|
13
13
|
font-weight: 500;
|
|
14
14
|
}
|
|
15
15
|
/* The field and anything that annotates it sit on one row; the help button is beside the box,
|
|
@@ -152,7 +152,7 @@
|
|
|
152
152
|
align-items: center;
|
|
153
153
|
justify-content: center;
|
|
154
154
|
font-family: var(--ui-font-family-mono, ui-monospace, monospace);
|
|
155
|
-
font-size:
|
|
155
|
+
font-size: var(--ui-font-size-2xs);
|
|
156
156
|
background: var(--ui-surface-hover);
|
|
157
157
|
border: 1px solid var(--ui-border);
|
|
158
158
|
border-radius: 3px;
|
package/styles/ui-form-field.css
CHANGED
|
@@ -18,12 +18,12 @@
|
|
|
18
18
|
|
|
19
19
|
.label {
|
|
20
20
|
color: var(--ui-text-secondary);
|
|
21
|
-
font-size:
|
|
21
|
+
font-size: var(--ui-font-size-sm);
|
|
22
22
|
}
|
|
23
23
|
|
|
24
24
|
.help {
|
|
25
25
|
color: var(--ui-text-muted);
|
|
26
|
-
font-size:
|
|
26
|
+
font-size: var(--ui-font-size-sm);
|
|
27
27
|
line-height: var(--ui-line-height-md);
|
|
28
28
|
}
|
|
29
29
|
|
|
@@ -43,7 +43,7 @@
|
|
|
43
43
|
.error,
|
|
44
44
|
:where([data-slotted], [data-slotted] *):is([role="alert"]) {
|
|
45
45
|
color: var(--ui-accent-active);
|
|
46
|
-
font-size:
|
|
46
|
+
font-size: var(--ui-font-size-sm);
|
|
47
47
|
}
|
|
48
48
|
|
|
49
49
|
/* A component that sets its display still honours the hidden attribute on its root. */
|
package/styles/ui-tree-item.css
CHANGED
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
align-items: center;
|
|
18
18
|
min-block-size: var(--ui-tree-item-min-block-size, var(--_tree-row-min-height));
|
|
19
19
|
min-inline-size: 0;
|
|
20
|
-
font-size: var(--ui-tree-item-font-size, var(--ui-font-size-
|
|
20
|
+
font-size: var(--ui-tree-item-font-size, var(--ui-font-size-sm));
|
|
21
21
|
border-radius: var(--ui-radius-md);
|
|
22
22
|
color: var(--ui-text-secondary);
|
|
23
23
|
transition:
|
package/tokens.css
CHANGED
|
@@ -36,7 +36,6 @@
|
|
|
36
36
|
"Segoe UI Emoji";
|
|
37
37
|
--ui-font-mono: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, "Liberation Mono", monospace;
|
|
38
38
|
--ui-font-size: 1rem;
|
|
39
|
-
--ui-font-size-sm: 0.875rem;
|
|
40
39
|
--ui-font-medium: 500;
|
|
41
40
|
--ui-line-height: 1.4;
|
|
42
41
|
|
|
@@ -78,8 +77,8 @@
|
|
|
78
77
|
/* Type scale, from the base size. */
|
|
79
78
|
--ui-font-size-2xs: calc(var(--ui-font-size) * 0.6875);
|
|
80
79
|
--ui-font-size-xs: calc(var(--ui-font-size) * 0.75);
|
|
81
|
-
/* Dense
|
|
82
|
-
--ui-font-size-
|
|
80
|
+
/* Dense text: controls, labels, and metadata. Two steps below body copy, never one pixel. */
|
|
81
|
+
--ui-font-size-sm: calc(var(--ui-font-size) * 0.875);
|
|
83
82
|
--ui-font-size-md: var(--ui-font-size);
|
|
84
83
|
--ui-font-size-lg: calc(var(--ui-font-size) * 1.125);
|
|
85
84
|
--ui-font-size-xl: calc(var(--ui-font-size) * 1.25);
|
package/vue/UiAvatar.vue
CHANGED
|
@@ -62,7 +62,7 @@ useComponentHost(controllerModule.default, {
|
|
|
62
62
|
background: var(--ui-avatar-surface, var(--ui-accent-soft));
|
|
63
63
|
color: var(--ui-avatar-text, var(--ui-accent-solid));
|
|
64
64
|
font: inherit;
|
|
65
|
-
font-size:
|
|
65
|
+
font-size: var(--ui-font-size-sm);
|
|
66
66
|
font-weight: 600;
|
|
67
67
|
text-transform: uppercase;
|
|
68
68
|
}
|
package/vue/UiAvatarGroup.vue
CHANGED
|
@@ -85,7 +85,7 @@ useComponentHost(controllerModule.default, {
|
|
|
85
85
|
var(--ui-avatar-group-overlap-shadow, var(--_overlap-shadow)),
|
|
86
86
|
var(--ui-avatar-group-edge-ring, var(--_edge-ring));
|
|
87
87
|
font: inherit;
|
|
88
|
-
font-size:
|
|
88
|
+
font-size: var(--ui-font-size-xs);
|
|
89
89
|
font-weight: 600;
|
|
90
90
|
flex-shrink: 0;
|
|
91
91
|
}
|
package/vue/UiButton.vue
CHANGED
|
@@ -140,13 +140,13 @@ function attribute(value: unknown): any {
|
|
|
140
140
|
[data-component~="ui-button"][data-ui-button-state~="size=sm"] {
|
|
141
141
|
min-block-size: var(--ui-control-size-sm);
|
|
142
142
|
padding: var(--ui-space-1) var(--ui-space-2);
|
|
143
|
-
font-size:
|
|
143
|
+
font-size: var(--ui-font-size-sm);
|
|
144
144
|
}
|
|
145
145
|
|
|
146
146
|
[data-component~="ui-button"][data-ui-button-state~="size=lg"] {
|
|
147
147
|
min-block-size: var(--ui-control-size-lg);
|
|
148
148
|
padding: var(--ui-space-3) var(--ui-space-4);
|
|
149
|
-
font-size:
|
|
149
|
+
font-size: var(--ui-font-size-md);
|
|
150
150
|
}
|
|
151
151
|
|
|
152
152
|
/* A link is never :enabled, so interactive states test "not unavailable" instead: for a button that
|
package/vue/UiCombobox.vue
CHANGED
|
@@ -648,7 +648,7 @@ defineExpose({
|
|
|
648
648
|
}
|
|
649
649
|
label {
|
|
650
650
|
color: var(--ui-combobox-label-text, var(--ui-text-primary));
|
|
651
|
-
font-size: var(--ui-combobox-label-font-size,
|
|
651
|
+
font-size: var(--ui-combobox-label-font-size, var(--ui-font-size-sm));
|
|
652
652
|
font-weight: 500;
|
|
653
653
|
}
|
|
654
654
|
/* The field and anything that annotates it sit on one row; the help button is beside the box,
|
|
@@ -246,7 +246,7 @@ useComponentHost(controllerModule.default, {
|
|
|
246
246
|
align-items: center;
|
|
247
247
|
justify-content: center;
|
|
248
248
|
font-family: var(--ui-font-family-mono, ui-monospace, monospace);
|
|
249
|
-
font-size:
|
|
249
|
+
font-size: var(--ui-font-size-2xs);
|
|
250
250
|
background: var(--ui-surface-hover);
|
|
251
251
|
border: 1px solid var(--ui-border);
|
|
252
252
|
border-radius: 3px;
|
|
@@ -260,7 +260,7 @@ useComponentHost(controllerModule.default, {
|
|
|
260
260
|
|
|
261
261
|
.heading {
|
|
262
262
|
padding: var(--ui-space-1) var(--ui-space-2);
|
|
263
|
-
font-size:
|
|
263
|
+
font-size: var(--ui-font-size-2xs);
|
|
264
264
|
font-weight: 700;
|
|
265
265
|
letter-spacing: 0.05em;
|
|
266
266
|
text-transform: uppercase;
|
|
@@ -356,7 +356,7 @@ useComponentHost(controllerModule.default, {
|
|
|
356
356
|
|
|
357
357
|
.menu-heading {
|
|
358
358
|
padding: var(--ui-space-1) var(--ui-space-2);
|
|
359
|
-
font-size:
|
|
359
|
+
font-size: var(--ui-font-size-2xs);
|
|
360
360
|
font-weight: 700;
|
|
361
361
|
letter-spacing: 0.05em;
|
|
362
362
|
text-transform: uppercase;
|