@nerd-bible/wordgard 0.5.3-beta7 → 0.6.2-beta1
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/dist/command.js +11 -10
- package/dist/doc.d.ts +45 -48
- package/dist/doc.js +131 -128
- package/dist/editor.d.ts +190 -104
- package/dist/editor.js +1935 -1583
- package/dist/highlight-code.d.ts +249 -0
- package/dist/highlight-code.js +264 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/dist/phrases.d.ts +3 -2
- package/dist/phrases.js +20 -1
- package/dist/schema.d.ts +37 -1
- package/dist/schema.js +154 -127
- package/dist/set.js +5 -4
- package/dist/state.d.ts +68 -22
- package/dist/state.js +137 -107
- package/dist/table.d.ts +3 -2
- package/dist/table.js +32 -14
- package/package.json +3 -2
package/dist/editor.js
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
import { GardState, GardSelection, TextblockMap, BidiSpan, Transaction } from 'wordgard/state';
|
|
2
|
-
import { Attributes, Elt, Node, Leaf, parse, Slice, Plot, serialize, Pos, ChangeSet, ValidationError
|
|
2
|
+
import { Attributes, Elt, Node, Mark, Leaf, parse, Slice, Plot, serialize, Pos, ChangeSet, ValidationError } from 'wordgard/doc';
|
|
3
3
|
import { StyleModule } from 'style-mod';
|
|
4
4
|
import { findClusterBreak } from '@marijn/find-cluster-break';
|
|
5
5
|
import { findAbove, PointSet, RangeSet } from 'wordgard/set';
|
|
6
6
|
import { enter, insertLineBreak, selectAll, undo, redo, killToLineEnd, yankKilled, transposeChars, Command, deleteUnit, deleteWord, deleteToLineEnd, moveByUnit, moveByLine, moveByWord, moveToLineSide, moveToDocSide, moveByPage, moveToTextblockSide, setAlignment, toggleUnderline, toggleEmphasis, toggleStrong, deleteLine, insertText, setDirection, deleteSelection, Menu, findWrappable, wrapBlockRange, autoJoinBlocks } from 'wordgard/command';
|
|
7
|
-
import {
|
|
7
|
+
import { phrases, PhraseSet } from 'wordgard/phrases';
|
|
8
|
+
import cr from 'crelt';
|
|
8
9
|
import { history } from 'wordgard/history';
|
|
9
10
|
|
|
10
11
|
function addUpdated(sections, updated) {
|
|
@@ -211,19 +212,19 @@ const Decoration = /*@__PURE__*/(function (Decoration) {
|
|
|
211
212
|
function shape(type, shape, config) {
|
|
212
213
|
let tp = Node.Type.get(type);
|
|
213
214
|
let shapeFunc = typeof shape == "function"
|
|
214
|
-
? tag =>
|
|
215
|
-
:
|
|
215
|
+
? memo(tag => shape(tag))
|
|
216
|
+
: () => shape;
|
|
216
217
|
let atom = typeof shape == "function" ? config?.atom : !shape.hasContent;
|
|
217
|
-
let ext = tagShape.of({ type: tp, shape:
|
|
218
|
+
let ext = tagShape.of({ type: tp, shape: shapeFunc });
|
|
218
219
|
if (tp.isPlot && atom != null)
|
|
219
220
|
ext = [ext, GardState.isAtom.of([tp, atom])];
|
|
220
221
|
return ext;
|
|
221
222
|
}
|
|
222
223
|
Tag.shape = shape;
|
|
223
224
|
(function (shape_1) {
|
|
224
|
-
function
|
|
225
|
+
function derived(type, shape, config) {
|
|
225
226
|
let tp = Node.Type.get(type);
|
|
226
|
-
let ext = tagShape.
|
|
227
|
+
let ext = tagShape.derive(state => {
|
|
227
228
|
let s = shape(state);
|
|
228
229
|
return { type: tp, shape: typeof s == "function" ? memo(s) : () => s };
|
|
229
230
|
});
|
|
@@ -232,7 +233,7 @@ const Decoration = /*@__PURE__*/(function (Decoration) {
|
|
|
232
233
|
ext = [ext, GardState.isAtom.of([tp, atom])];
|
|
233
234
|
return ext;
|
|
234
235
|
}
|
|
235
|
-
shape_1.
|
|
236
|
+
shape_1.derived = derived;
|
|
236
237
|
})(shape = Tag.shape || (Tag.shape = {}));
|
|
237
238
|
function wrapper(type, wrapper, options) {
|
|
238
239
|
if (!wrapper.hasContent)
|
|
@@ -256,10 +257,10 @@ const Decoration = /*@__PURE__*/(function (Decoration) {
|
|
|
256
257
|
}
|
|
257
258
|
Tag.widget = widget;
|
|
258
259
|
(function (widget_1) {
|
|
259
|
-
function
|
|
260
|
+
function derived(type, place, widget) {
|
|
260
261
|
let tp = Node.Type.get(type);
|
|
261
262
|
let p = getPlace(place);
|
|
262
|
-
return tagWidget.
|
|
263
|
+
return tagWidget.derive(state => {
|
|
263
264
|
let w = widget(state);
|
|
264
265
|
return {
|
|
265
266
|
type: tp,
|
|
@@ -268,7 +269,7 @@ const Decoration = /*@__PURE__*/(function (Decoration) {
|
|
|
268
269
|
};
|
|
269
270
|
});
|
|
270
271
|
}
|
|
271
|
-
widget_1.
|
|
272
|
+
widget_1.derived = derived;
|
|
272
273
|
})(widget = Tag.widget || (Tag.widget = {}));
|
|
273
274
|
function attribute(type, attr, value, options) {
|
|
274
275
|
let tp = Node.Type.get(type);
|
|
@@ -277,6 +278,16 @@ const Decoration = /*@__PURE__*/(function (Decoration) {
|
|
|
277
278
|
}
|
|
278
279
|
Tag.attribute = attribute;
|
|
279
280
|
})(Decoration.Tag || (Decoration.Tag = {}));
|
|
281
|
+
(function (Mark$1) {
|
|
282
|
+
function shape(type, shape) {
|
|
283
|
+
if (type instanceof Mark)
|
|
284
|
+
type = type.type;
|
|
285
|
+
if (type.spanning && !("element" in shape))
|
|
286
|
+
throw new Error("Spanning marks must have an element shape");
|
|
287
|
+
return markShape.of({ type, modified: Mark.Type.define(type.name, { ...type.spec, shape }) });
|
|
288
|
+
}
|
|
289
|
+
Mark$1.shape = shape;
|
|
290
|
+
})(Decoration.Mark || (Decoration.Mark = {}));
|
|
280
291
|
class Point {
|
|
281
292
|
constructor() { }
|
|
282
293
|
static widget(widget, options) {
|
|
@@ -324,10 +335,15 @@ const Decoration = /*@__PURE__*/(function (Decoration) {
|
|
|
324
335
|
}
|
|
325
336
|
Decoration.Range = Range;
|
|
326
337
|
;return Decoration})({});
|
|
327
|
-
const tagShape = /*@__PURE__*/GardState.Facet.define(
|
|
338
|
+
const tagShape = /*@__PURE__*/GardState.Facet.define({
|
|
339
|
+
combine: shapes => new Map(shapes.map(s => [s.type, s.shape]).reverse())
|
|
340
|
+
});
|
|
328
341
|
const tagWrapper = /*@__PURE__*/GardState.Facet.define();
|
|
329
342
|
const tagWidget = /*@__PURE__*/GardState.Facet.define();
|
|
330
343
|
const tagAttribute = /*@__PURE__*/GardState.Facet.define();
|
|
344
|
+
const markShape = /*@__PURE__*/GardState.Facet.define({
|
|
345
|
+
combine: shapes => new Map(shapes.map(s => [s.type, s.modified]).reverse())
|
|
346
|
+
});
|
|
331
347
|
function memo(f) {
|
|
332
348
|
let map = new WeakMap();
|
|
333
349
|
return (arg) => {
|
|
@@ -337,11 +353,12 @@ function memo(f) {
|
|
|
337
353
|
return found;
|
|
338
354
|
};
|
|
339
355
|
}
|
|
340
|
-
function addMarkAttributes(shape, tag) {
|
|
356
|
+
function addMarkAttributes(overrides, shape, tag) {
|
|
341
357
|
let attrs;
|
|
342
358
|
for (let mark of tag.marks) {
|
|
343
|
-
|
|
344
|
-
|
|
359
|
+
let type = overrides.get(mark.type) || mark.type;
|
|
360
|
+
if (type.attribute && (mark.spanning || !tag.isText)) {
|
|
361
|
+
let { get, target } = type.attribute;
|
|
345
362
|
let markAttrs = get(mark.value);
|
|
346
363
|
if (markAttrs.length) {
|
|
347
364
|
if (target && shape instanceof Elt)
|
|
@@ -367,13 +384,15 @@ function applyDeco(shape, deco, tag) {
|
|
|
367
384
|
return shape;
|
|
368
385
|
}
|
|
369
386
|
const baseTagShape = /*@__PURE__*/memo((tag) => {
|
|
370
|
-
return
|
|
371
|
-
: tag.type.shape.create(tag.param), tag);
|
|
387
|
+
return tag.is(Leaf.Text) ? Widget.editableText.of(tag.param) : tag.type.shape.create(tag.param);
|
|
372
388
|
});
|
|
373
|
-
function renderMarks(marks, around) {
|
|
374
|
-
let
|
|
389
|
+
function renderMarks(state, marks, around) {
|
|
390
|
+
let markShapes = state.facet(markShape);
|
|
391
|
+
let result = addMarkAttributes(markShapes, Elt.create("span", Attributes.none, [around]), Leaf.text(around, marks));
|
|
375
392
|
for (let i = marks.length - 1; i >= 0; i--) {
|
|
376
|
-
let mark = marks[i];
|
|
393
|
+
let mark = marks[i], shape = markShapes.get(mark.type);
|
|
394
|
+
if (shape)
|
|
395
|
+
mark = shape.of(mark.value);
|
|
377
396
|
if (mark.type.element)
|
|
378
397
|
result = renderMarkWrapper(mark).fill([result]);
|
|
379
398
|
}
|
|
@@ -494,13 +513,10 @@ function compareDecoSet(setA, setB, cmp) {
|
|
|
494
513
|
if (!setA.has(srcB))
|
|
495
514
|
cmp(null, valB);
|
|
496
515
|
}
|
|
497
|
-
|
|
498
|
-
return stateA.facet(facet) != stateB.facet(facet);
|
|
499
|
-
}
|
|
516
|
+
const globalDecoFacets = [tagShape, tagWidget, tagWrapper, tagAttribute, markShape];
|
|
500
517
|
function findChangedRanges(prevState, prevDeco, state, deco, sections) {
|
|
501
518
|
let result = [];
|
|
502
|
-
let globalChange =
|
|
503
|
-
compareGlobal(prevState, state, tagWrapper) || compareGlobal(prevState, state, tagAttribute);
|
|
519
|
+
let globalChange = globalDecoFacets.some(facet => prevState.facet(facet) !== state.facet(facet));
|
|
504
520
|
let shapeChanges = [];
|
|
505
521
|
for (let i = 0, posA = 0, posB = 0; i < sections.length;) {
|
|
506
522
|
let len = sections[i++], ins = sections[i++];
|
|
@@ -652,24 +668,6 @@ class SpanIterator {
|
|
|
652
668
|
return this;
|
|
653
669
|
}
|
|
654
670
|
}
|
|
655
|
-
function nodeWrappers(schema, tag, active, atom) {
|
|
656
|
-
let wrappers;
|
|
657
|
-
for (let mark of tag.marks)
|
|
658
|
-
if (mark.type.element)
|
|
659
|
-
(wrappers || (wrappers = [])).push(mark);
|
|
660
|
-
if (active.length) {
|
|
661
|
-
for (let val of active) {
|
|
662
|
-
if (val instanceof WrapperRangeDecoration && (tagScope(tag, atom) & val.scope) &&
|
|
663
|
-
(!val.query || schema.matchNode(tag.type, val.query)))
|
|
664
|
-
(wrappers || (wrappers = [])).push(val);
|
|
665
|
-
}
|
|
666
|
-
}
|
|
667
|
-
if (!wrappers)
|
|
668
|
-
return none;
|
|
669
|
-
if (wrappers.length > 1)
|
|
670
|
-
wrappers.sort((a, b) => (a.spanning == b.spanning ? 0 : a.spanning ? -1 : 1) || a.rank - b.rank);
|
|
671
|
-
return wrappers;
|
|
672
|
-
}
|
|
673
671
|
function tagScope(tag, atom) {
|
|
674
672
|
return 4 |
|
|
675
673
|
(atom ? 1 | (tag.type.isInline ? 2 : 0) : 0);
|
|
@@ -690,6 +688,7 @@ class DecoIterator {
|
|
|
690
688
|
globalWidgets;
|
|
691
689
|
globalWrappers;
|
|
692
690
|
globalAttrs;
|
|
691
|
+
markShapes;
|
|
693
692
|
schema;
|
|
694
693
|
pos;
|
|
695
694
|
rangeCursor;
|
|
@@ -705,6 +704,7 @@ class DecoIterator {
|
|
|
705
704
|
.some(w => (w.place == 1 || w.place == 3) && typeof w.widget == "function");
|
|
706
705
|
this.globalWrappers = state.facet(tagWrapper);
|
|
707
706
|
this.globalAttrs = state.facet(tagAttribute);
|
|
707
|
+
this.markShapes = state.facet(markShape);
|
|
708
708
|
this.pos = state.doc.resolve(0);
|
|
709
709
|
this.schema = state.schema;
|
|
710
710
|
this.rangeCursor = RangeSet.cursor(state.facet(Decoration.Range.source).map(s => s(state)));
|
|
@@ -729,6 +729,26 @@ class DecoIterator {
|
|
|
729
729
|
(tw.place == 3 || tw.place == 1) &&
|
|
730
730
|
typeof tw.widget == "function");
|
|
731
731
|
}
|
|
732
|
+
nodeWrappers(tag, active, atom) {
|
|
733
|
+
let wrappers;
|
|
734
|
+
for (let mark of tag.marks) {
|
|
735
|
+
let shape = this.markShapes.get(mark.type) || mark.type;
|
|
736
|
+
if (shape.element)
|
|
737
|
+
(wrappers || (wrappers = [])).push(shape == mark.type ? mark : shape.of(mark.value));
|
|
738
|
+
}
|
|
739
|
+
if (active.length) {
|
|
740
|
+
for (let val of active) {
|
|
741
|
+
if (val instanceof WrapperRangeDecoration && (tagScope(tag, atom) & val.scope) &&
|
|
742
|
+
(!val.query || this.schema.matchNode(tag.type, val.query)))
|
|
743
|
+
(wrappers || (wrappers = [])).push(val);
|
|
744
|
+
}
|
|
745
|
+
}
|
|
746
|
+
if (!wrappers)
|
|
747
|
+
return none;
|
|
748
|
+
if (wrappers.length > 1)
|
|
749
|
+
wrappers.sort((a, b) => (a.spanning == b.spanning ? 0 : a.spanning ? -1 : 1) || a.rank - b.rank);
|
|
750
|
+
return wrappers;
|
|
751
|
+
}
|
|
732
752
|
walk(from, inclusiveStart, to, walker) {
|
|
733
753
|
this.rangeCursor.goto(from);
|
|
734
754
|
this.pointCursor.goto(from, inclusiveStart ? -1e9 : 1000000000);
|
|
@@ -753,7 +773,7 @@ class DecoIterator {
|
|
|
753
773
|
shape = applyDeco(shape, deco, node.tag);
|
|
754
774
|
if (shape.hasContent)
|
|
755
775
|
throw new Error("Leaf nodes shapes shouldn't have a content hole");
|
|
756
|
-
walker.node(node, shape, nodeWrappers(
|
|
776
|
+
walker.node(node, shape, this.nodeWrappers(node.tag, iter.active, true), undefined);
|
|
757
777
|
this.widgets(node.tag, 1, walker);
|
|
758
778
|
},
|
|
759
779
|
enterPlot: (node, pos) => {
|
|
@@ -766,7 +786,7 @@ class DecoIterator {
|
|
|
766
786
|
if (pendingPos == pos)
|
|
767
787
|
for (let deco of pendingDeco)
|
|
768
788
|
shape = applyDeco(shape, deco, node.tag);
|
|
769
|
-
let wrappers = nodeWrappers(
|
|
789
|
+
let wrappers = this.nodeWrappers(node.tag, iter.active, !shape.hasContent);
|
|
770
790
|
let atom = !shape.hasContent;
|
|
771
791
|
if (atom)
|
|
772
792
|
walker.node(node, shape, wrappers, pos + node.length > to ? to - pos : undefined);
|
|
@@ -842,15 +862,10 @@ class DecoIterator {
|
|
|
842
862
|
this.pos = pos;
|
|
843
863
|
}
|
|
844
864
|
tagShape(tag, active) {
|
|
845
|
-
let
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
shape = src.shape(tag);
|
|
850
|
-
break;
|
|
851
|
-
}
|
|
852
|
-
if (!shape)
|
|
853
|
-
shape = baseTagShape(tag);
|
|
865
|
+
let override = this.tagShapes.get(tag.type);
|
|
866
|
+
let shape = override ? override(tag) : baseTagShape(tag);
|
|
867
|
+
if (tag.marks.length)
|
|
868
|
+
shape = addMarkAttributes(this.markShapes, shape, tag);
|
|
854
869
|
let add;
|
|
855
870
|
for (let src of this.globalAttrs)
|
|
856
871
|
if (tag.type == src.type) {
|
|
@@ -1423,6 +1438,13 @@ class CompositeTile extends Tile {
|
|
|
1423
1438
|
return null;
|
|
1424
1439
|
let { closest, rect } = result;
|
|
1425
1440
|
let pos = this.posBeforeChild(closest, start);
|
|
1441
|
+
if (textblock && textblock.start == start && (x < rect.left || x > rect.right)) {
|
|
1442
|
+
let start = (x < rect.left) == textblock.ltr;
|
|
1443
|
+
let span = start ? textblock.order[0] : textblock.order[textblock.order.length - 1];
|
|
1444
|
+
if (span.ltr != textblock.ltr && pos >= span.from + textblock.start && pos <= span.to + textblock.start)
|
|
1445
|
+
return start ? CoordPos.create(textblock.start, -1)
|
|
1446
|
+
: CoordPos.create(textblock.start + textblock.node.contentLength, 1);
|
|
1447
|
+
}
|
|
1426
1448
|
if (closest.dom.nodeName == "BR")
|
|
1427
1449
|
return CoordPos.create(pos, 1);
|
|
1428
1450
|
if (closest.tag && closest.tag.isPlot && closest.tag.type.isInline) {
|
|
@@ -1949,7 +1971,7 @@ class TilePointer {
|
|
|
1949
1971
|
}
|
|
1950
1972
|
tileAfter() {
|
|
1951
1973
|
let { tile, index } = this;
|
|
1952
|
-
if (tile.
|
|
1974
|
+
if (tile.isAtom)
|
|
1953
1975
|
return tile;
|
|
1954
1976
|
return index < tile.children.length ? tile.children[index] : null;
|
|
1955
1977
|
}
|
|
@@ -1975,25 +1997,26 @@ class TilePointer {
|
|
|
1975
1997
|
}
|
|
1976
1998
|
matchingWidget(widget, sideFlag, reused) {
|
|
1977
1999
|
let { index, tile, parent } = this;
|
|
1978
|
-
|
|
1979
|
-
|
|
1980
|
-
if (!
|
|
1981
|
-
|
|
1982
|
-
|
|
1983
|
-
|
|
1984
|
-
|
|
1985
|
-
|
|
1986
|
-
|
|
1987
|
-
|
|
1988
|
-
|
|
1989
|
-
|
|
1990
|
-
|
|
1991
|
-
(before
|
|
1992
|
-
|
|
1993
|
-
|
|
2000
|
+
if (!tile.isAtom)
|
|
2001
|
+
for (;;) {
|
|
2002
|
+
if (!index) {
|
|
2003
|
+
if (!parent || (tile instanceof EltTile ? tile.tag : !(tile instanceof TextTile)))
|
|
2004
|
+
break;
|
|
2005
|
+
({ index, tile, parent } = parent);
|
|
2006
|
+
}
|
|
2007
|
+
else {
|
|
2008
|
+
if (tile instanceof TextTile)
|
|
2009
|
+
break;
|
|
2010
|
+
let before = tile.children[--index];
|
|
2011
|
+
if (!before.isPoint)
|
|
2012
|
+
break;
|
|
2013
|
+
if (!reused.has(before) && before instanceof WidgetTile && before.widget.eq(widget) &&
|
|
2014
|
+
(before.flags & 96) == sideFlag && !(before.flags & 8192)) {
|
|
2015
|
+
reused.set(before, 1);
|
|
2016
|
+
return before;
|
|
2017
|
+
}
|
|
1994
2018
|
}
|
|
1995
2019
|
}
|
|
1996
|
-
}
|
|
1997
2020
|
return null;
|
|
1998
2021
|
}
|
|
1999
2022
|
}
|
|
@@ -2093,7 +2116,7 @@ class ContentUpdate {
|
|
|
2093
2116
|
let cut = [], end = this.posB + len;
|
|
2094
2117
|
if (this.deco.endWidgets)
|
|
2095
2118
|
for (let nw = this.new, { tile, index, parent } = this.old, pos = this.posB; pos < end;) {
|
|
2096
|
-
if (tile
|
|
2119
|
+
if (tile.isAtom) {
|
|
2097
2120
|
pos += tile.length - index;
|
|
2098
2121
|
({ tile, index, parent } = parent);
|
|
2099
2122
|
index++;
|
|
@@ -2543,6 +2566,16 @@ class Coords {
|
|
|
2543
2566
|
}
|
|
2544
2567
|
}
|
|
2545
2568
|
function coordsAtPos(wg, pos, assoc) {
|
|
2569
|
+
let textblock = wg.state.doc.resolve(pos).textblockParent;
|
|
2570
|
+
let map = textblock ? wg.state.textblockMap(textblock) : null;
|
|
2571
|
+
if (textblock && textblock.node.contentLength &&
|
|
2572
|
+
(pos == textblock.start && assoc < 0 || pos == textblock.end && assoc > 0)) {
|
|
2573
|
+
let span = map.order[pos == textblock.start ? 0 : map.order.length - 1];
|
|
2574
|
+
if (span.ltr != map.ltr)
|
|
2575
|
+
pos = textblock.start + (pos == textblock.start ? span.to : span.from);
|
|
2576
|
+
else
|
|
2577
|
+
assoc = -assoc;
|
|
2578
|
+
}
|
|
2546
2579
|
let { offset, tile, pos: tilePos } = wg.docTile.resolve(pos, assoc);
|
|
2547
2580
|
if (tile instanceof TextTile) {
|
|
2548
2581
|
let from = offset, to = offset;
|
|
@@ -2551,7 +2584,7 @@ function coordsAtPos(wg, pos, assoc) {
|
|
|
2551
2584
|
to++;
|
|
2552
2585
|
else
|
|
2553
2586
|
from--;
|
|
2554
|
-
return new Coords(tile, flattenV(singleRect(textRange(tile.dom, from, to), side, true), (side < 0) == ltrAt(wg.state, pos, assoc)));
|
|
2587
|
+
return new Coords(tile, flattenV(singleRect(textRange(tile.dom, from, to), side, true), (side < 0) == ltrAt(wg.state, pos, assoc, map)));
|
|
2555
2588
|
}
|
|
2556
2589
|
let tagTile = tile;
|
|
2557
2590
|
while (!tagTile.tag)
|
|
@@ -2562,7 +2595,7 @@ function coordsAtPos(wg, pos, assoc) {
|
|
|
2562
2595
|
if (tile.widget.type.inFlow) {
|
|
2563
2596
|
let rect = singleRect(tile.dom, after ? 1 : -1);
|
|
2564
2597
|
if (rect.width || rect.height)
|
|
2565
|
-
return new Coords(tile, horizontal ? flattenH(rect, !after) : flattenV(rect, ltrAt(wg.state, pos, 1) == !after));
|
|
2598
|
+
return new Coords(tile, horizontal ? flattenH(rect, !after) : flattenV(rect, ltrAt(wg.state, pos, 1, map) == !after));
|
|
2566
2599
|
}
|
|
2567
2600
|
if (!tile.parent)
|
|
2568
2601
|
return new Coords(tile, new DOMRect);
|
|
@@ -2579,7 +2612,7 @@ function coordsAtPos(wg, pos, assoc) {
|
|
|
2579
2612
|
break;
|
|
2580
2613
|
let rect = singleRect(before.dom, 1);
|
|
2581
2614
|
if (rect.width || rect.height)
|
|
2582
|
-
return new Coords(before, horizontal ? flattenH(rect, false) : flattenV(rect, !ltrAt(wg.state, pos, 1)));
|
|
2615
|
+
return new Coords(before, horizontal ? flattenH(rect, false) : flattenV(rect, !ltrAt(wg.state, pos, 1, map)));
|
|
2583
2616
|
}
|
|
2584
2617
|
}
|
|
2585
2618
|
else { for (let i = offset; i < tile.children.length; i++) {
|
|
@@ -2588,7 +2621,7 @@ function coordsAtPos(wg, pos, assoc) {
|
|
|
2588
2621
|
continue;
|
|
2589
2622
|
let rect = singleRect(after.dom, -1);
|
|
2590
2623
|
if (rect.width || rect.height)
|
|
2591
|
-
return new Coords(after, horizontal ? flattenH(rect, true) : flattenV(rect, ltrAt(wg.state, pos, 1)));
|
|
2624
|
+
return new Coords(after, horizontal ? flattenH(rect, true) : flattenV(rect, ltrAt(wg.state, pos, 1, map)));
|
|
2592
2625
|
}
|
|
2593
2626
|
}
|
|
2594
2627
|
}
|
|
@@ -2632,19 +2665,18 @@ const clipboardInputFilter = /*@__PURE__*/GardState.Facet.define();
|
|
|
2632
2665
|
const clipboardInputHTMLFilter = /*@__PURE__*/GardState.Facet.define();
|
|
2633
2666
|
const clipboardTextParser = /*@__PURE__*/GardState.Facet.define();
|
|
2634
2667
|
const clipboardInputTextFilter = /*@__PURE__*/GardState.Facet.define();
|
|
2635
|
-
function writeClipboard(state, slice,
|
|
2668
|
+
function writeClipboard(state, slice, data) {
|
|
2636
2669
|
for (let filter of state.facet(clipboardOutputFilter))
|
|
2637
2670
|
slice = filter(slice, state);
|
|
2638
2671
|
let includeContext = 0;
|
|
2639
|
-
for (let i = 0; i < context.length; i++) {
|
|
2640
|
-
let next = context[i];
|
|
2641
|
-
if (next.type.defining && (!includeContext || next.type != context[includeContext - 1].type))
|
|
2672
|
+
for (let i = 0; i < slice.context.length; i++) {
|
|
2673
|
+
let next = slice.context[i];
|
|
2674
|
+
if (next.type.defining && (!includeContext || next.type != slice.context[includeContext - 1].type))
|
|
2642
2675
|
includeContext = i + 1;
|
|
2643
2676
|
else if (next.type.defining || !next.isTextblock)
|
|
2644
2677
|
break;
|
|
2645
2678
|
}
|
|
2646
2679
|
let doc = detachedDoc(), dom = serialize.slice(slice, {
|
|
2647
|
-
context,
|
|
2648
2680
|
includeContext,
|
|
2649
2681
|
openAttr: "wg-open"
|
|
2650
2682
|
}).toDOM();
|
|
@@ -2668,7 +2700,7 @@ function writeClipboard(state, slice, context, data) {
|
|
|
2668
2700
|
data.setData("text/html", html);
|
|
2669
2701
|
let text;
|
|
2670
2702
|
for (let serialize of state.facet(clipboardTextSerializer)) {
|
|
2671
|
-
if ((text = serialize(slice,
|
|
2703
|
+
if ((text = serialize(slice, state)) != null)
|
|
2672
2704
|
break;
|
|
2673
2705
|
}
|
|
2674
2706
|
if (text == null)
|
|
@@ -2683,7 +2715,7 @@ function isOpen(elt) {
|
|
|
2683
2715
|
function readClipboard(state, data, targetContext, plain) {
|
|
2684
2716
|
let html = data.getData("text/html");
|
|
2685
2717
|
let text = data.getData("text/plain") || data.getData("Text") || data.getData("text/uri-list").replace(/\r?\n/g, " ");
|
|
2686
|
-
let slice
|
|
2718
|
+
let slice;
|
|
2687
2719
|
if (text && (targetContext.parent.node.type.hasRole(Node.Role.Code) || !html || plain)) {
|
|
2688
2720
|
for (let filter of state.facet(clipboardInputTextFilter))
|
|
2689
2721
|
text = filter(text, state);
|
|
@@ -2699,14 +2731,14 @@ function readClipboard(state, data, targetContext, plain) {
|
|
|
2699
2731
|
if (browser.webkit)
|
|
2700
2732
|
restoreReplacedSpaces(dom);
|
|
2701
2733
|
let fromWordgard = dom.querySelector("[wg-content=true]");
|
|
2702
|
-
|
|
2734
|
+
slice = parse.slice(state.schema, dom, {
|
|
2703
2735
|
collapseWhiteSpace: !fromWordgard,
|
|
2704
2736
|
isOpen: fromWordgard ? isOpen : undefined
|
|
2705
|
-
})
|
|
2737
|
+
});
|
|
2706
2738
|
}
|
|
2707
2739
|
for (let filter of state.facet(clipboardInputFilter))
|
|
2708
2740
|
slice = filter(slice, state);
|
|
2709
|
-
return
|
|
2741
|
+
return slice;
|
|
2710
2742
|
}
|
|
2711
2743
|
function readClipboardText(state, text, context, plain) {
|
|
2712
2744
|
if (!plain)
|
|
@@ -2839,7 +2871,6 @@ const baseStyles = /*@__PURE__*/buildTheme("." + styleID, {
|
|
|
2839
2871
|
whiteSpace: "pre-wrap",
|
|
2840
2872
|
overflowWrap: "anywhere",
|
|
2841
2873
|
wordBreak: "break-word", boxSizing: "border-box",
|
|
2842
|
-
minHeight: "100%",
|
|
2843
2874
|
padding: "4px 12px",
|
|
2844
2875
|
outline: "none",
|
|
2845
2876
|
caretColor: "transparent",
|
|
@@ -2924,14 +2955,26 @@ const baseStyles = /*@__PURE__*/buildTheme("." + styleID, {
|
|
|
2924
2955
|
},
|
|
2925
2956
|
".wg-panels-top": { top: "0" },
|
|
2926
2957
|
".wg-panels-bottom": { bottom: "0" },
|
|
2927
|
-
|
|
2928
|
-
|
|
2929
|
-
padding: "
|
|
2930
|
-
|
|
2931
|
-
"
|
|
2932
|
-
|
|
2933
|
-
|
|
2934
|
-
|
|
2958
|
+
dialog: {
|
|
2959
|
+
font: "var(--wg-dialog-font)",
|
|
2960
|
+
padding: "7px 22px 7px 8px",
|
|
2961
|
+
minWidth: "120px",
|
|
2962
|
+
border: "1px solid var(--wg-border-color)",
|
|
2963
|
+
borderRadius: "5px",
|
|
2964
|
+
boxShadow: "0 0 8px 0 rgba(128, 128, 128, 0.2)",
|
|
2965
|
+
inset: "unset",
|
|
2966
|
+
"&.wg-free-dialog": {
|
|
2967
|
+
position: "fixed"
|
|
2968
|
+
}
|
|
2969
|
+
},
|
|
2970
|
+
"h3.wg-dialog-title": {
|
|
2971
|
+
fontSize: "90%",
|
|
2972
|
+
fontWeight: "bold",
|
|
2973
|
+
textAlign: "center",
|
|
2974
|
+
margin: "0 0 0.8em"
|
|
2975
|
+
},
|
|
2976
|
+
"dialog label, dialog .wg-label": {
|
|
2977
|
+
fontSize: "90%"
|
|
2935
2978
|
},
|
|
2936
2979
|
".wg-dialog-close": {
|
|
2937
2980
|
position: "absolute",
|
|
@@ -2961,6 +3004,24 @@ const baseStyles = /*@__PURE__*/buildTheme("." + styleID, {
|
|
|
2961
3004
|
backgroundColor: "#222"
|
|
2962
3005
|
}
|
|
2963
3006
|
},
|
|
3007
|
+
".wg-key-help": {
|
|
3008
|
+
padding: "15px 4px 4px",
|
|
3009
|
+
maxWidth: "350px"
|
|
3010
|
+
},
|
|
3011
|
+
".wg-key-list": {
|
|
3012
|
+
padding: "11px",
|
|
3013
|
+
outline: "none",
|
|
3014
|
+
maxHeight: "calc(min(70vh, 300px))",
|
|
3015
|
+
overflowY: "auto",
|
|
3016
|
+
display: "grid",
|
|
3017
|
+
gridTemplateColumns: "max-content auto",
|
|
3018
|
+
gap: "8px 15px",
|
|
3019
|
+
"& h4": {
|
|
3020
|
+
gridColumn: "span 2",
|
|
3021
|
+
margin: "0.5em 0",
|
|
3022
|
+
fontSize: "110%"
|
|
3023
|
+
}
|
|
3024
|
+
}
|
|
2964
3025
|
}, lightDarkIDs);
|
|
2965
3026
|
|
|
2966
3027
|
function setDOMSelection(wg) {
|
|
@@ -3013,7 +3074,7 @@ function rangeForClick(wg, pos, type) {
|
|
|
3013
3074
|
}
|
|
3014
3075
|
else { let cx = wg.state.doc.resolve(pos.pos), block = cx.textblockParent;
|
|
3015
3076
|
if (block)
|
|
3016
|
-
return GardSelection.
|
|
3077
|
+
return GardSelection.undirectionalRange(block.start, block.end);
|
|
3017
3078
|
else
|
|
3018
3079
|
return GardSelection.near(wg.state, pos.pos, pos.side || -1);
|
|
3019
3080
|
}
|
|
@@ -3126,12 +3187,23 @@ function moveToLineBoundary(wg, start, forward) {
|
|
|
3126
3187
|
let startCoords = wg.coordsAtPos(start.head, start.headSide);
|
|
3127
3188
|
let ltr = wg.state.textblockLTR(block.node);
|
|
3128
3189
|
let y = (startCoords.top + startCoords.bottom) / 2, left = forward != ltr;
|
|
3129
|
-
let { pos } = wg.posAtCoords({ x: left ? -1e7 : 1e7, y });
|
|
3190
|
+
let { pos, side } = wg.posAtCoords({ x: left ? -1e7 : 1e7, y });
|
|
3130
3191
|
if (pos < block.start || pos > block.end) {
|
|
3131
3192
|
let blockRect = wg.docTile.nodeTile(block.before).dom.getBoundingClientRect();
|
|
3132
|
-
|
|
3193
|
+
let result = wg.posAtCoords({ x: left ? blockRect.left + 0.2 : blockRect.right - 0.2, y });
|
|
3194
|
+
if (result.pos < block.start) {
|
|
3195
|
+
pos = block.start;
|
|
3196
|
+
side = -1;
|
|
3197
|
+
}
|
|
3198
|
+
else if (result.pos > block.end) {
|
|
3199
|
+
pos = block.end;
|
|
3200
|
+
side = 1;
|
|
3201
|
+
}
|
|
3202
|
+
else {
|
|
3203
|
+
({ pos, side } = result);
|
|
3204
|
+
}
|
|
3133
3205
|
}
|
|
3134
|
-
return GardSelection.cursor(pos,
|
|
3206
|
+
return GardSelection.cursor(pos, side);
|
|
3135
3207
|
}
|
|
3136
3208
|
|
|
3137
3209
|
const observeOptions = {
|
|
@@ -3269,7 +3341,7 @@ class DOMObserver {
|
|
|
3269
3341
|
if (selRange)
|
|
3270
3342
|
range = buildSelectionRangeFromRange(wg, selRange);
|
|
3271
3343
|
}
|
|
3272
|
-
if (!range || this.selectionRange.eq(range))
|
|
3344
|
+
if (!range || !range.focusNode || this.selectionRange.eq(range))
|
|
3273
3345
|
return false;
|
|
3274
3346
|
let context = range.anchorNode && wg.docTile.nearest(range.anchorNode);
|
|
3275
3347
|
if (context instanceof WidgetTile)
|
|
@@ -3281,10 +3353,6 @@ class DOMObserver {
|
|
|
3281
3353
|
this.selectionRange.set(anchor.dom, anchor.offset, head.dom, head.offset);
|
|
3282
3354
|
this.selectionChanged = false;
|
|
3283
3355
|
}
|
|
3284
|
-
clearSelectionRange() {
|
|
3285
|
-
this.selectionRange.set(null, 0, null, 0);
|
|
3286
|
-
this.selectionChanged = false;
|
|
3287
|
-
}
|
|
3288
3356
|
ignore(f) {
|
|
3289
3357
|
let result = f();
|
|
3290
3358
|
this.clear();
|
|
@@ -3378,18 +3446,46 @@ class KeyBinding {
|
|
|
3378
3446
|
static of(spec) { return new KeyBinding(spec); }
|
|
3379
3447
|
}
|
|
3380
3448
|
;KeyBinding = /*@__PURE__*/(function (KeyBinding) {
|
|
3381
|
-
function
|
|
3382
|
-
let map = getKeymap(wg.state
|
|
3383
|
-
return runHandlers(map, event, wg
|
|
3384
|
-
}
|
|
3385
|
-
KeyBinding.
|
|
3386
|
-
KeyBinding.
|
|
3449
|
+
function handle(wg, event) {
|
|
3450
|
+
let map = getKeymap(wg.state);
|
|
3451
|
+
return runHandlers(map, event, wg);
|
|
3452
|
+
}
|
|
3453
|
+
KeyBinding.handle = handle;
|
|
3454
|
+
KeyBinding.keymap = GardState.Field.Derived.define(s => {
|
|
3455
|
+
let bindings = s.facet(KeyBinding.source);
|
|
3456
|
+
return s.facet(KeyBinding.useDefaultKeymap) ? bindings.concat(KeyBinding.defaultKeymap) : bindings;
|
|
3457
|
+
});
|
|
3458
|
+
KeyBinding.source = GardState.Facet.define({
|
|
3459
|
+
enables: KeyBinding.keymap
|
|
3460
|
+
});
|
|
3387
3461
|
KeyBinding.useDefaultKeymap = GardState.Facet.define({
|
|
3388
3462
|
combine: input => input.length ? input[0] : true
|
|
3389
3463
|
});
|
|
3464
|
+
class Group {
|
|
3465
|
+
description;
|
|
3466
|
+
rank;
|
|
3467
|
+
constructor(
|
|
3468
|
+
description,
|
|
3469
|
+
rank) {
|
|
3470
|
+
this.description = description;
|
|
3471
|
+
this.rank = rank;
|
|
3472
|
+
}
|
|
3473
|
+
static define(spec) {
|
|
3474
|
+
return new Group(spec.description, spec.rank || 1000);
|
|
3475
|
+
}
|
|
3476
|
+
static Inline = new Group(phrases.ref("group_inline"), 20);
|
|
3477
|
+
static Block = new Group(phrases.ref("group_block"), 30);
|
|
3478
|
+
static History = new Group(phrases.ref("group_history"), 70);
|
|
3479
|
+
}
|
|
3480
|
+
KeyBinding.Group = Group;
|
|
3481
|
+
function lookupByDescription(state, desc) {
|
|
3482
|
+
return getDescMap(state).get(desc) || null;
|
|
3483
|
+
}
|
|
3484
|
+
KeyBinding.lookupByDescription = lookupByDescription;
|
|
3390
3485
|
KeyBinding.defaultKeymap = [
|
|
3391
3486
|
{ key: "Enter", run: enter },
|
|
3392
|
-
{ key: "Shift-Enter", run: insertLineBreak
|
|
3487
|
+
{ key: "Shift-Enter", run: insertLineBreak,
|
|
3488
|
+
description: phrases.ref("insert_break"), group: Group.Inline },
|
|
3393
3489
|
{ key: "Backspace", run: Command.bind(deleteUnit, "backward") },
|
|
3394
3490
|
{ key: "Delete", run: Command.bind(deleteUnit, "forward") },
|
|
3395
3491
|
{ key: "Ctrl-Backspace", mac: "Alt-Backspace", run: Command.bind(deleteWord, "backward") },
|
|
@@ -3433,9 +3529,9 @@ class KeyBinding {
|
|
|
3433
3529
|
{ key: "Mod-End", run: Command.bind(moveToDocSide, { side: "end" }),
|
|
3434
3530
|
shift: Command.bind(moveToDocSide, { side: "end", extend: true }) },
|
|
3435
3531
|
{ key: "Mod-a", run: selectAll },
|
|
3436
|
-
{ key: "Mod-z", run: undo },
|
|
3437
|
-
{ key: "Mod-y", mac: "Mod-Shift-z", run: redo },
|
|
3438
|
-
{ linux: "Ctrl-Shift-z", run: redo },
|
|
3532
|
+
{ key: "Mod-z", run: undo, description: phrases.ref("undo"), group: Group.History },
|
|
3533
|
+
{ key: "Mod-y", mac: "Mod-Shift-z", run: redo, description: phrases.ref("redo"), group: Group.History },
|
|
3534
|
+
{ linux: "Ctrl-Shift-z", run: redo, description: phrases.ref("redo"), group: Group.History },
|
|
3439
3535
|
{ mac: "Ctrl-b", run: Command.bind(moveByUnit, { dir: "backward" }),
|
|
3440
3536
|
shift: Command.bind(moveByUnit, { dir: "backward", extend: true }) },
|
|
3441
3537
|
{ mac: "Ctrl-f", run: Command.bind(moveByUnit, { dir: "forward" }),
|
|
@@ -3469,15 +3565,15 @@ function normalizeKeyName(name, platform) {
|
|
|
3469
3565
|
let alt, ctrl, shift, meta;
|
|
3470
3566
|
for (let i = 0; i < parts.length - 1; ++i) {
|
|
3471
3567
|
const mod = parts[i];
|
|
3472
|
-
if (
|
|
3568
|
+
if (mod == "Cmd" || mod == "Meta")
|
|
3473
3569
|
meta = true;
|
|
3474
|
-
else if (
|
|
3570
|
+
else if (mod == "Alt")
|
|
3475
3571
|
alt = true;
|
|
3476
|
-
else if (
|
|
3572
|
+
else if (mod == "Ctrl")
|
|
3477
3573
|
ctrl = true;
|
|
3478
|
-
else if (
|
|
3574
|
+
else if (mod == "Shift")
|
|
3479
3575
|
shift = true;
|
|
3480
|
-
else if (
|
|
3576
|
+
else if (mod == "Mod") {
|
|
3481
3577
|
if (platform == "mac")
|
|
3482
3578
|
meta = true;
|
|
3483
3579
|
else
|
|
@@ -3491,18 +3587,18 @@ function normalizeKeyName(name, platform) {
|
|
|
3491
3587
|
if (ctrl)
|
|
3492
3588
|
result = "Ctrl-" + result;
|
|
3493
3589
|
if (meta)
|
|
3494
|
-
result = "Meta-" + result;
|
|
3590
|
+
result = (platform == "mac" ? "Cmd-" : "Meta-") + result;
|
|
3495
3591
|
if (shift)
|
|
3496
3592
|
result = "Shift-" + result;
|
|
3497
3593
|
return result;
|
|
3498
3594
|
}
|
|
3499
|
-
function modifiers(name, event) {
|
|
3595
|
+
function modifiers(name, event, platform) {
|
|
3500
3596
|
if (event.altKey)
|
|
3501
3597
|
name = "Alt-" + name;
|
|
3502
3598
|
if (event.ctrlKey)
|
|
3503
3599
|
name = "Ctrl-" + name;
|
|
3504
3600
|
if (event.metaKey)
|
|
3505
|
-
name = "Meta-" + name;
|
|
3601
|
+
name = (platform == "mac" ? "Cmd-" : "Meta-") + name;
|
|
3506
3602
|
if (event.shiftKey)
|
|
3507
3603
|
name = "Shift-" + name;
|
|
3508
3604
|
return name;
|
|
@@ -3518,56 +3614,65 @@ class NormalizedBinding {
|
|
|
3518
3614
|
}
|
|
3519
3615
|
}
|
|
3520
3616
|
const keymapCache = /*@__PURE__*/(() => new WeakMap())();
|
|
3521
|
-
function getKeymap(
|
|
3617
|
+
function getKeymap(state) {
|
|
3618
|
+
let bindings = state.field(KeyBinding.keymap);
|
|
3522
3619
|
let found = keymapCache.get(bindings);
|
|
3523
|
-
if (!found
|
|
3524
|
-
found =
|
|
3525
|
-
|
|
3526
|
-
|
|
3527
|
-
|
|
3528
|
-
|
|
3620
|
+
if (!found)
|
|
3621
|
+
keymapCache.set(bindings, found = buildKeymap(bindings, currentPlatform));
|
|
3622
|
+
return found;
|
|
3623
|
+
}
|
|
3624
|
+
const lookupCache = /*@__PURE__*/(() => new WeakMap())();
|
|
3625
|
+
function getDescMap(state) {
|
|
3626
|
+
let bindings = state.field(KeyBinding.keymap);
|
|
3627
|
+
let map = lookupCache.get(bindings);
|
|
3628
|
+
if (!map) {
|
|
3629
|
+
lookupCache.set(bindings, map = new Map);
|
|
3630
|
+
for (let binding of bindings) {
|
|
3631
|
+
let { description, shiftDescription } = binding.spec;
|
|
3632
|
+
if (description || shiftDescription) {
|
|
3633
|
+
let name = binding.spec[currentPlatform] || binding.spec.key;
|
|
3634
|
+
if (name && description)
|
|
3635
|
+
map.set(description, normalizeKeyName(name, currentPlatform));
|
|
3636
|
+
if (name && shiftDescription)
|
|
3637
|
+
map.set(shiftDescription, "Shift-" + normalizeKeyName(name, currentPlatform));
|
|
3638
|
+
}
|
|
3639
|
+
}
|
|
3529
3640
|
}
|
|
3530
|
-
return
|
|
3641
|
+
return map;
|
|
3531
3642
|
}
|
|
3532
3643
|
function bind(run) {
|
|
3533
3644
|
return (wg) => Command.dispatch(wg, run);
|
|
3534
3645
|
}
|
|
3535
3646
|
function buildKeymap(bindings, platform) {
|
|
3536
|
-
let
|
|
3647
|
+
let map = [];
|
|
3537
3648
|
for (let { spec: b } of bindings) {
|
|
3538
3649
|
let baseFlags = (b.allowDefault ? 8 : 0);
|
|
3539
|
-
|
|
3540
|
-
|
|
3541
|
-
let key = b[platform] || b.key;
|
|
3542
|
-
if (b.char) {
|
|
3543
|
-
if (key)
|
|
3544
|
-
throw new Error("A key binding may not provide both a char and a key field");
|
|
3545
|
-
if (b.shift)
|
|
3546
|
-
throw new Error("Shift-modified bindings are not supported for char bindings");
|
|
3547
|
-
array.push(new NormalizedBinding(baseFlags | 1, b.char, bind(b.run)));
|
|
3548
|
-
}
|
|
3650
|
+
let key = b[platform] || b.key;
|
|
3651
|
+
if (b.char) {
|
|
3549
3652
|
if (key)
|
|
3550
|
-
|
|
3551
|
-
if (
|
|
3552
|
-
|
|
3553
|
-
|
|
3554
|
-
array.push(new NormalizedBinding(4, "", b.any));
|
|
3653
|
+
throw new Error("A key binding may not provide both a char and a key field");
|
|
3654
|
+
if (b.shift)
|
|
3655
|
+
throw new Error("Shift-modified bindings are not supported for char bindings");
|
|
3656
|
+
map.push(new NormalizedBinding(baseFlags | 1, b.char, bind(b.run)));
|
|
3555
3657
|
}
|
|
3658
|
+
if (key)
|
|
3659
|
+
map.push(new NormalizedBinding(baseFlags | 2, normalizeKeyName(key, platform), bind(b.run)));
|
|
3660
|
+
if (key && b.shift)
|
|
3661
|
+
map.push(new NormalizedBinding(baseFlags | 2, normalizeKeyName("Shift-" + key, platform), bind(b.shift)));
|
|
3662
|
+
if (b.any)
|
|
3663
|
+
map.push(new NormalizedBinding(4, "", b.any));
|
|
3556
3664
|
}
|
|
3557
|
-
return
|
|
3665
|
+
return map;
|
|
3558
3666
|
}
|
|
3559
|
-
function runHandlers(map, event, wg
|
|
3560
|
-
let handlers = map[scope];
|
|
3561
|
-
if (!handlers)
|
|
3562
|
-
return false;
|
|
3667
|
+
function runHandlers(map, event, wg) {
|
|
3563
3668
|
let key = event.key, charCode = key.codePointAt(0);
|
|
3564
3669
|
let altGr = event.getModifierState("AltGraph"), fromCode = charKeyCodes[event.keyCode];
|
|
3565
3670
|
let isChar = codePointSize(charCode) == key.length;
|
|
3566
3671
|
let char = isChar ? String.fromCodePoint(charCode) : null;
|
|
3567
|
-
let base = modifiers(key, event);
|
|
3568
|
-
let fallback = isChar && !altGr && fromCode && fromCode != base ? modifiers(fromCode, event) : null;
|
|
3672
|
+
let base = modifiers(key, event, currentPlatform);
|
|
3673
|
+
let fallback = isChar && !altGr && fromCode && fromCode != base ? modifiers(fromCode, event, currentPlatform) : null;
|
|
3569
3674
|
let handled = false, didMatch = false, allowDefault = false;
|
|
3570
|
-
for (let binding of
|
|
3675
|
+
for (let binding of map) {
|
|
3571
3676
|
let matched = ((binding.flags & 1) && (altGr || !event.ctrlKey && !event.metaKey) && binding.name == char) ||
|
|
3572
3677
|
((binding.flags & 2) && (binding.name == base || binding.name == fallback)) ||
|
|
3573
3678
|
(binding.flags & 4);
|
|
@@ -3614,6 +3719,11 @@ const eventObserver = /*@__PURE__*/GardState.Facet.define({
|
|
|
3614
3719
|
return result;
|
|
3615
3720
|
}
|
|
3616
3721
|
});
|
|
3722
|
+
const compositionInputTypes = /*@__PURE__*/(() => new Set([
|
|
3723
|
+
"insertCompositionText",
|
|
3724
|
+
"deleteCompositionText",
|
|
3725
|
+
"insertFromComposition"
|
|
3726
|
+
]))();
|
|
3617
3727
|
class InputState {
|
|
3618
3728
|
wg;
|
|
3619
3729
|
shiftKey = false;
|
|
@@ -3772,11 +3882,12 @@ class InputState {
|
|
|
3772
3882
|
}
|
|
3773
3883
|
}
|
|
3774
3884
|
let command = inputTypeCommands[type];
|
|
3775
|
-
if ((type
|
|
3776
|
-
|
|
3777
|
-
|
|
3778
|
-
|
|
3779
|
-
|
|
3885
|
+
if (isDeletionInputEvent(type) && range &&
|
|
3886
|
+
(!command ||
|
|
3887
|
+
(range.from != range.to && !this.unflushedSelection && (sel.empty
|
|
3888
|
+
? !isSingleChar(this.domDoc, data.domRange.from, data.domRange.to) ||
|
|
3889
|
+
sel.head != (type == "deleteContentBackward" ? range.to : range.from)
|
|
3890
|
+
: sel.from != range.from || sel.to != range.to)))) {
|
|
3780
3891
|
wg.dispatch({ changes: { from: range.from, to: range.to, fit: true }, userEvent: "delete" });
|
|
3781
3892
|
}
|
|
3782
3893
|
else if (command) {
|
|
@@ -3787,13 +3898,28 @@ class InputState {
|
|
|
3787
3898
|
let { from, to } = this.unflushedSelection ? wg.state.selection : range;
|
|
3788
3899
|
Command.dispatch(wg, insertText, { from, to, insert, userEvent: "input.type" });
|
|
3789
3900
|
}
|
|
3901
|
+
else if (type == "insertFromPaste") {
|
|
3902
|
+
let { from, to } = this.unflushedSelection ? wg.state.selection.replacementRange : range;
|
|
3903
|
+
let slice = readClipboard(wg.state, event.dataTransfer, wg.state.doc.resolve(from), wg.inputState.shiftKey);
|
|
3904
|
+
let isSel = from == wg.state.selection.replacementRange.from && to == wg.state.selection.replacementRange.to;
|
|
3905
|
+
if (isSel && wg.state.facet(pasteHandler).some(h => h(wg, event, slice || Slice.empty)))
|
|
3906
|
+
return;
|
|
3907
|
+
if (slice) {
|
|
3908
|
+
wg.dispatch({
|
|
3909
|
+
changes: { from, to, insert: slice, fit: true },
|
|
3910
|
+
selection: isSel ? (cx, changes) => GardSelection.near(cx, changes.mapPos(to, 1), -1) : undefined,
|
|
3911
|
+
userEvent: "input.paste",
|
|
3912
|
+
scrollIntoView: isSel
|
|
3913
|
+
});
|
|
3914
|
+
}
|
|
3915
|
+
}
|
|
3790
3916
|
else if ((type == "insertReplacementText" || type == "insertFromYank")) {
|
|
3791
3917
|
let read = readClipboard(wg.state, event.dataTransfer, wg.state.sel.head, true);
|
|
3792
3918
|
let { from, to } = this.unflushedSelection ? wg.state.selection : range;
|
|
3793
3919
|
let sel = wg.state.selection, touchesSel = from <= sel.to && to >= sel.from;
|
|
3794
3920
|
if (read)
|
|
3795
3921
|
wg.dispatch({
|
|
3796
|
-
changes: { from, to, insert: read
|
|
3922
|
+
changes: { from, to, insert: read, fit: true },
|
|
3797
3923
|
selection: touchesSel ? (cx, changes) => {
|
|
3798
3924
|
return GardSelection.near(cx, changes.mapPos(to, 1), -1);
|
|
3799
3925
|
} : undefined,
|
|
@@ -3801,7 +3927,7 @@ class InputState {
|
|
|
3801
3927
|
userEvent: "insert.replacementText"
|
|
3802
3928
|
});
|
|
3803
3929
|
}
|
|
3804
|
-
else if (type
|
|
3930
|
+
else if (compositionInputTypes.has(type)) {
|
|
3805
3931
|
let compositionStart = true;
|
|
3806
3932
|
if (wg.inputState.composing) {
|
|
3807
3933
|
compositionStart = !wg.inputState.composing.changes;
|
|
@@ -3811,7 +3937,7 @@ class InputState {
|
|
|
3811
3937
|
if (!sel.focusNode)
|
|
3812
3938
|
return false;
|
|
3813
3939
|
let userEvent = "input.type.compose" + (compositionStart ? ".start" : "");
|
|
3814
|
-
Command.dispatch(wg, insertText, { from: range.from, to: range.to, insert: event.data, userEvent });
|
|
3940
|
+
Command.dispatch(wg, insertText, { from: range.from, to: range.to, insert: event.data || "", userEvent });
|
|
3815
3941
|
}
|
|
3816
3942
|
else if (type == "formatSetBlockTextDirection") {
|
|
3817
3943
|
if (event.data == "ltr" || event.data == "rtl")
|
|
@@ -3890,6 +4016,7 @@ class InputState {
|
|
|
3890
4016
|
clearComposition() {
|
|
3891
4017
|
let comp = this.composing;
|
|
3892
4018
|
this.composing = null;
|
|
4019
|
+
this.compositionPendingKey = true;
|
|
3893
4020
|
this.compositionEndedAt = Date.now();
|
|
3894
4021
|
if (!comp.target)
|
|
3895
4022
|
return false;
|
|
@@ -4131,32 +4258,38 @@ function basicMouseSelection(wg, event) {
|
|
|
4131
4258
|
get(event, extend) {
|
|
4132
4259
|
let cur = queryPos(wg, event), range = rangeForClick(wg, cur, type), { from, to } = range;
|
|
4133
4260
|
if (extend) {
|
|
4261
|
+
let startAnchor = !(startSel instanceof GardSelection.Text) || startSel.directional ? startSel.anchor
|
|
4262
|
+
: from < startSel.from ? startSel.to : startSel.from;
|
|
4134
4263
|
if (from < startSel.anchor)
|
|
4135
|
-
return GardSelection.range(
|
|
4264
|
+
return GardSelection.range(startAnchor, from, from < to ? 1 : cur.side);
|
|
4136
4265
|
else
|
|
4137
|
-
return GardSelection.range(
|
|
4266
|
+
return GardSelection.range(startAnchor, to, from < to ? -1 : cur.side);
|
|
4138
4267
|
}
|
|
4268
|
+
let { anchor, head } = range;
|
|
4139
4269
|
if (start.pos != cur.pos) {
|
|
4140
4270
|
let startRange = rangeForClick(wg, start, type);
|
|
4141
|
-
from = Math.min(
|
|
4142
|
-
|
|
4271
|
+
let from = Math.min(range.from, startRange.from), to = Math.max(range.to, startRange.to);
|
|
4272
|
+
if (startRange.from < range.from) {
|
|
4273
|
+
anchor = from;
|
|
4274
|
+
head = to;
|
|
4275
|
+
}
|
|
4276
|
+
else {
|
|
4277
|
+
anchor = to;
|
|
4278
|
+
head = from;
|
|
4279
|
+
}
|
|
4143
4280
|
}
|
|
4144
|
-
return
|
|
4281
|
+
return anchor == range.anchor && head == range.head ? range
|
|
4282
|
+
: GardSelection.range(anchor, head, head == cur.pos ? cur.side : undefined);
|
|
4145
4283
|
}
|
|
4146
4284
|
};
|
|
4147
4285
|
}
|
|
4148
4286
|
const dropHandler = /*@__PURE__*/GardState.Facet.define();
|
|
4149
4287
|
const pasteHandler = /*@__PURE__*/GardState.Facet.define();
|
|
4150
|
-
function selectionSlice(state) {
|
|
4151
|
-
return {
|
|
4152
|
-
slice: state.doc.slice(state.selection.from, state.selection.to),
|
|
4153
|
-
context: state.doc.contextAt(state.selection.from)
|
|
4154
|
-
};
|
|
4155
|
-
}
|
|
4156
4288
|
function copy(wg, event) {
|
|
4157
4289
|
let { state } = wg;
|
|
4158
|
-
if (!state.selection.empty && event.clipboardData) {
|
|
4159
|
-
|
|
4290
|
+
if (!state.selection.empty && event.clipboardData) {
|
|
4291
|
+
let slice = state.selection.toSlice(state.doc);
|
|
4292
|
+
writeClipboard(state, slice, event.clipboardData);
|
|
4160
4293
|
if (event.type == "cut" && !state.readOnly)
|
|
4161
4294
|
wg.dispatch({
|
|
4162
4295
|
changes: state.selection.ranges.map(r => ({ from: r.from, to: r.to, fit: true })),
|
|
@@ -4216,7 +4349,7 @@ function inEditableDOM(wg, node) {
|
|
|
4216
4349
|
let tile = wg.docTile.nearest(node);
|
|
4217
4350
|
return tile ? !(tile.isPoint || tile instanceof WidgetTile) : false;
|
|
4218
4351
|
}
|
|
4219
|
-
function isDeletionInputEvent(type) { return /^delete(Content|Word)/.test(type); }
|
|
4352
|
+
function isDeletionInputEvent(type) { return /^delete(Content|Word|ByComposition)/.test(type); }
|
|
4220
4353
|
const inputTypeCommands = /*@__PURE__*/(() => ({
|
|
4221
4354
|
historyUndo: undo,
|
|
4222
4355
|
historyRedo: redo,
|
|
@@ -4249,7 +4382,7 @@ const baseHandlers = {
|
|
|
4249
4382
|
keydown(wg, event) {
|
|
4250
4383
|
if ((browser.ios || browser.android) && (event.key == "Backspace" || event.key == "Enter"))
|
|
4251
4384
|
return false;
|
|
4252
|
-
return KeyBinding.
|
|
4385
|
+
return KeyBinding.handle(wg, event);
|
|
4253
4386
|
},
|
|
4254
4387
|
mousedown(wg, event) {
|
|
4255
4388
|
wg.inputState.shiftKey = event.shiftKey;
|
|
@@ -4288,8 +4421,8 @@ const baseHandlers = {
|
|
|
4288
4421
|
inputState.mouseSelection.dragging = true;
|
|
4289
4422
|
inputState.draggedContent = selection;
|
|
4290
4423
|
if (event.dataTransfer) {
|
|
4291
|
-
let
|
|
4292
|
-
writeClipboard(wg.state, slice,
|
|
4424
|
+
let slice = wg.state.selection.toSlice(wg.state.doc);
|
|
4425
|
+
writeClipboard(wg.state, slice, event.dataTransfer);
|
|
4293
4426
|
event.dataTransfer.effectAllowed = "copyMove";
|
|
4294
4427
|
}
|
|
4295
4428
|
return false;
|
|
@@ -4303,52 +4436,31 @@ const baseHandlers = {
|
|
|
4303
4436
|
drop(wg, event) {
|
|
4304
4437
|
if (!event.dataTransfer || wg.state.readOnly)
|
|
4305
4438
|
return true;
|
|
4306
|
-
let
|
|
4307
|
-
if (!
|
|
4439
|
+
let slice = readClipboard(wg.state, event.dataTransfer, wg.state.sel.head, false);
|
|
4440
|
+
if (!slice)
|
|
4308
4441
|
return false;
|
|
4309
4442
|
let dropPos = wg.posAtCoords({ x: event.clientX, y: event.clientY }).pos;
|
|
4310
4443
|
let { draggedContent } = wg.inputState;
|
|
4311
4444
|
let del = draggedContent && dragMovesSelection(wg, event)
|
|
4312
4445
|
? { from: draggedContent.from, to: draggedContent.to } : null;
|
|
4313
|
-
if (wg.state.facet(dropHandler).some(f => f(wg, event, dropPos, del,
|
|
4446
|
+
if (wg.state.facet(dropHandler).some(f => f(wg, event, dropPos, del, slice)))
|
|
4314
4447
|
return true;
|
|
4315
|
-
let ins = { from: dropPos, insert:
|
|
4448
|
+
let ins = { from: dropPos, insert: slice, fit: true };
|
|
4316
4449
|
let changes = ChangeSet.create(wg.state.doc, del ? [del, ins] : ins);
|
|
4317
4450
|
wg.focus();
|
|
4318
4451
|
wg.dispatch({
|
|
4319
4452
|
changes,
|
|
4320
|
-
selection: GardSelection.
|
|
4453
|
+
selection: GardSelection.undirectionalRange(changes.mapPos(dropPos, -1), changes.mapPos(dropPos, 1)),
|
|
4321
4454
|
userEvent: del ? "move.drop" : "input.drop"
|
|
4322
4455
|
});
|
|
4323
4456
|
wg.inputState.draggedContent = null;
|
|
4324
4457
|
return true;
|
|
4325
4458
|
},
|
|
4326
|
-
paste(wg, event) {
|
|
4327
|
-
if (wg.state.readOnly || !event.clipboardData)
|
|
4328
|
-
return true;
|
|
4329
|
-
let { state } = wg;
|
|
4330
|
-
let content = readClipboard(state, event.clipboardData, state.sel.head, wg.inputState.shiftKey);
|
|
4331
|
-
if (wg.state.facet(pasteHandler).some(h => h(wg, event, content ? content.slice : Slice.empty, content ? content.context : [])))
|
|
4332
|
-
return true;
|
|
4333
|
-
if (content) { wg.dispatch({
|
|
4334
|
-
changes: {
|
|
4335
|
-
from: state.selection.from,
|
|
4336
|
-
to: state.selection.to,
|
|
4337
|
-
insert: content.slice,
|
|
4338
|
-
fit: content.context
|
|
4339
|
-
},
|
|
4340
|
-
selection: (cx, changes) => GardSelection.near(cx, changes.mapPos(state.selection.to, 1), -1),
|
|
4341
|
-
userEvent: "input.paste",
|
|
4342
|
-
scrollIntoView: true
|
|
4343
|
-
});
|
|
4344
|
-
}
|
|
4345
|
-
return true;
|
|
4346
|
-
},
|
|
4347
4459
|
beforeinput(wg, event) {
|
|
4348
4460
|
let type = event.inputType;
|
|
4349
4461
|
if (browser.safari && type == "insertText" && wg.inputState.composing)
|
|
4350
4462
|
compositionEnd(wg);
|
|
4351
|
-
if (type
|
|
4463
|
+
if (compositionInputTypes.has(type) && !wg.inputState.composing)
|
|
4352
4464
|
wg.inputState.composing = { changes: 0, target: null };
|
|
4353
4465
|
let data = {
|
|
4354
4466
|
inputType: type,
|
|
@@ -4364,7 +4476,7 @@ const baseHandlers = {
|
|
|
4364
4476
|
}
|
|
4365
4477
|
wg.inputState.beforeInput(event, wg.inputState.pendingInputEvent = data);
|
|
4366
4478
|
wg.scheduleFlush();
|
|
4367
|
-
let allow = type
|
|
4479
|
+
let allow = compositionInputTypes.has(type) ||
|
|
4368
4480
|
editable && (type == "insertText" || isDeletionInputEvent(type) &&
|
|
4369
4481
|
data.domRange && inlineContext(wg.inputState.domDoc, data.domRange));
|
|
4370
4482
|
return !allow;
|
|
@@ -4375,8 +4487,8 @@ const baseHandlers = {
|
|
|
4375
4487
|
return false;
|
|
4376
4488
|
wg.inputState.pendingInputEvent = null;
|
|
4377
4489
|
let change;
|
|
4378
|
-
if (event.inputType
|
|
4379
|
-
change = { from: pending.domRange.from, to: pending.domRange.to, insert: [Leaf.text(pending.data)] };
|
|
4490
|
+
if (compositionInputTypes.has(event.inputType) || event.inputType == "insertText") {
|
|
4491
|
+
change = { from: pending.domRange.from, to: pending.domRange.to, insert: [Leaf.text(pending.data || "")] };
|
|
4380
4492
|
}
|
|
4381
4493
|
else if (isDeletionInputEvent(event.inputType)) {
|
|
4382
4494
|
change = { from: pending.domRange.from, to: pending.domRange.to };
|
|
@@ -4403,7 +4515,6 @@ const baseObservers = {
|
|
|
4403
4515
|
updateForFocusChange(wg);
|
|
4404
4516
|
},
|
|
4405
4517
|
blur(wg) {
|
|
4406
|
-
wg.observer.clearSelectionRange();
|
|
4407
4518
|
updateForFocusChange(wg);
|
|
4408
4519
|
},
|
|
4409
4520
|
compositionstart: compositionUpdate,
|
|
@@ -4487,15 +4598,18 @@ class ViewState {
|
|
|
4487
4598
|
measure(wg) {
|
|
4488
4599
|
let dom = wg.contentDOM, style = window.getComputedStyle(dom);
|
|
4489
4600
|
this.styleLTR = style.direction == "ltr";
|
|
4490
|
-
let domRect = dom.getBoundingClientRect();
|
|
4491
|
-
this.contentDOMHeight = domRect.height;
|
|
4492
4601
|
let result = 0;
|
|
4602
|
+
let domRect = dom.getBoundingClientRect();
|
|
4603
|
+
if (Math.abs(this.contentDOMHeight - domRect.height) > 0.5) {
|
|
4604
|
+
result |= 2;
|
|
4605
|
+
this.contentDOMHeight = domRect.height;
|
|
4606
|
+
}
|
|
4493
4607
|
if (this.editorWidth != wg.scrollDOM.clientWidth) {
|
|
4494
4608
|
this.editorWidth = wg.scrollDOM.clientWidth;
|
|
4495
4609
|
result |= 2;
|
|
4496
4610
|
}
|
|
4497
4611
|
let contentWidth = domRect.width;
|
|
4498
|
-
if (this.contentDOMWidth
|
|
4612
|
+
if (Math.abs(this.contentDOMWidth - contentWidth) > 0.5 || this.editorHeight != wg.scrollDOM.clientHeight ||
|
|
4499
4613
|
this.editorOffset != wg.scrollDOM.offsetTop) {
|
|
4500
4614
|
this.contentDOMWidth = domRect.width;
|
|
4501
4615
|
this.editorHeight = wg.scrollDOM.clientHeight;
|
|
@@ -4684,7 +4798,7 @@ function getCursorInfo(wg, plugin, cont) {
|
|
|
4684
4798
|
return finish(null);
|
|
4685
4799
|
let target = sel.head.parent.node.isDoc ? wg.contentDOM : wg.nodeDOM(sel.head.parent.before);
|
|
4686
4800
|
wg.scheduleDOMWrite(() => {
|
|
4687
|
-
let temp = renderMarks(marks, "M");
|
|
4801
|
+
let temp = renderMarks(wg.state, marks, "M");
|
|
4688
4802
|
temp.style.position = "absolute";
|
|
4689
4803
|
wg.observer.ignore(() => target.insertBefore(temp, target.firstChild));
|
|
4690
4804
|
wg.scheduleDOMRead(() => {
|
|
@@ -5398,844 +5512,719 @@ class PluginInstance {
|
|
|
5398
5512
|
}
|
|
5399
5513
|
}
|
|
5400
5514
|
|
|
5401
|
-
|
|
5402
|
-
|
|
5403
|
-
|
|
5404
|
-
|
|
5405
|
-
|
|
5406
|
-
|
|
5407
|
-
|
|
5408
|
-
|
|
5409
|
-
|
|
5410
|
-
|
|
5411
|
-
|
|
5412
|
-
|
|
5413
|
-
|
|
5414
|
-
|
|
5415
|
-
|
|
5416
|
-
|
|
5417
|
-
|
|
5418
|
-
|
|
5419
|
-
|
|
5420
|
-
|
|
5421
|
-
|
|
5422
|
-
|
|
5423
|
-
|
|
5424
|
-
|
|
5425
|
-
|
|
5426
|
-
|
|
5427
|
-
|
|
5428
|
-
|
|
5429
|
-
|
|
5430
|
-
|
|
5431
|
-
|
|
5432
|
-
|
|
5433
|
-
|
|
5434
|
-
|
|
5435
|
-
|
|
5436
|
-
|
|
5437
|
-
if (
|
|
5438
|
-
|
|
5439
|
-
|
|
5440
|
-
|
|
5441
|
-
|
|
5442
|
-
|
|
5443
|
-
|
|
5444
|
-
|
|
5515
|
+
const Outside = "-10000px";
|
|
5516
|
+
class TooltipViewManager {
|
|
5517
|
+
facet;
|
|
5518
|
+
createTooltipView;
|
|
5519
|
+
removeTooltipView;
|
|
5520
|
+
input;
|
|
5521
|
+
tooltips;
|
|
5522
|
+
tooltipViews;
|
|
5523
|
+
constructor(wg, facet, createTooltipView, removeTooltipView) {
|
|
5524
|
+
this.facet = facet;
|
|
5525
|
+
this.createTooltipView = createTooltipView;
|
|
5526
|
+
this.removeTooltipView = removeTooltipView;
|
|
5527
|
+
this.input = wg.state.facet(facet);
|
|
5528
|
+
this.tooltips = this.input.filter(t => t);
|
|
5529
|
+
let prev = null;
|
|
5530
|
+
this.tooltipViews = this.tooltips.map(t => prev = createTooltipView(t, prev));
|
|
5531
|
+
}
|
|
5532
|
+
update(update, above) {
|
|
5533
|
+
let input = update.state.facet(this.facet);
|
|
5534
|
+
let tooltips = input.filter(x => x);
|
|
5535
|
+
if (input === this.input) {
|
|
5536
|
+
for (let t of this.tooltipViews)
|
|
5537
|
+
if (t.update)
|
|
5538
|
+
t.update(update);
|
|
5539
|
+
return false;
|
|
5540
|
+
}
|
|
5541
|
+
let tooltipViews = [], newAbove = above ? [] : null;
|
|
5542
|
+
for (let i = 0; i < tooltips.length; i++) {
|
|
5543
|
+
let tip = tooltips[i], known = -1;
|
|
5544
|
+
if (!tip)
|
|
5545
|
+
continue;
|
|
5546
|
+
for (let i = 0; i < this.tooltips.length; i++) {
|
|
5547
|
+
let other = this.tooltips[i];
|
|
5548
|
+
if (other && other.create == tip.create)
|
|
5549
|
+
known = i;
|
|
5550
|
+
}
|
|
5551
|
+
if (known < 0) {
|
|
5552
|
+
tooltipViews[i] = this.createTooltipView(tip, i ? tooltipViews[i - 1] : null);
|
|
5553
|
+
if (newAbove)
|
|
5554
|
+
newAbove[i] = !!tip.above;
|
|
5555
|
+
}
|
|
5556
|
+
else {
|
|
5557
|
+
let tooltipView = tooltipViews[i] = this.tooltipViews[known];
|
|
5558
|
+
if (newAbove)
|
|
5559
|
+
newAbove[i] = above[known];
|
|
5560
|
+
if (tooltipView.update)
|
|
5561
|
+
tooltipView.update(update);
|
|
5445
5562
|
}
|
|
5446
|
-
});
|
|
5447
|
-
if (!covered) {
|
|
5448
|
-
let end = tr.startState.doc.resolve(toA);
|
|
5449
|
-
let open = end.matchingParent(p => doc.schema.matchNode(p.type, config.type));
|
|
5450
|
-
if (open && open.before >= fromA)
|
|
5451
|
-
clear.push({ from: open.before, to: open.after });
|
|
5452
5563
|
}
|
|
5453
|
-
|
|
5454
|
-
|
|
5455
|
-
|
|
5456
|
-
|
|
5457
|
-
|
|
5458
|
-
|
|
5459
|
-
|
|
5460
|
-
|
|
5461
|
-
|
|
5462
|
-
|
|
5463
|
-
let source = (plot, start, add) => points(plot, offset(add, start));
|
|
5464
|
-
let field = GardState.Field.define({
|
|
5465
|
-
create(state) { return init(type, PointSet.create, source, state.doc); },
|
|
5466
|
-
update(value, tr) { return update(config, PointSet.create, source, value, tr); }
|
|
5467
|
-
});
|
|
5468
|
-
result.push(field, Decoration.Point.source.of(s => s.field(field)));
|
|
5469
|
-
}
|
|
5470
|
-
if (ranges) {
|
|
5471
|
-
let source = (plot, start, add) => ranges(plot, offset(add, start));
|
|
5472
|
-
let field = GardState.Field.define({
|
|
5473
|
-
create(state) { return init(type, RangeSet.create, source, state.doc); },
|
|
5474
|
-
update(value, tr) { return update(config, RangeSet.create, source, value, tr); }
|
|
5475
|
-
});
|
|
5476
|
-
result.push(field, Decoration.Range.source.of(s => s.field(field)));
|
|
5477
|
-
}
|
|
5478
|
-
return result;
|
|
5479
|
-
}
|
|
5480
|
-
|
|
5481
|
-
const panelConfig = /*@__PURE__*/GardState.Facet.define({
|
|
5482
|
-
combine(configs) {
|
|
5483
|
-
let topContainer, bottomContainer;
|
|
5484
|
-
for (let c of configs) {
|
|
5485
|
-
topContainer ||= c.topContainer;
|
|
5486
|
-
bottomContainer ||= c.bottomContainer;
|
|
5564
|
+
for (let t of this.tooltipViews)
|
|
5565
|
+
if (tooltipViews.indexOf(t) < 0) {
|
|
5566
|
+
this.removeTooltipView(t);
|
|
5567
|
+
if (update.editor.connected)
|
|
5568
|
+
t.disconnect?.(update.editor);
|
|
5569
|
+
t.remove?.(update.editor);
|
|
5570
|
+
}
|
|
5571
|
+
if (above) {
|
|
5572
|
+
newAbove.forEach((val, i) => above[i] = val);
|
|
5573
|
+
above.length = newAbove.length;
|
|
5487
5574
|
}
|
|
5488
|
-
|
|
5575
|
+
this.input = input;
|
|
5576
|
+
this.tooltips = tooltips;
|
|
5577
|
+
this.tooltipViews = tooltipViews;
|
|
5578
|
+
return true;
|
|
5489
5579
|
}
|
|
5580
|
+
}
|
|
5581
|
+
const tooltipConfig = /*@__PURE__*/GardState.Facet.define({
|
|
5582
|
+
combine: values => ({
|
|
5583
|
+
position: browser.ios ? "absolute" : values.find(conf => conf.position)?.position || "fixed",
|
|
5584
|
+
parent: values.find(conf => conf.parent)?.parent || null,
|
|
5585
|
+
tooltipSpace: values.find(conf => conf.tooltipSpace)?.tooltipSpace || (wg => windowRect(wg.win)),
|
|
5586
|
+
})
|
|
5490
5587
|
});
|
|
5491
|
-
const
|
|
5492
|
-
|
|
5493
|
-
|
|
5494
|
-
|
|
5495
|
-
|
|
5496
|
-
|
|
5497
|
-
|
|
5498
|
-
|
|
5499
|
-
|
|
5500
|
-
|
|
5501
|
-
|
|
5502
|
-
|
|
5503
|
-
|
|
5504
|
-
|
|
5505
|
-
|
|
5506
|
-
this.
|
|
5507
|
-
|
|
5508
|
-
|
|
5588
|
+
const knownHeight = /*@__PURE__*/(() => new WeakMap())();
|
|
5589
|
+
const tooltipPlugin = /*@__PURE__*/Wordgard.Plugin.fromClass(class {
|
|
5590
|
+
wg;
|
|
5591
|
+
manager;
|
|
5592
|
+
above = [];
|
|
5593
|
+
inView = true;
|
|
5594
|
+
position;
|
|
5595
|
+
madeAbsolute = false;
|
|
5596
|
+
parent;
|
|
5597
|
+
classes;
|
|
5598
|
+
intersectionObserver;
|
|
5599
|
+
resizeObserver;
|
|
5600
|
+
lastTransaction = 0;
|
|
5601
|
+
measureTimeout = -1;
|
|
5602
|
+
constructor(wg) {
|
|
5603
|
+
this.wg = wg;
|
|
5604
|
+
let config = wg.state.facet(tooltipConfig);
|
|
5605
|
+
this.position = config.position;
|
|
5606
|
+
this.parent = config.parent;
|
|
5607
|
+
this.classes = wg.themeClasses;
|
|
5608
|
+
this.createContainer();
|
|
5609
|
+
this.measure = this.measure.bind(this);
|
|
5610
|
+
this.resizeObserver = typeof ResizeObserver == "function" ? new ResizeObserver(() => this.measureSoon()) : null;
|
|
5611
|
+
this.manager = new TooltipViewManager(wg, Tooltip.show, (t, p) => this.createTooltip(t, p), t => {
|
|
5612
|
+
if (this.resizeObserver)
|
|
5613
|
+
this.resizeObserver.unobserve(t.dom);
|
|
5614
|
+
t.dom.remove();
|
|
5615
|
+
});
|
|
5616
|
+
this.above = this.manager.tooltips.map(t => !!t.above);
|
|
5617
|
+
this.intersectionObserver = typeof IntersectionObserver == "function" ? new IntersectionObserver(entries => {
|
|
5618
|
+
if (Date.now() > this.lastTransaction - 50 &&
|
|
5619
|
+
entries.length > 0 && entries[entries.length - 1].intersectionRatio < 1)
|
|
5620
|
+
this.measureSoon();
|
|
5621
|
+
}, { threshold: [1] }) : null;
|
|
5622
|
+
this.observeIntersection();
|
|
5623
|
+
this.maybeMeasure();
|
|
5624
|
+
}
|
|
5625
|
+
createContainer() {
|
|
5626
|
+
if (this.parent) {
|
|
5627
|
+
this.container = document.createElement("wg-tooltip-root");
|
|
5628
|
+
this.container.style.position = "relative";
|
|
5629
|
+
this.container.className = this.wg.themeClasses;
|
|
5630
|
+
this.parent.appendChild(this.container);
|
|
5631
|
+
}
|
|
5632
|
+
else {
|
|
5633
|
+
this.container = this.wg.dom;
|
|
5634
|
+
}
|
|
5635
|
+
}
|
|
5636
|
+
observeIntersection() {
|
|
5637
|
+
if (this.intersectionObserver && this.wg.connected) {
|
|
5638
|
+
this.intersectionObserver.disconnect();
|
|
5639
|
+
for (let tooltip of this.manager.tooltipViews)
|
|
5640
|
+
this.intersectionObserver.observe(tooltip.dom);
|
|
5641
|
+
}
|
|
5642
|
+
}
|
|
5643
|
+
measureSoon() {
|
|
5644
|
+
if (this.measureTimeout < 0)
|
|
5645
|
+
this.measureTimeout = setTimeout(() => {
|
|
5646
|
+
this.measureTimeout = -1;
|
|
5647
|
+
this.maybeMeasure();
|
|
5648
|
+
}, 50);
|
|
5649
|
+
}
|
|
5509
5650
|
update(update) {
|
|
5510
|
-
|
|
5511
|
-
|
|
5512
|
-
|
|
5513
|
-
|
|
5651
|
+
if (update.transactions.length)
|
|
5652
|
+
this.lastTransaction = Date.now();
|
|
5653
|
+
let updated = this.manager.update(update, this.above);
|
|
5654
|
+
if (updated)
|
|
5655
|
+
this.observeIntersection();
|
|
5656
|
+
let shouldMeasure = updated || update.geometryChanged;
|
|
5657
|
+
let newConfig = update.state.facet(tooltipConfig);
|
|
5658
|
+
if (newConfig.position != this.position && !this.madeAbsolute) {
|
|
5659
|
+
this.position = newConfig.position;
|
|
5660
|
+
for (let t of this.manager.tooltipViews)
|
|
5661
|
+
t.dom.style.position = this.position;
|
|
5662
|
+
shouldMeasure = true;
|
|
5514
5663
|
}
|
|
5515
|
-
if (
|
|
5516
|
-
this.
|
|
5517
|
-
|
|
5664
|
+
if (newConfig.parent != this.parent) {
|
|
5665
|
+
if (this.parent)
|
|
5666
|
+
this.container.remove();
|
|
5667
|
+
this.parent = newConfig.parent;
|
|
5668
|
+
this.createContainer();
|
|
5669
|
+
for (let t of this.manager.tooltipViews)
|
|
5670
|
+
this.container.appendChild(t.dom);
|
|
5671
|
+
shouldMeasure = true;
|
|
5518
5672
|
}
|
|
5519
|
-
this.
|
|
5520
|
-
|
|
5521
|
-
let input = update.state.facet(Panel.show);
|
|
5522
|
-
if (input != this.input) {
|
|
5523
|
-
let specs = input.filter(x => x);
|
|
5524
|
-
let panels = [], top = [], bottom = [], mount = [];
|
|
5525
|
-
for (let spec of specs) {
|
|
5526
|
-
let known = this.specs.indexOf(spec), panel;
|
|
5527
|
-
if (known < 0) {
|
|
5528
|
-
panel = spec(update.editor);
|
|
5529
|
-
mount.push(panel);
|
|
5530
|
-
}
|
|
5531
|
-
else {
|
|
5532
|
-
panel = this.panels[known];
|
|
5533
|
-
if (panel.update)
|
|
5534
|
-
panel.update(update);
|
|
5535
|
-
}
|
|
5536
|
-
panels.push(panel);
|
|
5537
|
-
(panel.top ? top : bottom).push(panel);
|
|
5538
|
-
}
|
|
5539
|
-
this.specs = specs;
|
|
5540
|
-
this.panels = panels;
|
|
5541
|
-
this.top.sync(top, update.editor);
|
|
5542
|
-
this.bottom.sync(bottom, update.editor);
|
|
5543
|
-
for (let p of mount) {
|
|
5544
|
-
p.dom.classList.add("wg-panel");
|
|
5545
|
-
if (p.connect && update.editor.connected)
|
|
5546
|
-
p.connect(update.editor);
|
|
5547
|
-
}
|
|
5673
|
+
else if (this.parent && this.wg.themeClasses != this.classes) {
|
|
5674
|
+
this.classes = this.container.className = this.wg.themeClasses;
|
|
5548
5675
|
}
|
|
5549
|
-
|
|
5550
|
-
|
|
5551
|
-
|
|
5552
|
-
|
|
5676
|
+
if (shouldMeasure)
|
|
5677
|
+
this.maybeMeasure();
|
|
5678
|
+
}
|
|
5679
|
+
createTooltip(tooltip, prev) {
|
|
5680
|
+
let tooltipView = tooltip.create(this.wg);
|
|
5681
|
+
let before = prev ? prev.dom : null;
|
|
5682
|
+
tooltipView.dom.classList.add("wg-tooltip");
|
|
5683
|
+
if (tooltip.arrow && !tooltipView.dom.querySelector(".wg-tooltip > wg-tooltip-arrow")) {
|
|
5684
|
+
let arrow = document.createElement("wg-tooltip-arrow");
|
|
5685
|
+
tooltipView.dom.appendChild(arrow);
|
|
5553
5686
|
}
|
|
5687
|
+
tooltipView.dom.style.position = this.position;
|
|
5688
|
+
tooltipView.dom.style.top = Outside;
|
|
5689
|
+
tooltipView.dom.style.left = "0px";
|
|
5690
|
+
this.container.insertBefore(tooltipView.dom, before);
|
|
5691
|
+
if (this.wg.connected)
|
|
5692
|
+
tooltipView.connect?.(this.wg);
|
|
5693
|
+
if (this.resizeObserver && this.wg.connected)
|
|
5694
|
+
this.resizeObserver.observe(tooltipView.dom);
|
|
5695
|
+
return tooltipView;
|
|
5554
5696
|
}
|
|
5555
5697
|
connect(wg) {
|
|
5556
|
-
|
|
5557
|
-
|
|
5698
|
+
wg.win.addEventListener("resize", this.measureSoon = this.measureSoon.bind(this));
|
|
5699
|
+
for (let t of this.manager.tooltipViews) {
|
|
5700
|
+
t.connect?.(wg);
|
|
5701
|
+
if (this.resizeObserver)
|
|
5702
|
+
this.resizeObserver.observe(t.dom);
|
|
5703
|
+
}
|
|
5704
|
+
this.observeIntersection();
|
|
5558
5705
|
}
|
|
5559
5706
|
disconnect(wg) {
|
|
5560
|
-
|
|
5561
|
-
|
|
5562
|
-
|
|
5563
|
-
|
|
5564
|
-
|
|
5565
|
-
|
|
5566
|
-
|
|
5567
|
-
|
|
5568
|
-
let value = wg.plugin(plugin);
|
|
5569
|
-
return value && { top: value.top.scrollMargin(), bottom: value.bottom.scrollMargin() };
|
|
5570
|
-
}));
|
|
5571
|
-
const Panel = /*@__PURE__*/(function (Panel) {
|
|
5572
|
-
Panel.show = GardState.Facet.define({
|
|
5573
|
-
enables: panelPlugin
|
|
5574
|
-
});
|
|
5575
|
-
function get(wg, constructor) {
|
|
5576
|
-
let plugin = wg.plugin(panelPlugin);
|
|
5577
|
-
let index = plugin ? plugin.specs.indexOf(constructor) : -1;
|
|
5578
|
-
return index > -1 ? plugin.panels[index] : null;
|
|
5707
|
+
this.wg.win.removeEventListener("resize", this.measureSoon);
|
|
5708
|
+
for (let t of this.manager.tooltipViews) {
|
|
5709
|
+
t.disconnect?.(wg);
|
|
5710
|
+
if (this.resizeObserver)
|
|
5711
|
+
this.resizeObserver.unobserve(t.dom);
|
|
5712
|
+
}
|
|
5713
|
+
if (this.intersectionObserver)
|
|
5714
|
+
this.intersectionObserver.disconnect();
|
|
5579
5715
|
}
|
|
5580
|
-
|
|
5581
|
-
|
|
5582
|
-
|
|
5716
|
+
remove() {
|
|
5717
|
+
for (let tooltipView of this.manager.tooltipViews) {
|
|
5718
|
+
tooltipView.dom.remove();
|
|
5719
|
+
if (this.wg.connected)
|
|
5720
|
+
tooltipView.disconnect?.(this.wg);
|
|
5721
|
+
tooltipView.remove?.(this.wg);
|
|
5722
|
+
}
|
|
5723
|
+
if (this.parent)
|
|
5724
|
+
this.container.remove();
|
|
5725
|
+
clearTimeout(this.measureTimeout);
|
|
5583
5726
|
}
|
|
5584
|
-
|
|
5585
|
-
|
|
5586
|
-
|
|
5587
|
-
wg;
|
|
5588
|
-
top;
|
|
5589
|
-
container;
|
|
5590
|
-
dom = undefined;
|
|
5591
|
-
classes = "";
|
|
5592
|
-
panels = [];
|
|
5593
|
-
constructor(wg, top, container) {
|
|
5594
|
-
this.wg = wg;
|
|
5595
|
-
this.top = top;
|
|
5596
|
-
this.container = container;
|
|
5597
|
-
this.syncClasses();
|
|
5727
|
+
measure() {
|
|
5728
|
+
let measure = this.readMeasure();
|
|
5729
|
+
this.wg.scheduleDOMWrite(() => this.writeMeasure(measure));
|
|
5598
5730
|
}
|
|
5599
|
-
|
|
5600
|
-
|
|
5601
|
-
|
|
5602
|
-
|
|
5603
|
-
|
|
5604
|
-
|
|
5731
|
+
readMeasure() {
|
|
5732
|
+
let scaleX = 1, scaleY = 1, makeAbsolute = false;
|
|
5733
|
+
if (this.position == "fixed" && this.manager.tooltipViews.length) {
|
|
5734
|
+
let { dom } = this.manager.tooltipViews[0];
|
|
5735
|
+
if (browser.safari) {
|
|
5736
|
+
let rect = dom.getBoundingClientRect();
|
|
5737
|
+
makeAbsolute = Math.abs(rect.top + 10000) > 1 || Math.abs(rect.left) > 1;
|
|
5605
5738
|
}
|
|
5606
|
-
|
|
5607
|
-
|
|
5608
|
-
}
|
|
5609
|
-
syncDOM() {
|
|
5610
|
-
if (this.panels.length == 0) {
|
|
5611
|
-
if (this.dom) {
|
|
5612
|
-
this.dom.remove();
|
|
5613
|
-
this.dom = undefined;
|
|
5739
|
+
else {
|
|
5740
|
+
makeAbsolute = !!dom.offsetParent && dom.offsetParent != this.container.ownerDocument.body;
|
|
5614
5741
|
}
|
|
5615
|
-
return;
|
|
5616
|
-
}
|
|
5617
|
-
if (!this.dom) {
|
|
5618
|
-
this.dom = document.createElement("wg-panels");
|
|
5619
|
-
this.dom.className = this.top ? "wg-panels-top" : "wg-panels-bottom";
|
|
5620
|
-
let parent = this.container || this.wg.dom;
|
|
5621
|
-
parent.insertBefore(this.dom, this.top ? parent.firstChild : null);
|
|
5622
5742
|
}
|
|
5623
|
-
|
|
5624
|
-
|
|
5625
|
-
if (
|
|
5626
|
-
|
|
5627
|
-
|
|
5628
|
-
curDOM = curDOM.nextSibling;
|
|
5629
|
-
}
|
|
5630
|
-
else {
|
|
5631
|
-
this.dom.insertBefore(panel.dom, curDOM);
|
|
5743
|
+
if (makeAbsolute || this.position == "absolute") {
|
|
5744
|
+
let measure = this.parent || this.container, rect = measure.getBoundingClientRect();
|
|
5745
|
+
if (rect.width && rect.height) {
|
|
5746
|
+
scaleX = rect.width / measure.offsetWidth;
|
|
5747
|
+
scaleY = rect.height / measure.offsetHeight;
|
|
5632
5748
|
}
|
|
5633
5749
|
}
|
|
5634
|
-
|
|
5635
|
-
|
|
5636
|
-
|
|
5637
|
-
|
|
5638
|
-
|
|
5639
|
-
:
|
|
5640
|
-
|
|
5641
|
-
|
|
5642
|
-
|
|
5643
|
-
|
|
5644
|
-
|
|
5645
|
-
|
|
5646
|
-
|
|
5647
|
-
if (cls)
|
|
5648
|
-
this.container.classList.remove(cls);
|
|
5649
|
-
for (let cls of (this.classes = this.wg.themeClasses).split(" "))
|
|
5650
|
-
if (cls)
|
|
5651
|
-
this.container.classList.add(cls);
|
|
5652
|
-
}
|
|
5653
|
-
}
|
|
5654
|
-
|
|
5655
|
-
let nextID = 0;
|
|
5656
|
-
function id(prefix) {
|
|
5657
|
-
return prefix + "-" + (nextID++ % 0xffffff).toString(16);
|
|
5658
|
-
}
|
|
5659
|
-
const SVG = "http://www.w3.org/2000/svg";
|
|
5660
|
-
function labelButton(wg, button, label) {
|
|
5661
|
-
button.textContent = "";
|
|
5662
|
-
if (!label) ;
|
|
5663
|
-
else if (typeof label == "function" || typeof label == "string") {
|
|
5664
|
-
let span = button.appendChild(document.createElement("span"));
|
|
5665
|
-
span.className = "wg-button-label";
|
|
5666
|
-
span.textContent = typeof label == "string" ? label : label(wg.state);
|
|
5667
|
-
}
|
|
5668
|
-
else if ("icon" in label) {
|
|
5669
|
-
let svg = button.appendChild(document.createElementNS(SVG, "svg"));
|
|
5670
|
-
svg.classList.add("wg-icon");
|
|
5671
|
-
svg.setAttribute("viewBox", "0 0 100 100");
|
|
5672
|
-
let path = svg.appendChild(document.createElementNS(SVG, "path"));
|
|
5673
|
-
path.setAttribute("d", label.icon);
|
|
5674
|
-
if (label.directional && !wg.state.textLTR)
|
|
5675
|
-
svg.setAttribute("transform", "scale(-1, 1)");
|
|
5750
|
+
let visible = this.wg.scrollDOM.getBoundingClientRect(), margins = this.wg.getScrollMargins();
|
|
5751
|
+
let visLeft = visible.left + margins.left, visTop = visible.top + margins.top;
|
|
5752
|
+
return {
|
|
5753
|
+
visible: new DOMRect(visLeft, visTop, visible.right - margins.right - visLeft, visible.bottom - margins.bottom - visTop),
|
|
5754
|
+
parent: this.parent ? this.container.getBoundingClientRect() : this.wg.dom.getBoundingClientRect(),
|
|
5755
|
+
pos: this.manager.tooltips.map((t, i) => {
|
|
5756
|
+
let tv = this.manager.tooltipViews[i];
|
|
5757
|
+
return tv.getCoords ? tv.getCoords(t.pos) : this.wg.coordsAtPos(t.pos);
|
|
5758
|
+
}),
|
|
5759
|
+
size: this.manager.tooltipViews.map(({ dom }) => dom.getBoundingClientRect()),
|
|
5760
|
+
space: this.wg.state.facet(tooltipConfig).tooltipSpace(this.wg),
|
|
5761
|
+
scaleX, scaleY, makeAbsolute
|
|
5762
|
+
};
|
|
5676
5763
|
}
|
|
5677
|
-
|
|
5678
|
-
|
|
5679
|
-
|
|
5680
|
-
|
|
5681
|
-
|
|
5682
|
-
|
|
5683
|
-
constructor(item, wg) {
|
|
5684
|
-
this.item = item;
|
|
5685
|
-
this.dom = document.createElement("button");
|
|
5686
|
-
this.dom.className = "wg-menu-button";
|
|
5687
|
-
this.dom.type = "button";
|
|
5688
|
-
this.dom.tabIndex = -1;
|
|
5689
|
-
labelButton(wg, this.dom, item.label);
|
|
5690
|
-
if (item.description) {
|
|
5691
|
-
let desc = typeof item.description == "function" ? item.description(wg.state) : item.description;
|
|
5692
|
-
this.dom.title = desc;
|
|
5693
|
-
this.dom.setAttribute("aria-label", desc);
|
|
5764
|
+
writeMeasure(measured) {
|
|
5765
|
+
if (measured.makeAbsolute) {
|
|
5766
|
+
this.madeAbsolute = true;
|
|
5767
|
+
this.position = "absolute";
|
|
5768
|
+
for (let t of this.manager.tooltipViews)
|
|
5769
|
+
t.dom.style.position = "absolute";
|
|
5694
5770
|
}
|
|
5695
|
-
|
|
5696
|
-
|
|
5697
|
-
|
|
5698
|
-
|
|
5699
|
-
|
|
5700
|
-
|
|
5701
|
-
|
|
5702
|
-
|
|
5703
|
-
|
|
5704
|
-
|
|
5705
|
-
|
|
5771
|
+
let { visible, space, scaleX, scaleY } = measured;
|
|
5772
|
+
let others = [];
|
|
5773
|
+
for (let i = 0; i < this.manager.tooltips.length; i++) {
|
|
5774
|
+
let tooltip = this.manager.tooltips[i], tView = this.manager.tooltipViews[i], { dom } = tView;
|
|
5775
|
+
let pos = measured.pos[i], size = measured.size[i];
|
|
5776
|
+
if (!pos || tooltip.clip !== false && (pos.bottom <= Math.max(visible.top, space.top) ||
|
|
5777
|
+
pos.top >= Math.min(visible.bottom, space.bottom) ||
|
|
5778
|
+
pos.right < Math.max(visible.left, space.left) - .1 ||
|
|
5779
|
+
pos.left > Math.min(visible.right, space.right) + .1)) {
|
|
5780
|
+
dom.style.top = Outside;
|
|
5781
|
+
continue;
|
|
5706
5782
|
}
|
|
5707
|
-
|
|
5708
|
-
|
|
5709
|
-
|
|
5710
|
-
|
|
5711
|
-
|
|
5712
|
-
|
|
5783
|
+
let arrow = tooltip.arrow ? tView.dom.querySelector("wg-tooltip-arrow") : null;
|
|
5784
|
+
let arrowHeight = arrow ? 7 : 0;
|
|
5785
|
+
let width = size.right - size.left, height = knownHeight.get(tView) ?? size.bottom - size.top;
|
|
5786
|
+
let offset = tView.offset || noOffset, ltr = this.wg.state.textLTR;
|
|
5787
|
+
let left = size.width > space.right - space.left
|
|
5788
|
+
? (ltr ? space.left : space.right - size.width)
|
|
5789
|
+
: ltr ? Math.max(space.left, Math.min(pos.left - (arrow ? 14 : 0) + offset.x, space.right - width))
|
|
5790
|
+
: Math.min(Math.max(space.left, pos.left - width + (arrow ? 14 : 0) - offset.x), space.right - width);
|
|
5791
|
+
let above = this.above[i];
|
|
5792
|
+
if (!tooltip.strictSide && (above
|
|
5793
|
+
? pos.top - height - arrowHeight - offset.y < space.top
|
|
5794
|
+
: pos.bottom + height + arrowHeight + offset.y > space.bottom) &&
|
|
5795
|
+
above == (space.bottom - pos.bottom > pos.top - space.top))
|
|
5796
|
+
above = this.above[i] = !above;
|
|
5797
|
+
let spaceVert = (above ? pos.top - space.top : space.bottom - pos.bottom) - arrowHeight;
|
|
5798
|
+
if (spaceVert < height && tView.resize !== false) {
|
|
5799
|
+
if (spaceVert < 15) {
|
|
5800
|
+
dom.style.top = Outside;
|
|
5801
|
+
continue;
|
|
5802
|
+
}
|
|
5803
|
+
knownHeight.set(tView, height);
|
|
5804
|
+
dom.style.height = (height = spaceVert) / scaleY + "px";
|
|
5713
5805
|
}
|
|
5714
|
-
if (
|
|
5715
|
-
|
|
5716
|
-
this.dom.setAttribute("aria-pressed", "true");
|
|
5717
|
-
else
|
|
5718
|
-
this.dom.removeAttribute("aria-pressed");
|
|
5806
|
+
else if (dom.style.height) {
|
|
5807
|
+
dom.style.height = "";
|
|
5719
5808
|
}
|
|
5720
|
-
|
|
5809
|
+
let top = above ? pos.top - height - arrowHeight - offset.y : pos.bottom + arrowHeight + offset.y;
|
|
5810
|
+
let right = left + width;
|
|
5811
|
+
if (tView.overlap !== true)
|
|
5812
|
+
for (let r of others)
|
|
5813
|
+
if (r.left < right && r.right > left && r.top < top + height && r.bottom > top)
|
|
5814
|
+
top = above ? r.top - height - 2 - arrowHeight : r.bottom + arrowHeight + 2;
|
|
5815
|
+
if (this.position == "absolute") {
|
|
5816
|
+
dom.style.top = (top - measured.parent.top) / scaleY + "px";
|
|
5817
|
+
setLeftStyle(dom, (left - measured.parent.left) / scaleX);
|
|
5818
|
+
}
|
|
5819
|
+
else {
|
|
5820
|
+
dom.style.top = top / scaleY + "px";
|
|
5821
|
+
setLeftStyle(dom, left / scaleX);
|
|
5822
|
+
}
|
|
5823
|
+
if (arrow) {
|
|
5824
|
+
let arrowLeft = pos.left + (ltr ? offset.x : -offset.x) - (left + 14 - 7);
|
|
5825
|
+
arrow.style.left = arrowLeft / scaleX + "px";
|
|
5826
|
+
}
|
|
5827
|
+
if (tView.overlap !== true)
|
|
5828
|
+
others.push({ left, top, right, bottom: top + height });
|
|
5829
|
+
dom.classList.toggle("wg-tooltip-above", above);
|
|
5830
|
+
dom.classList.toggle("wg-tooltip-below", !above);
|
|
5831
|
+
if (tView.positioned)
|
|
5832
|
+
tView.positioned(measured.space);
|
|
5721
5833
|
}
|
|
5722
5834
|
}
|
|
5723
|
-
|
|
5724
|
-
|
|
5725
|
-
|
|
5835
|
+
maybeMeasure() {
|
|
5836
|
+
if (this.manager.tooltips.length)
|
|
5837
|
+
this.wg.scheduleDOMRead(this.measure);
|
|
5726
5838
|
}
|
|
5839
|
+
}, plugin => plugin.eventObserver("scroll", (event, wg, value) => value.maybeMeasure()));
|
|
5840
|
+
function setLeftStyle(elt, value) {
|
|
5841
|
+
let current = parseInt(elt.style.left, 10);
|
|
5842
|
+
if (isNaN(current) || Math.abs(value - current) > 1)
|
|
5843
|
+
elt.style.left = value + "px";
|
|
5727
5844
|
}
|
|
5728
|
-
|
|
5729
|
-
|
|
5730
|
-
|
|
5731
|
-
|
|
5732
|
-
|
|
5733
|
-
|
|
5734
|
-
|
|
5735
|
-
|
|
5736
|
-
|
|
5737
|
-
|
|
5738
|
-
|
|
5739
|
-
|
|
5740
|
-
|
|
5741
|
-
|
|
5742
|
-
|
|
5743
|
-
|
|
5744
|
-
|
|
5745
|
-
|
|
5746
|
-
|
|
5747
|
-
|
|
5748
|
-
|
|
5749
|
-
|
|
5750
|
-
|
|
5751
|
-
|
|
5752
|
-
|
|
5845
|
+
const styles = /*@__PURE__*/Wordgard.styles({
|
|
5846
|
+
".wg-tooltip": {
|
|
5847
|
+
zIndex: 500,
|
|
5848
|
+
boxSizing: "border-box",
|
|
5849
|
+
backgroundColor: "var(--wg-panel-color)",
|
|
5850
|
+
boxShadow: "0 0 8px 0 rgba(128, 128, 128, 0.2)",
|
|
5851
|
+
font: "var(--wg-dialog-font)",
|
|
5852
|
+
},
|
|
5853
|
+
".wg-tooltip-section:not(:first-child)": {
|
|
5854
|
+
borderTop: "1px solid var(--wg-border-color)",
|
|
5855
|
+
},
|
|
5856
|
+
"wg-tooltip-arrow": {
|
|
5857
|
+
display: "block",
|
|
5858
|
+
height: `${7}px`,
|
|
5859
|
+
width: `${7 * 2}px`,
|
|
5860
|
+
position: "absolute",
|
|
5861
|
+
zIndex: -1,
|
|
5862
|
+
overflow: "hidden",
|
|
5863
|
+
"&:before, &:after": {
|
|
5864
|
+
content: "''",
|
|
5865
|
+
position: "absolute",
|
|
5866
|
+
width: 0,
|
|
5867
|
+
height: 0,
|
|
5868
|
+
borderLeft: `${7}px solid transparent`,
|
|
5869
|
+
borderRight: `${7}px solid transparent`,
|
|
5870
|
+
},
|
|
5871
|
+
".wg-tooltip-above &": {
|
|
5872
|
+
bottom: `-${7}px`,
|
|
5873
|
+
"&:before": {
|
|
5874
|
+
borderTop: `${7}px solid var(--wg-border-color)`,
|
|
5875
|
+
},
|
|
5876
|
+
"&:after": {
|
|
5877
|
+
borderTop: `${7}px solid var(--wg-panel-color)`,
|
|
5878
|
+
bottom: "1px"
|
|
5753
5879
|
}
|
|
5754
|
-
|
|
5755
|
-
|
|
5880
|
+
},
|
|
5881
|
+
".wg-tooltip-below &": {
|
|
5882
|
+
top: `-${7}px`,
|
|
5883
|
+
"&:before": {
|
|
5884
|
+
borderBottom: `${7}px solid var(--wg-border-color)`,
|
|
5885
|
+
},
|
|
5886
|
+
"&:after": {
|
|
5887
|
+
borderBottom: `${7}px solid var(--wg-panel-color)`,
|
|
5888
|
+
top: "1px"
|
|
5889
|
+
}
|
|
5890
|
+
},
|
|
5891
|
+
},
|
|
5892
|
+
});
|
|
5893
|
+
const closeHoverTooltipEffect = /*@__PURE__*/Transaction.Effect.define();
|
|
5894
|
+
const Tooltip = /*@__PURE__*/(function (Tooltip) {
|
|
5895
|
+
function configure(config = {}) {
|
|
5896
|
+
return tooltipConfig.of(config);
|
|
5756
5897
|
}
|
|
5757
|
-
|
|
5758
|
-
|
|
5759
|
-
|
|
5760
|
-
|
|
5761
|
-
|
|
5762
|
-
|
|
5763
|
-
|
|
5764
|
-
|
|
5765
|
-
|
|
5766
|
-
|
|
5767
|
-
index = 0;
|
|
5768
|
-
children;
|
|
5769
|
-
constructor(item, children, wg) {
|
|
5770
|
-
this.item = item;
|
|
5771
|
-
this.dom = document.createElement("wg-submenu");
|
|
5772
|
-
this.button = this.dom.appendChild(document.createElement("button"));
|
|
5773
|
-
this.button.type = "button";
|
|
5774
|
-
this.button.tabIndex = -1;
|
|
5775
|
-
this.button.className = "wg-menu-button";
|
|
5776
|
-
this.button.setAttribute("aria-haspopup", "true");
|
|
5777
|
-
this.button.setAttribute("aria-expanded", "false");
|
|
5778
|
-
if (item.description) {
|
|
5779
|
-
let desc = typeof item.description == "function" ? item.description(wg.state) : item.description;
|
|
5780
|
-
this.dom.title = desc;
|
|
5781
|
-
this.dom.setAttribute("aria-label", desc);
|
|
5782
|
-
}
|
|
5783
|
-
if (item.label) {
|
|
5784
|
-
labelButton(wg, this.button, item.label);
|
|
5785
|
-
this.activeChild = -2;
|
|
5786
|
-
}
|
|
5787
|
-
if (item.width != null)
|
|
5788
|
-
this.dom.style.setProperty("--wg-submenu-width", item.width + "ch");
|
|
5789
|
-
if (item.arrow)
|
|
5790
|
-
this.button.classList.add("wg-submenu-arrow");
|
|
5791
|
-
this.list = this.dom.appendChild(document.createElement("wg-menu-list"));
|
|
5792
|
-
this.list.style.display = "none";
|
|
5793
|
-
this.list.role = "menu";
|
|
5794
|
-
this.list.id = id("wg-popup");
|
|
5795
|
-
this.list.setAttribute("aria-label", this.button.title);
|
|
5796
|
-
this.button.setAttribute("aria-controls", this.list.id);
|
|
5797
|
-
this.children = children.filter((ch) => !(ch instanceof BarSpacer));
|
|
5798
|
-
for (let child of children) {
|
|
5799
|
-
this.list.appendChild(child.dom);
|
|
5800
|
-
if (!(child instanceof BarSpacer))
|
|
5801
|
-
child.focusDOM.role = "menuitem";
|
|
5802
|
-
}
|
|
5898
|
+
Tooltip.configure = configure;
|
|
5899
|
+
Tooltip.show = GardState.Facet.define({
|
|
5900
|
+
enables: [tooltipPlugin, styles]
|
|
5901
|
+
});
|
|
5902
|
+
function get(wg, tooltip) {
|
|
5903
|
+
let plugin = wg.plugin(tooltipPlugin);
|
|
5904
|
+
if (!plugin)
|
|
5905
|
+
return null;
|
|
5906
|
+
let found = plugin.manager.tooltips.findIndex(typeof tooltip == "function" ? p => p.create == tooltip : p => p == tooltip);
|
|
5907
|
+
return found < 0 ? null : plugin.manager.tooltipViews[found];
|
|
5803
5908
|
}
|
|
5804
|
-
get
|
|
5805
|
-
|
|
5806
|
-
|
|
5807
|
-
|
|
5808
|
-
|
|
5809
|
-
if ((flags & 8) != (this.flags & 8)) {
|
|
5810
|
-
if (flags & 8)
|
|
5811
|
-
this.button.setAttribute("aria-disabled", "true");
|
|
5812
|
-
else
|
|
5813
|
-
this.button.removeAttribute("aria-disabled");
|
|
5814
|
-
}
|
|
5815
|
-
if ((flags & 4) != (this.flags & 4)) {
|
|
5816
|
-
if (flags & 4)
|
|
5817
|
-
this.button.setAttribute("aria-selected", "true");
|
|
5818
|
-
else
|
|
5819
|
-
this.button.removeAttribute("aria-selected");
|
|
5820
|
-
this.button.tabIndex = flags & 4 ? 0 : -1;
|
|
5821
|
-
}
|
|
5822
|
-
if ((flags & 2) != (this.flags & 2))
|
|
5823
|
-
this.list.style.display = flags & 2 ? "" : "none";
|
|
5824
|
-
this.flags = flags;
|
|
5825
|
-
}
|
|
5826
|
-
if (this.activeChild != -2) {
|
|
5827
|
-
let activeChild = this.children.findIndex(ch => ch.flags & 16);
|
|
5828
|
-
if (this.activeChild != activeChild) {
|
|
5829
|
-
this.activeChild = activeChild;
|
|
5830
|
-
let label = activeChild < 0 ? this.item.defaultLabel : this.children[activeChild].item.label;
|
|
5831
|
-
labelButton(wg, this.button, label);
|
|
5832
|
-
}
|
|
5833
|
-
}
|
|
5909
|
+
Tooltip.get = get;
|
|
5910
|
+
function reposition(wg) {
|
|
5911
|
+
let plugin = wg.plugin(tooltipPlugin);
|
|
5912
|
+
if (plugin)
|
|
5913
|
+
plugin.maybeMeasure();
|
|
5834
5914
|
}
|
|
5835
|
-
|
|
5836
|
-
}
|
|
5837
|
-
|
|
5838
|
-
|
|
5839
|
-
|
|
5840
|
-
|
|
5915
|
+
Tooltip.reposition = reposition;
|
|
5916
|
+
function hover(source, options = {}) {
|
|
5917
|
+
let setHover = Transaction.Effect.define();
|
|
5918
|
+
let hoverState = GardState.Field.define({
|
|
5919
|
+
create() { return []; },
|
|
5920
|
+
update(value, tr) {
|
|
5921
|
+
if (value.length) {
|
|
5922
|
+
if (options.hideOnChange && (tr.docChanged || tr.selection))
|
|
5923
|
+
value = [];
|
|
5924
|
+
else if (options.hideOn)
|
|
5925
|
+
value = value.filter(v => !options.hideOn(tr, v));
|
|
5926
|
+
if (tr.docChanged) {
|
|
5927
|
+
let mapped = [];
|
|
5928
|
+
for (let tooltip of value) {
|
|
5929
|
+
let newPos = tr.changes.mapPos(tooltip.pos, -1, "around");
|
|
5930
|
+
if (newPos != null) {
|
|
5931
|
+
let copy = Object.assign(Object.create(null), tooltip);
|
|
5932
|
+
copy.pos = newPos;
|
|
5933
|
+
if (copy.end != null)
|
|
5934
|
+
copy.end = tr.changes.mapPos(copy.end);
|
|
5935
|
+
mapped.push(copy);
|
|
5936
|
+
}
|
|
5937
|
+
}
|
|
5938
|
+
value = mapped;
|
|
5939
|
+
}
|
|
5940
|
+
}
|
|
5941
|
+
for (let effect of tr.effects) {
|
|
5942
|
+
if (effect.is(setHover))
|
|
5943
|
+
value = effect.value;
|
|
5944
|
+
if (effect.is(closeHoverTooltipEffect))
|
|
5945
|
+
value = [];
|
|
5946
|
+
}
|
|
5947
|
+
return value;
|
|
5948
|
+
},
|
|
5949
|
+
provide: f => showHoverTooltip.from(f)
|
|
5950
|
+
});
|
|
5951
|
+
return {
|
|
5952
|
+
active: hoverState,
|
|
5953
|
+
extension: [
|
|
5954
|
+
hoverState,
|
|
5955
|
+
Wordgard.Plugin.define(wg => new HoverPlugin(wg, source, hoverState, setHover, options.hoverTime || 300)),
|
|
5956
|
+
showHoverTooltipHost
|
|
5957
|
+
]
|
|
5958
|
+
};
|
|
5841
5959
|
}
|
|
5842
|
-
|
|
5843
|
-
function
|
|
5844
|
-
|
|
5845
|
-
|
|
5846
|
-
|
|
5847
|
-
|
|
5848
|
-
|
|
5849
|
-
|
|
5850
|
-
|
|
5851
|
-
|
|
5852
|
-
|
|
5853
|
-
|
|
5854
|
-
|
|
5855
|
-
|
|
5856
|
-
}
|
|
5857
|
-
class MenuBar {
|
|
5960
|
+
Tooltip.hover = hover;
|
|
5961
|
+
(function (hover) {
|
|
5962
|
+
function has(state) {
|
|
5963
|
+
return state.facet(showHoverTooltip).some(x => x);
|
|
5964
|
+
}
|
|
5965
|
+
hover.has = has;
|
|
5966
|
+
hover.closeAll = closeHoverTooltipEffect.of(null);
|
|
5967
|
+
})(hover = Tooltip.hover || (Tooltip.hover = {}));
|
|
5968
|
+
;return Tooltip})({});
|
|
5969
|
+
const noOffset = { x: 0, y: 0 };
|
|
5970
|
+
const showHoverTooltip = /*@__PURE__*/GardState.Facet.define({
|
|
5971
|
+
combine: inputs => inputs.reduce((a, i) => a.concat(i), [])
|
|
5972
|
+
});
|
|
5973
|
+
class HoverTooltipHost {
|
|
5858
5974
|
wg;
|
|
5975
|
+
manager;
|
|
5859
5976
|
dom;
|
|
5860
|
-
|
|
5861
|
-
|
|
5977
|
+
connected = false;
|
|
5978
|
+
static create(wg) {
|
|
5979
|
+
return new HoverTooltipHost(wg);
|
|
5980
|
+
}
|
|
5862
5981
|
constructor(wg) {
|
|
5863
5982
|
this.wg = wg;
|
|
5864
|
-
this.dom = document.createElement("wg-
|
|
5865
|
-
this.
|
|
5866
|
-
this.dom.addEventListener("keydown", this.key.bind(this));
|
|
5867
|
-
this.dom.addEventListener("mousedown", this.click.bind(this));
|
|
5868
|
-
this.dom.addEventListener("focusout", this.focusout.bind(this));
|
|
5869
|
-
this.items = wg.state.facet(Menu.Item.source);
|
|
5870
|
-
this.init();
|
|
5871
|
-
this.globalClick = this.globalClick.bind(this);
|
|
5983
|
+
this.dom = document.createElement("wg-tooltip-hover");
|
|
5984
|
+
this.manager = new TooltipViewManager(wg, showHoverTooltip, (t, p) => this.createHostedView(t, p), t => t.dom.remove());
|
|
5872
5985
|
}
|
|
5873
|
-
|
|
5874
|
-
|
|
5875
|
-
|
|
5876
|
-
this.
|
|
5877
|
-
|
|
5878
|
-
|
|
5879
|
-
|
|
5880
|
-
this.dom.appendChild(elt.dom);
|
|
5881
|
-
this.selection = this.children.length ? [this.children[0]] : [];
|
|
5882
|
-
this.updateElts(true, this.selection);
|
|
5986
|
+
createHostedView(tooltip, prev) {
|
|
5987
|
+
let hostedView = tooltip.create(this.wg);
|
|
5988
|
+
hostedView.dom.classList.add("wg-tooltip-section");
|
|
5989
|
+
this.dom.insertBefore(hostedView.dom, prev ? prev.dom.nextSibling : this.dom.firstChild);
|
|
5990
|
+
if (this.connected && hostedView.connect)
|
|
5991
|
+
hostedView.connect(this.wg);
|
|
5992
|
+
return hostedView;
|
|
5883
5993
|
}
|
|
5884
|
-
|
|
5885
|
-
let
|
|
5886
|
-
|
|
5887
|
-
|
|
5888
|
-
update.startState.textLTR != update.state.textLTR ||
|
|
5889
|
-
PhraseSet.didChange(update.startState, update.state)) {
|
|
5890
|
-
this.items = items;
|
|
5891
|
-
this.dom.textContent = "";
|
|
5892
|
-
this.init();
|
|
5893
|
-
}
|
|
5894
|
-
else {
|
|
5895
|
-
this.updateElts(update, this.selection);
|
|
5896
|
-
}
|
|
5994
|
+
connect(wg) {
|
|
5995
|
+
for (let t of this.manager.tooltipViews)
|
|
5996
|
+
t.connect?.(wg);
|
|
5997
|
+
this.connected = true;
|
|
5897
5998
|
}
|
|
5898
|
-
|
|
5899
|
-
|
|
5999
|
+
disconnect(wg) {
|
|
6000
|
+
for (let t of this.manager.tooltipViews)
|
|
6001
|
+
t.disconnect?.(wg);
|
|
6002
|
+
this.connected = false;
|
|
5900
6003
|
}
|
|
5901
|
-
|
|
5902
|
-
let
|
|
5903
|
-
|
|
5904
|
-
|
|
5905
|
-
for (let i = 0; i < this.elts.length; i++) {
|
|
5906
|
-
let elt = this.elts[i], flags;
|
|
5907
|
-
if (update && (update === true || (elt.item.updateFor ? update.transactions.some(tr => elt.item.updateFor(tr)) : changed))) {
|
|
5908
|
-
flags = ((elt.item.select ? elt.item.select(state) : true) ? 0 : 32) |
|
|
5909
|
-
((elt.item.enable ? elt.item.enable(state) : true) ? 0 : 8) |
|
|
5910
|
-
((elt.item instanceof Menu.Button && elt.item.active ? elt.item.active(state) : false) ? 16 : 0);
|
|
5911
|
-
}
|
|
5912
|
-
else {
|
|
5913
|
-
flags = elt.flags & (32 | 8 | 16);
|
|
5914
|
-
}
|
|
5915
|
-
if (selection.length) {
|
|
5916
|
-
let selected = selection.indexOf(elt);
|
|
5917
|
-
if (selected == selection.length - 1)
|
|
5918
|
-
flags |= 4;
|
|
5919
|
-
else if (selected > -1)
|
|
5920
|
-
flags |= 2;
|
|
5921
|
-
}
|
|
5922
|
-
elt.update(flags, this.wg, updateObj);
|
|
5923
|
-
}
|
|
5924
|
-
if (update && selection.some(e => e.flags & 32)) {
|
|
5925
|
-
let reset = selection[0].flags & 32 ? findChild(this.children, true) : selection[0];
|
|
5926
|
-
this.setSelection(reset ? [reset] : [], this.dom.contains(this.wg.root.activeElement));
|
|
6004
|
+
positioned(space) {
|
|
6005
|
+
for (let hostedView of this.manager.tooltipViews) {
|
|
6006
|
+
if (hostedView.positioned)
|
|
6007
|
+
hostedView.positioned(space);
|
|
5927
6008
|
}
|
|
5928
6009
|
}
|
|
5929
|
-
|
|
5930
|
-
this.
|
|
5931
|
-
if (selection.length > 1 && this.selection.length <= 1)
|
|
5932
|
-
this.dom.ownerDocument.addEventListener("mousedown", this.globalClick);
|
|
5933
|
-
this.selection = selection;
|
|
5934
|
-
if (focus && selection.length)
|
|
5935
|
-
selection[selection.length - 1].focusDOM.focus();
|
|
6010
|
+
update(update) {
|
|
6011
|
+
this.manager.update(update);
|
|
5936
6012
|
}
|
|
5937
|
-
|
|
5938
|
-
|
|
5939
|
-
|
|
5940
|
-
|
|
5941
|
-
|
|
5942
|
-
|
|
5943
|
-
|
|
5944
|
-
|
|
5945
|
-
|
|
5946
|
-
|
|
5947
|
-
|
|
5948
|
-
|
|
5949
|
-
|
|
5950
|
-
let parent = this.selection[sLen - 2];
|
|
5951
|
-
let next = findNextChild(parent.children, this.selection[sLen - 1], event.key == "ArrowUp" ? -1 : 1);
|
|
5952
|
-
if (next)
|
|
5953
|
-
this.setSelection(this.selection.slice(0, sLen - 1).concat(next));
|
|
5954
|
-
}
|
|
5955
|
-
else if (sLen == 1 && this.selection[0].children) {
|
|
5956
|
-
let inner = defaultChild(this.selection[0].children);
|
|
5957
|
-
if (inner)
|
|
5958
|
-
this.setSelection([this.selection[0], inner]);
|
|
5959
|
-
}
|
|
5960
|
-
}
|
|
5961
|
-
else if (event.key == "Home" || event.key == "End") {
|
|
5962
|
-
let child = findChild(sLen > 1 ? this.selection[sLen - 2].children : this.children, event.key == "Home");
|
|
5963
|
-
if (child)
|
|
5964
|
-
this.setSelection(this.selection.slice(0, sLen - 1).concat(child));
|
|
5965
|
-
}
|
|
5966
|
-
else if (event.key == " " || event.key == "Enter") {
|
|
5967
|
-
if (sLen) {
|
|
5968
|
-
let child = this.selection[sLen - 1];
|
|
5969
|
-
if (child.flags & 8) ;
|
|
5970
|
-
else if (child.children) {
|
|
5971
|
-
let inner = defaultChild(child.children);
|
|
5972
|
-
if (inner)
|
|
5973
|
-
this.setSelection(this.selection.concat(inner));
|
|
5974
|
-
}
|
|
5975
|
-
else {
|
|
5976
|
-
if (child.run)
|
|
5977
|
-
child.run(this.wg);
|
|
5978
|
-
this.setSelection([this.selection[0]]);
|
|
5979
|
-
}
|
|
6013
|
+
remove(wg) {
|
|
6014
|
+
for (let t of this.manager.tooltipViews)
|
|
6015
|
+
t.remove?.(wg);
|
|
6016
|
+
}
|
|
6017
|
+
passProp(name) {
|
|
6018
|
+
let value = undefined;
|
|
6019
|
+
for (let view of this.manager.tooltipViews) {
|
|
6020
|
+
let given = view[name];
|
|
6021
|
+
if (given !== undefined) {
|
|
6022
|
+
if (value === undefined)
|
|
6023
|
+
value = given;
|
|
6024
|
+
else if (value !== given)
|
|
6025
|
+
return undefined;
|
|
5980
6026
|
}
|
|
5981
6027
|
}
|
|
5982
|
-
|
|
5983
|
-
|
|
5984
|
-
|
|
5985
|
-
|
|
5986
|
-
|
|
6028
|
+
return value;
|
|
6029
|
+
}
|
|
6030
|
+
get offset() { return this.passProp("offset"); }
|
|
6031
|
+
get getCoords() { return this.passProp("getCoords"); }
|
|
6032
|
+
get overlap() { return this.passProp("overlap"); }
|
|
6033
|
+
get resize() { return this.passProp("resize"); }
|
|
6034
|
+
}
|
|
6035
|
+
const showHoverTooltipHost = /*@__PURE__*/Tooltip.show.derive(state => {
|
|
6036
|
+
let tooltips = state.facet(showHoverTooltip);
|
|
6037
|
+
if (tooltips.length === 0)
|
|
6038
|
+
return null;
|
|
6039
|
+
return {
|
|
6040
|
+
pos: Math.min(...tooltips.map(t => t.pos)),
|
|
6041
|
+
end: Math.max(...tooltips.map(t => t.end ?? t.pos)),
|
|
6042
|
+
create: HoverTooltipHost.create,
|
|
6043
|
+
above: tooltips[0].above,
|
|
6044
|
+
arrow: tooltips.some(t => t.arrow),
|
|
6045
|
+
};
|
|
6046
|
+
});
|
|
6047
|
+
class HoverPlugin {
|
|
6048
|
+
wg;
|
|
6049
|
+
source;
|
|
6050
|
+
field;
|
|
6051
|
+
setHover;
|
|
6052
|
+
hoverTime;
|
|
6053
|
+
lastMove;
|
|
6054
|
+
hoverTimeout = -1;
|
|
6055
|
+
restartTimeout = -1;
|
|
6056
|
+
pending = null;
|
|
6057
|
+
constructor(wg, source, field, setHover, hoverTime) {
|
|
6058
|
+
this.wg = wg;
|
|
6059
|
+
this.source = source;
|
|
6060
|
+
this.field = field;
|
|
6061
|
+
this.setHover = setHover;
|
|
6062
|
+
this.hoverTime = hoverTime;
|
|
6063
|
+
this.lastMove = { x: 0, y: 0, target: wg.dom, time: 0 };
|
|
6064
|
+
this.checkHover = this.checkHover.bind(this);
|
|
6065
|
+
wg.dom.addEventListener("mouseleave", this.mouseleave = this.mouseleave.bind(this));
|
|
6066
|
+
wg.dom.addEventListener("mousemove", this.mousemove = this.mousemove.bind(this));
|
|
6067
|
+
}
|
|
6068
|
+
update() {
|
|
6069
|
+
if (this.pending) {
|
|
6070
|
+
this.pending = null;
|
|
6071
|
+
clearTimeout(this.restartTimeout);
|
|
6072
|
+
this.restartTimeout = setTimeout(() => this.startHover(), 20);
|
|
5987
6073
|
}
|
|
5988
|
-
event.preventDefault();
|
|
5989
6074
|
}
|
|
5990
|
-
|
|
5991
|
-
|
|
6075
|
+
get active() {
|
|
6076
|
+
return this.wg.state.field(this.field);
|
|
6077
|
+
}
|
|
6078
|
+
checkHover() {
|
|
6079
|
+
this.hoverTimeout = -1;
|
|
6080
|
+
if (this.active.length)
|
|
5992
6081
|
return;
|
|
5993
|
-
let
|
|
5994
|
-
|
|
5995
|
-
|
|
5996
|
-
|
|
5997
|
-
|
|
5998
|
-
|
|
5999
|
-
|
|
6000
|
-
|
|
6001
|
-
|
|
6002
|
-
|
|
6003
|
-
|
|
6004
|
-
|
|
6005
|
-
}
|
|
6006
|
-
|
|
6007
|
-
|
|
6008
|
-
|
|
6009
|
-
if (
|
|
6010
|
-
|
|
6011
|
-
if (next)
|
|
6012
|
-
this.setSelection(this.selection.slice(0, i).concat([target, next]), false);
|
|
6013
|
-
}
|
|
6082
|
+
let hovered = Date.now() - this.lastMove.time;
|
|
6083
|
+
if (hovered < this.hoverTime)
|
|
6084
|
+
this.hoverTimeout = setTimeout(this.checkHover, this.hoverTime - hovered);
|
|
6085
|
+
else
|
|
6086
|
+
this.startHover();
|
|
6087
|
+
}
|
|
6088
|
+
startHover() {
|
|
6089
|
+
clearTimeout(this.restartTimeout);
|
|
6090
|
+
let { wg, lastMove } = this;
|
|
6091
|
+
let { pos, side } = wg.posAtCoords(lastMove);
|
|
6092
|
+
let open = this.source(wg, pos, side || -1);
|
|
6093
|
+
if (open?.then) {
|
|
6094
|
+
let pending = this.pending = { pos };
|
|
6095
|
+
open.then(result => {
|
|
6096
|
+
if (this.pending == pending) {
|
|
6097
|
+
this.pending = null;
|
|
6098
|
+
if (result && !(Array.isArray(result) && !result.length))
|
|
6099
|
+
wg.dispatch({ effects: this.setHover.of(Array.isArray(result) ? result : [result]) });
|
|
6014
6100
|
}
|
|
6015
|
-
}
|
|
6101
|
+
}, e => logException(wg.state, e, "hover tooltip"));
|
|
6016
6102
|
}
|
|
6017
|
-
else {
|
|
6018
|
-
|
|
6019
|
-
target.run(this.wg);
|
|
6020
|
-
this.setSelection(this.children.includes(target) ? [target] : this.selection.length ? [this.selection[0]] : [], false);
|
|
6103
|
+
else if (open && !(Array.isArray(open) && !open.length)) {
|
|
6104
|
+
wg.dispatch({ effects: this.setHover.of(Array.isArray(open) ? open : [open]) });
|
|
6021
6105
|
}
|
|
6022
|
-
event.preventDefault();
|
|
6023
6106
|
}
|
|
6024
|
-
|
|
6025
|
-
|
|
6026
|
-
|
|
6027
|
-
|
|
6028
|
-
|
|
6107
|
+
get tooltip() {
|
|
6108
|
+
let plugin = this.wg.plugin(tooltipPlugin);
|
|
6109
|
+
let index = plugin ? plugin.manager.tooltips.findIndex(t => t.create == HoverTooltipHost.create) : -1;
|
|
6110
|
+
return index > -1 ? plugin.manager.tooltipViews[index] : null;
|
|
6111
|
+
}
|
|
6112
|
+
mousemove(event) {
|
|
6113
|
+
this.lastMove = { x: event.clientX, y: event.clientY, target: event.target, time: Date.now() };
|
|
6114
|
+
if (this.hoverTimeout < 0)
|
|
6115
|
+
this.hoverTimeout = setTimeout(this.checkHover, this.hoverTime);
|
|
6116
|
+
let { active, tooltip } = this;
|
|
6117
|
+
if (active.length && tooltip && !isInTooltip(tooltip.dom, event) || this.pending) {
|
|
6118
|
+
let { pos } = active[0] || this.pending, end = active[0]?.end ?? pos;
|
|
6119
|
+
if ((pos == end ? this.wg.posAtCoords(this.lastMove).pos != pos
|
|
6120
|
+
: !isOverRange(this.wg, pos, end, event.clientX, event.clientY))) {
|
|
6121
|
+
this.wg.dispatch({ effects: this.setHover.of([]) });
|
|
6122
|
+
this.pending = null;
|
|
6123
|
+
}
|
|
6029
6124
|
}
|
|
6030
6125
|
}
|
|
6031
|
-
|
|
6032
|
-
clearTimeout(this.
|
|
6033
|
-
|
|
6034
|
-
|
|
6035
|
-
|
|
6036
|
-
|
|
6037
|
-
|
|
6038
|
-
|
|
6039
|
-
|
|
6040
|
-
|
|
6041
|
-
|
|
6042
|
-
}, 20);
|
|
6126
|
+
mouseleave(event) {
|
|
6127
|
+
clearTimeout(this.hoverTimeout);
|
|
6128
|
+
this.hoverTimeout = -1;
|
|
6129
|
+
let { active } = this;
|
|
6130
|
+
if (active.length) {
|
|
6131
|
+
let { tooltip } = this;
|
|
6132
|
+
let inTooltip = tooltip && tooltip.dom.contains(event.relatedTarget);
|
|
6133
|
+
if (!inTooltip)
|
|
6134
|
+
this.wg.dispatch({ effects: this.setHover.of([]) });
|
|
6135
|
+
else
|
|
6136
|
+
this.watchTooltipLeave(tooltip.dom);
|
|
6043
6137
|
}
|
|
6044
6138
|
}
|
|
6045
|
-
|
|
6046
|
-
|
|
6047
|
-
|
|
6139
|
+
watchTooltipLeave(tooltip) {
|
|
6140
|
+
let watch = (event) => {
|
|
6141
|
+
tooltip.removeEventListener("mouseleave", watch);
|
|
6142
|
+
if (this.active.length && !this.wg.dom.contains(event.relatedTarget))
|
|
6143
|
+
this.wg.dispatch({ effects: this.setHover.of([]) });
|
|
6144
|
+
};
|
|
6145
|
+
tooltip.addEventListener("mouseleave", watch);
|
|
6048
6146
|
}
|
|
6049
|
-
|
|
6050
|
-
|
|
6051
|
-
|
|
6052
|
-
|
|
6053
|
-
for (let i = start ? 0 : children.length - 1; start ? i < children.length : i >= 0; start ? i++ : i--) {
|
|
6054
|
-
let child = children[i];
|
|
6055
|
-
if (!(child.flags & 8))
|
|
6056
|
-
return child;
|
|
6147
|
+
remove() {
|
|
6148
|
+
clearTimeout(this.hoverTimeout);
|
|
6149
|
+
this.wg.dom.removeEventListener("mouseleave", this.mouseleave);
|
|
6150
|
+
this.wg.dom.removeEventListener("mousemove", this.mousemove);
|
|
6057
6151
|
}
|
|
6058
|
-
return null;
|
|
6059
6152
|
}
|
|
6060
|
-
|
|
6061
|
-
|
|
6062
|
-
|
|
6063
|
-
|
|
6064
|
-
|
|
6065
|
-
|
|
6066
|
-
|
|
6067
|
-
else if (i >= children.length)
|
|
6068
|
-
i = 0;
|
|
6069
|
-
if (i == index)
|
|
6070
|
-
return null;
|
|
6071
|
-
let child = children[i];
|
|
6072
|
-
if (!(child.flags & 32))
|
|
6073
|
-
return child;
|
|
6153
|
+
const tooltipMargin = 4;
|
|
6154
|
+
function isInTooltip(tooltip, event) {
|
|
6155
|
+
let { left, right, top, bottom } = tooltip.getBoundingClientRect(), arrow;
|
|
6156
|
+
if (arrow = tooltip.querySelector(".wg-tooltip-arrow")) {
|
|
6157
|
+
let arrowRect = arrow.getBoundingClientRect();
|
|
6158
|
+
top = Math.min(arrowRect.top, top);
|
|
6159
|
+
bottom = Math.max(arrowRect.bottom, bottom);
|
|
6074
6160
|
}
|
|
6161
|
+
return event.clientX >= left - tooltipMargin && event.clientX <= right + tooltipMargin &&
|
|
6162
|
+
event.clientY >= top - tooltipMargin && event.clientY <= bottom + tooltipMargin;
|
|
6075
6163
|
}
|
|
6076
|
-
function
|
|
6077
|
-
|
|
6078
|
-
|
|
6079
|
-
|
|
6080
|
-
|
|
6081
|
-
|
|
6082
|
-
},
|
|
6083
|
-
"&light": {
|
|
6084
|
-
"--wg-menu-color": "#555"
|
|
6085
|
-
},
|
|
6086
|
-
"&dark": {
|
|
6087
|
-
"--wg-menu-color": "#ccc"
|
|
6088
|
-
},
|
|
6089
|
-
"wg-menubar": {
|
|
6090
|
-
display: "flex",
|
|
6091
|
-
flexWrap: "wrap",
|
|
6092
|
-
gap: "5px",
|
|
6093
|
-
padding: "3px",
|
|
6094
|
-
color: "var(--wg-menu-color)",
|
|
6095
|
-
borderBottom: "1px solid var(--wg-border-color)",
|
|
6096
|
-
},
|
|
6097
|
-
".wg-menu-button:focus": {
|
|
6098
|
-
outline: "1.5px solid var(--wg-highlight-color)"
|
|
6099
|
-
},
|
|
6100
|
-
".wg-menu-button": {
|
|
6101
|
-
border: 0,
|
|
6102
|
-
padding: "3px",
|
|
6103
|
-
borderRadius: "4px",
|
|
6104
|
-
boxSizing: "content-box",
|
|
6105
|
-
backgroundColor: "transparent",
|
|
6106
|
-
font: "inherit",
|
|
6107
|
-
color: "inherit",
|
|
6108
|
-
height: "var(--wg-menu-item-size)",
|
|
6109
|
-
textAlign: "left",
|
|
6110
|
-
"&[aria-disabled]": {
|
|
6111
|
-
opacity: "0.3"
|
|
6112
|
-
},
|
|
6113
|
-
"&[aria-pressed]": {
|
|
6114
|
-
color: "var(--wg-highlight-color)"
|
|
6115
|
-
},
|
|
6116
|
-
"&:hover": {
|
|
6117
|
-
backgroundColor: "#88888820",
|
|
6118
|
-
},
|
|
6119
|
-
},
|
|
6120
|
-
".wg-button-label": {
|
|
6121
|
-
display: "inline-block",
|
|
6122
|
-
minWidth: "var(--wg-submenu-width)",
|
|
6123
|
-
padding: "0 3px",
|
|
6124
|
-
},
|
|
6125
|
-
"svg.wg-icon": {
|
|
6126
|
-
fill: "currentColor",
|
|
6127
|
-
width: "var(--wg-menu-item-size)",
|
|
6128
|
-
height: "var(--wg-menu-item-size)",
|
|
6129
|
-
},
|
|
6130
|
-
"wg-menu-spacer": {
|
|
6131
|
-
display: "block",
|
|
6132
|
-
width: "7px"
|
|
6133
|
-
},
|
|
6134
|
-
"wg-submenu": {
|
|
6135
|
-
display: "block",
|
|
6136
|
-
position: "relative",
|
|
6137
|
-
lineHeight: ".6",
|
|
6138
|
-
whiteSpace: "nowrap"
|
|
6139
|
-
},
|
|
6140
|
-
"wg-menu-list": {
|
|
6141
|
-
display: "flex",
|
|
6142
|
-
flexDirection: "column",
|
|
6143
|
-
alignItems: "stretch",
|
|
6144
|
-
gap: "5px",
|
|
6145
|
-
padding: "5px",
|
|
6146
|
-
borderRadius: "4px",
|
|
6147
|
-
backgroundColor: "var(--wg-panel-color)",
|
|
6148
|
-
position: "absolute",
|
|
6149
|
-
zIndex: "10",
|
|
6150
|
-
top: "100%",
|
|
6151
|
-
boxShadow: "0 2px 8px 0 rgba(128, 128, 128, 0.2)",
|
|
6152
|
-
"& wg-menu-list": {
|
|
6153
|
-
left: "100%",
|
|
6154
|
-
top: 0
|
|
6155
|
-
}
|
|
6156
|
-
},
|
|
6157
|
-
".wg-submenu-arrow:after": {
|
|
6158
|
-
padding: "0 2px",
|
|
6159
|
-
fontSize: "80%",
|
|
6160
|
-
verticalAlign: "10%",
|
|
6161
|
-
opacity: "0.4",
|
|
6162
|
-
content: "'▾'"
|
|
6163
|
-
},
|
|
6164
|
-
".wg-submenu-arrow.wg-submenu-arrow-open:after": {
|
|
6165
|
-
content: "'▴'"
|
|
6166
|
-
},
|
|
6167
|
-
});
|
|
6168
|
-
const barTemplate = /*@__PURE__*/GardState.Facet.define({
|
|
6169
|
-
combine: inputs => inputs.length ? inputs[0] : [Menu.Group.top.template()]
|
|
6170
|
-
});
|
|
6171
|
-
function menuBar(config = {}) {
|
|
6172
|
-
let extensions = [menuBarPanel, theme];
|
|
6173
|
-
if (config.template)
|
|
6174
|
-
extensions.push(barTemplate.of(Array.isArray(config.template) ? config.template : [config.template]));
|
|
6175
|
-
return extensions;
|
|
6164
|
+
function isOverRange(wg, from, to, x, y, margin) {
|
|
6165
|
+
let rect = wg.contentDOM.getBoundingClientRect();
|
|
6166
|
+
if (rect.left > x || rect.right < x || rect.top > y || rect.bottom < y)
|
|
6167
|
+
return false;
|
|
6168
|
+
let pos = wg.posAtCoords({ x, y }).pos;
|
|
6169
|
+
return pos >= from && pos <= to;
|
|
6176
6170
|
}
|
|
6177
6171
|
|
|
6178
6172
|
const Dialog = /*@__PURE__*/(function (Dialog) {
|
|
6179
6173
|
function show(wg, config) {
|
|
6180
6174
|
let resolve;
|
|
6181
|
-
let
|
|
6182
|
-
let
|
|
6183
|
-
|
|
6184
|
-
|
|
6175
|
+
let result = new Promise(r => resolve = r);
|
|
6176
|
+
let hint = config.positioningHint === true ? PositioningHint.get() : config.positioningHint;
|
|
6177
|
+
let tooltip = hint || !config.tooltip ? null : {
|
|
6178
|
+
...config.tooltip,
|
|
6179
|
+
create: (wg) => createDialog(wg, dialog),
|
|
6180
|
+
}, offset = null;
|
|
6181
|
+
if (hint) {
|
|
6182
|
+
let editorRect = wg.dom.getBoundingClientRect();
|
|
6183
|
+
offset = {
|
|
6184
|
+
x: wg.state.textLTR ? hint.left - editorRect.left : editorRect.right - hint.right,
|
|
6185
|
+
y: hint.bottom - editorRect.top
|
|
6186
|
+
};
|
|
6185
6187
|
}
|
|
6186
|
-
|
|
6187
|
-
|
|
6188
|
-
|
|
6189
|
-
|
|
6190
|
-
|
|
6191
|
-
|
|
6192
|
-
|
|
6193
|
-
|
|
6194
|
-
|
|
6195
|
-
|
|
6196
|
-
|
|
6197
|
-
|
|
6188
|
+
let dialog = new OpenDialog(config, resolve, tooltip, offset);
|
|
6189
|
+
let effects = [openDialog.of(dialog)];
|
|
6190
|
+
if (!wg.state.field(dialogs, false))
|
|
6191
|
+
effects.push(GardState.appendConfig.of([dialogs, renderDialogs]));
|
|
6192
|
+
wg.dispatch({ effects });
|
|
6193
|
+
wg.scheduleDOMRead(() => {
|
|
6194
|
+
if (!wg.state.field(dialogs).includes(dialog))
|
|
6195
|
+
dialog.resolve(null);
|
|
6196
|
+
});
|
|
6197
|
+
return {
|
|
6198
|
+
close: () => doCloseDialog(wg, dialog),
|
|
6199
|
+
result
|
|
6200
|
+
};
|
|
6198
6201
|
}
|
|
6199
6202
|
Dialog.show = show;
|
|
6200
|
-
function get(wg,
|
|
6201
|
-
let
|
|
6202
|
-
|
|
6203
|
-
|
|
6204
|
-
|
|
6205
|
-
|
|
6206
|
-
}
|
|
6207
|
-
return null;
|
|
6203
|
+
function get(wg, key) {
|
|
6204
|
+
let active = wg.state.field(dialogs, false);
|
|
6205
|
+
let found = active && active.find(d => d.spec.key === key);
|
|
6206
|
+
if (!found)
|
|
6207
|
+
return null;
|
|
6208
|
+
return { dom: dialogDOM(wg, found), close: () => doCloseDialog(wg, found) };
|
|
6208
6209
|
}
|
|
6209
6210
|
Dialog.get = get;
|
|
6210
|
-
function close(wg, className) {
|
|
6211
|
-
let dialogs = wg.state.field(dialogField, false) || [];
|
|
6212
|
-
for (let open of dialogs) {
|
|
6213
|
-
let panel = Panel.get(wg, open);
|
|
6214
|
-
if (panel && panel.dom.classList.contains(className)) {
|
|
6215
|
-
wg.dispatch({ effects: closeDialogEffect.of(open) });
|
|
6216
|
-
return true;
|
|
6217
|
-
}
|
|
6218
|
-
}
|
|
6219
|
-
return false;
|
|
6220
|
-
}
|
|
6221
|
-
Dialog.close = close;
|
|
6222
6211
|
;return Dialog})({});
|
|
6223
|
-
|
|
6224
|
-
|
|
6225
|
-
|
|
6226
|
-
|
|
6227
|
-
|
|
6228
|
-
|
|
6229
|
-
|
|
6230
|
-
|
|
6231
|
-
|
|
6232
|
-
|
|
6233
|
-
|
|
6234
|
-
|
|
6235
|
-
}
|
|
6236
|
-
|
|
6237
|
-
|
|
6238
|
-
|
|
6212
|
+
function dialogDOM(wg, dialog) {
|
|
6213
|
+
let plugin = wg.plugin(renderDialogs);
|
|
6214
|
+
let index = plugin ? plugin.active.indexOf(dialog) : -1;
|
|
6215
|
+
return index > -1 ? plugin.elements[index] : null;
|
|
6216
|
+
}
|
|
6217
|
+
function doCloseDialog(wg, dialog) {
|
|
6218
|
+
let active = wg.state.field(dialogs, false);
|
|
6219
|
+
if (active && active.includes(dialog)) {
|
|
6220
|
+
let dom = dialogDOM(wg, dialog);
|
|
6221
|
+
if (dom && dom.contains(wg.win.document.activeElement))
|
|
6222
|
+
wg.focus();
|
|
6223
|
+
wg.dispatch({ effects: closeDialog.of(dialog) });
|
|
6224
|
+
}
|
|
6225
|
+
}
|
|
6226
|
+
function createDialog(wg, dialog) {
|
|
6227
|
+
let config = dialog.spec;
|
|
6239
6228
|
let content = config.content ? config.content(wg, () => done(null)) : null;
|
|
6240
6229
|
if (!content) {
|
|
6241
6230
|
content = document.createElement("form");
|
|
@@ -6270,10 +6259,7 @@ function createDialog(wg, config, result) {
|
|
|
6270
6259
|
for (let i = 0; i < forms.length; i++) {
|
|
6271
6260
|
let form = forms[i];
|
|
6272
6261
|
form.addEventListener("keydown", (event) => {
|
|
6273
|
-
if (event.keyCode ==
|
|
6274
|
-
done(null);
|
|
6275
|
-
}
|
|
6276
|
-
else if (event.keyCode == 13) { event.preventDefault();
|
|
6262
|
+
if (event.keyCode == 13) { event.preventDefault();
|
|
6277
6263
|
done(form);
|
|
6278
6264
|
}
|
|
6279
6265
|
});
|
|
@@ -6288,691 +6274,1057 @@ function createDialog(wg, config, result) {
|
|
|
6288
6274
|
close.className = "wg-dialog-close";
|
|
6289
6275
|
close.type = "button";
|
|
6290
6276
|
close.append("×");
|
|
6291
|
-
let
|
|
6292
|
-
|
|
6277
|
+
let dom = document.createElement("dialog");
|
|
6278
|
+
dom.open = true;
|
|
6279
|
+
dom.append(content, close);
|
|
6280
|
+
dom.addEventListener("keydown", event => {
|
|
6281
|
+
if (event.keyCode == 27) { event.preventDefault();
|
|
6282
|
+
done(null);
|
|
6283
|
+
}
|
|
6284
|
+
});
|
|
6293
6285
|
if (config.class)
|
|
6294
|
-
|
|
6286
|
+
dom.className = config.class;
|
|
6295
6287
|
function done(form) {
|
|
6296
|
-
|
|
6297
|
-
|
|
6298
|
-
|
|
6288
|
+
dialog.resolve(form);
|
|
6289
|
+
doCloseDialog(wg, dialog);
|
|
6290
|
+
}
|
|
6291
|
+
let focus = null;
|
|
6292
|
+
if (config.focus) {
|
|
6293
|
+
if (typeof config.focus == "string")
|
|
6294
|
+
focus = dom.querySelector(config.focus);
|
|
6295
|
+
else
|
|
6296
|
+
focus = content.querySelector("input") || content.querySelector("button");
|
|
6299
6297
|
}
|
|
6300
|
-
let mustFocus = config.focus;
|
|
6301
6298
|
return {
|
|
6302
|
-
dom
|
|
6303
|
-
top: config.top !== false,
|
|
6299
|
+
dom,
|
|
6304
6300
|
connect: () => {
|
|
6305
|
-
if (
|
|
6306
|
-
|
|
6307
|
-
let focus;
|
|
6308
|
-
if (typeof config.focus == "string")
|
|
6309
|
-
focus = content.querySelector(config.focus);
|
|
6310
|
-
else
|
|
6311
|
-
focus = content.querySelector("input") || content.querySelector("button");
|
|
6312
|
-
if (focus && "select" in focus)
|
|
6301
|
+
if (focus) {
|
|
6302
|
+
if ("select" in focus)
|
|
6313
6303
|
focus.select();
|
|
6314
|
-
else if (
|
|
6304
|
+
else if ("focus" in focus)
|
|
6315
6305
|
focus.focus();
|
|
6306
|
+
focus = null;
|
|
6316
6307
|
}
|
|
6317
6308
|
}
|
|
6318
6309
|
};
|
|
6319
6310
|
}
|
|
6320
|
-
|
|
6321
|
-
|
|
6322
|
-
|
|
6323
|
-
|
|
6324
|
-
|
|
6325
|
-
|
|
6326
|
-
|
|
6327
|
-
|
|
6328
|
-
|
|
6329
|
-
|
|
6330
|
-
this.facet = facet;
|
|
6331
|
-
this.createTooltipView = createTooltipView;
|
|
6332
|
-
this.removeTooltipView = removeTooltipView;
|
|
6333
|
-
this.input = wg.state.facet(facet);
|
|
6334
|
-
this.tooltips = this.input.filter(t => t);
|
|
6335
|
-
let prev = null;
|
|
6336
|
-
this.tooltipViews = this.tooltips.map(t => prev = createTooltipView(t, prev));
|
|
6311
|
+
class OpenDialog {
|
|
6312
|
+
spec;
|
|
6313
|
+
resolve;
|
|
6314
|
+
tooltip;
|
|
6315
|
+
offset;
|
|
6316
|
+
constructor(spec, resolve, tooltip, offset) {
|
|
6317
|
+
this.spec = spec;
|
|
6318
|
+
this.resolve = resolve;
|
|
6319
|
+
this.tooltip = tooltip;
|
|
6320
|
+
this.offset = offset;
|
|
6337
6321
|
}
|
|
6338
|
-
|
|
6339
|
-
|
|
6340
|
-
|
|
6341
|
-
|
|
6342
|
-
|
|
6343
|
-
|
|
6344
|
-
|
|
6345
|
-
|
|
6346
|
-
|
|
6347
|
-
|
|
6348
|
-
|
|
6349
|
-
|
|
6350
|
-
|
|
6351
|
-
|
|
6352
|
-
|
|
6353
|
-
|
|
6354
|
-
|
|
6355
|
-
known = i;
|
|
6322
|
+
}
|
|
6323
|
+
const openDialog = /*@__PURE__*/Transaction.Effect.define();
|
|
6324
|
+
const closeDialog = /*@__PURE__*/Transaction.Effect.define();
|
|
6325
|
+
const dialogs = /*@__PURE__*/GardState.Field.define({
|
|
6326
|
+
create: () => [],
|
|
6327
|
+
update: (value, tr) => {
|
|
6328
|
+
for (let e of tr.effects) {
|
|
6329
|
+
if (e.is(openDialog))
|
|
6330
|
+
value = value.concat(e.value);
|
|
6331
|
+
else if (e.is(closeDialog))
|
|
6332
|
+
value = value.filter(d => d != e.value);
|
|
6333
|
+
}
|
|
6334
|
+
for (let i = 0; i < value.length; i++) {
|
|
6335
|
+
let { closedBy } = value[i].spec;
|
|
6336
|
+
if (closedBy && closedBy(tr)) {
|
|
6337
|
+
value = value.slice(0, i).concat(value.slice(i + 1));
|
|
6338
|
+
i--;
|
|
6356
6339
|
}
|
|
6357
|
-
|
|
6358
|
-
|
|
6359
|
-
|
|
6360
|
-
|
|
6340
|
+
}
|
|
6341
|
+
return value;
|
|
6342
|
+
},
|
|
6343
|
+
provide: f => Tooltip.show.deriveN(state => {
|
|
6344
|
+
let tooltips = [];
|
|
6345
|
+
for (let d of state.field(f))
|
|
6346
|
+
if (d.tooltip)
|
|
6347
|
+
tooltips.push(d.tooltip);
|
|
6348
|
+
return tooltips;
|
|
6349
|
+
})
|
|
6350
|
+
});
|
|
6351
|
+
const renderDialogs = /*@__PURE__*/Wordgard.Plugin.fromClass(class {
|
|
6352
|
+
active = [];
|
|
6353
|
+
elements = [];
|
|
6354
|
+
mustPosition = false;
|
|
6355
|
+
constructor(wg) {
|
|
6356
|
+
this.positionDialogs = this.positionDialogs.bind(this);
|
|
6357
|
+
this.updateTo(wg, wg.state.field(dialogs));
|
|
6358
|
+
if (this.mustPosition)
|
|
6359
|
+
wg.scheduleDOMRead(this.positionDialogs);
|
|
6360
|
+
}
|
|
6361
|
+
update(update) {
|
|
6362
|
+
let active = update.state.field(dialogs), changed = this.active != active;
|
|
6363
|
+
if (changed)
|
|
6364
|
+
this.updateTo(update.editor, active);
|
|
6365
|
+
if ((update.geometryChanged || changed) && this.mustPosition)
|
|
6366
|
+
update.editor.scheduleDOMRead(this.positionDialogs);
|
|
6367
|
+
}
|
|
6368
|
+
updateTo(wg, active) {
|
|
6369
|
+
for (let i = 0; i < this.active.length; i++)
|
|
6370
|
+
if (!active.includes(this.active[i])) {
|
|
6371
|
+
let elt = this.elements[i], dialog = this.active[i];
|
|
6372
|
+
if (elt)
|
|
6373
|
+
elt.remove();
|
|
6374
|
+
dialog.resolve(null);
|
|
6375
|
+
}
|
|
6376
|
+
this.mustPosition = false;
|
|
6377
|
+
this.elements = active.map((dialog, i) => {
|
|
6378
|
+
if (dialog.tooltip)
|
|
6379
|
+
return null;
|
|
6380
|
+
this.mustPosition = true;
|
|
6381
|
+
let panel;
|
|
6382
|
+
let found = this.active.indexOf(dialog);
|
|
6383
|
+
if (found > -1) {
|
|
6384
|
+
panel = this.elements[found];
|
|
6361
6385
|
}
|
|
6362
6386
|
else {
|
|
6363
|
-
let
|
|
6364
|
-
|
|
6365
|
-
|
|
6366
|
-
|
|
6367
|
-
|
|
6387
|
+
let { dom, connect } = createDialog(wg, dialog);
|
|
6388
|
+
dom.classList.add("wg-free-dialog");
|
|
6389
|
+
wg.dom.appendChild(dom);
|
|
6390
|
+
connect();
|
|
6391
|
+
panel = dom;
|
|
6392
|
+
}
|
|
6393
|
+
panel.style.zIndex = String(400 + i);
|
|
6394
|
+
return panel;
|
|
6395
|
+
});
|
|
6396
|
+
this.active = active;
|
|
6397
|
+
}
|
|
6398
|
+
positionDialogs(wg) {
|
|
6399
|
+
let sizes = this.elements.map(e => e && e.getBoundingClientRect());
|
|
6400
|
+
let editor = wg.dom.getBoundingClientRect();
|
|
6401
|
+
let windowWidth = wg.win.innerWidth, windowHeight = wg.win.innerHeight;
|
|
6402
|
+
let midX = (Math.max(0, editor.left) + Math.min(windowWidth, editor.right)) / 2;
|
|
6403
|
+
let midY = (Math.max(0, editor.top) + Math.min(windowHeight, editor.bottom)) / 2;
|
|
6404
|
+
let ltr = wg.state.textLTR;
|
|
6405
|
+
wg.scheduleDOMWrite(() => {
|
|
6406
|
+
for (let i = 0; i < sizes.length; i++) {
|
|
6407
|
+
let size = sizes[i];
|
|
6408
|
+
if (!size)
|
|
6409
|
+
continue;
|
|
6410
|
+
let { offset } = this.active[i];
|
|
6411
|
+
let baseX, baseY;
|
|
6412
|
+
if (offset) {
|
|
6413
|
+
baseY = editor.top + offset.y;
|
|
6414
|
+
baseX = ltr ? editor.left + offset.x : editor.right - offset.x - size.width;
|
|
6415
|
+
}
|
|
6416
|
+
else {
|
|
6417
|
+
baseX = midX - size.width / 2;
|
|
6418
|
+
baseY = midY - size.height / 2;
|
|
6419
|
+
}
|
|
6420
|
+
if (baseX < 0)
|
|
6421
|
+
baseX = 0;
|
|
6422
|
+
else if (baseX + size.width > windowWidth && size.width < windowWidth)
|
|
6423
|
+
baseX = windowWidth - size.width;
|
|
6424
|
+
if (baseY < 0)
|
|
6425
|
+
baseY = 0;
|
|
6426
|
+
else if (baseY + size.height > windowHeight && size.height < windowHeight)
|
|
6427
|
+
baseY = windowHeight - size.height;
|
|
6428
|
+
let elt = this.elements[i];
|
|
6429
|
+
elt.style.left = baseX + "px";
|
|
6430
|
+
elt.style.top = baseY + "px";
|
|
6368
6431
|
}
|
|
6432
|
+
});
|
|
6433
|
+
}
|
|
6434
|
+
destroy() {
|
|
6435
|
+
for (let elt of this.elements)
|
|
6436
|
+
if (elt)
|
|
6437
|
+
elt.remove();
|
|
6438
|
+
for (let dialog of this.active)
|
|
6439
|
+
dialog.resolve(null);
|
|
6440
|
+
}
|
|
6441
|
+
}, plugin => plugin.eventHandler("scroll", (event, wg, val) => {
|
|
6442
|
+
if (val.mustPosition)
|
|
6443
|
+
wg.scheduleDOMRead(val.positionDialogs);
|
|
6444
|
+
}));
|
|
6445
|
+
const PositioningHint = /*@__PURE__*/(function (PositioningHint) {
|
|
6446
|
+
let currentHint = null;
|
|
6447
|
+
function runWith(hint, run) {
|
|
6448
|
+
let prev = currentHint;
|
|
6449
|
+
currentHint = hint;
|
|
6450
|
+
try {
|
|
6451
|
+
return run();
|
|
6369
6452
|
}
|
|
6370
|
-
|
|
6371
|
-
|
|
6372
|
-
this.removeTooltipView(t);
|
|
6373
|
-
if (update.editor.connected)
|
|
6374
|
-
t.disconnect?.(update.editor);
|
|
6375
|
-
t.remove?.(update.editor);
|
|
6376
|
-
}
|
|
6377
|
-
if (above) {
|
|
6378
|
-
newAbove.forEach((val, i) => above[i] = val);
|
|
6379
|
-
above.length = newAbove.length;
|
|
6453
|
+
finally {
|
|
6454
|
+
currentHint = prev;
|
|
6380
6455
|
}
|
|
6381
|
-
this.input = input;
|
|
6382
|
-
this.tooltips = tooltips;
|
|
6383
|
-
this.tooltipViews = tooltipViews;
|
|
6384
|
-
return true;
|
|
6385
6456
|
}
|
|
6457
|
+
PositioningHint.runWith = runWith;
|
|
6458
|
+
function get() {
|
|
6459
|
+
return currentHint ? currentHint() : null;
|
|
6460
|
+
}
|
|
6461
|
+
PositioningHint.get = get;
|
|
6462
|
+
;return PositioningHint})({});
|
|
6463
|
+
|
|
6464
|
+
function collectKeyDescs(bindings) {
|
|
6465
|
+
let groups = [];
|
|
6466
|
+
let add = (group, key, desc) => {
|
|
6467
|
+
let found = groups.find(g => g.group == group);
|
|
6468
|
+
if (!found)
|
|
6469
|
+
groups.push(found = { group, bindings: [] });
|
|
6470
|
+
found.bindings.push({ key, desc });
|
|
6471
|
+
};
|
|
6472
|
+
for (let binding of bindings) {
|
|
6473
|
+
let group = binding.spec.group || null;
|
|
6474
|
+
let name = binding.spec[currentPlatform] || binding.spec.key;
|
|
6475
|
+
if (name) {
|
|
6476
|
+
if (binding.spec.description)
|
|
6477
|
+
add(group, normalizeKeyName(name, currentPlatform), binding.spec.description);
|
|
6478
|
+
if (binding.spec.shiftDescription)
|
|
6479
|
+
add(group, "Shift-" + normalizeKeyName(name, currentPlatform), binding.spec.shiftDescription);
|
|
6480
|
+
}
|
|
6481
|
+
}
|
|
6482
|
+
return groups.sort((a, b) => (a.group?.rank ?? 0) - (b.group?.rank || 0));
|
|
6483
|
+
}
|
|
6484
|
+
function resolveText(state, text) {
|
|
6485
|
+
return typeof text == "string" ? text : text(state);
|
|
6486
|
+
}
|
|
6487
|
+
function renderKeyDescs(state, groups) {
|
|
6488
|
+
let frag = document.createDocumentFragment();
|
|
6489
|
+
frag.append(cr("h3", { class: "wg-dialog-title" }, phrases.get(state, "key_bindings")));
|
|
6490
|
+
frag.append(cr("div", { class: "wg-key-list", tabindex: "-1" }, groups.map(group => [
|
|
6491
|
+
group.group ? cr("h4", resolveText(state, group.group.description)) : null,
|
|
6492
|
+
group.bindings.map(({ key, desc }) => [
|
|
6493
|
+
cr("div", cr("kbd", key)),
|
|
6494
|
+
cr("div", resolveText(state, desc))
|
|
6495
|
+
])
|
|
6496
|
+
])));
|
|
6497
|
+
return frag;
|
|
6498
|
+
}
|
|
6499
|
+
function keyBindingHelp() {
|
|
6500
|
+
return [keyBindingHelp.keyBindings, keyBindingHelp.button];
|
|
6501
|
+
}
|
|
6502
|
+
;keyBindingHelp = /*@__PURE__*/(function (keyBindingHelp) {
|
|
6503
|
+
keyBindingHelp.showKeyBindings = wg => {
|
|
6504
|
+
let open = Dialog.get(wg, keyBindingHelp.showKeyBindings);
|
|
6505
|
+
if (open) {
|
|
6506
|
+
open.close();
|
|
6507
|
+
return true;
|
|
6508
|
+
}
|
|
6509
|
+
let descs = collectKeyDescs(wg.state.field(KeyBinding.keymap));
|
|
6510
|
+
if (!descs.length)
|
|
6511
|
+
return false;
|
|
6512
|
+
Dialog.show(wg, {
|
|
6513
|
+
key: keyBindingHelp.showKeyBindings,
|
|
6514
|
+
content: () => renderKeyDescs(wg.state, descs),
|
|
6515
|
+
class: "wg-key-help",
|
|
6516
|
+
focus: ".wg-key-list",
|
|
6517
|
+
positioningHint: true
|
|
6518
|
+
});
|
|
6519
|
+
return true;
|
|
6520
|
+
};
|
|
6521
|
+
keyBindingHelp.button = Menu.Button.define({
|
|
6522
|
+
run: keyBindingHelp.showKeyBindings,
|
|
6523
|
+
label: { icon: "M24 31c-2 0-4-2-4-4C22 14 32 5 49 5c17 0 28 10 28 24 0 10-5 17-13 22-8 5-11 8-11 15v0a4 4 0 0 1-4 4h-6a4 4 0 0 1-4-4l0-1c0-9 4-15 12-20 8-5 10-9 10-15 0-7-6-13-14-13-8 0-13 4-15 11 0 2-2 3-4 3h-6ZM46 95c5 0 8-4 8-8 0-5-4-8-8-8-5 0-8 4-8 8S42 95 46 95" },
|
|
6524
|
+
description: phrases.ref("show_keys"),
|
|
6525
|
+
parent: Menu.Group.top,
|
|
6526
|
+
rank: 99
|
|
6527
|
+
});
|
|
6528
|
+
keyBindingHelp.keyBindings = [
|
|
6529
|
+
KeyBinding.of({ key: "Mod-?", run: keyBindingHelp.showKeyBindings, description: phrases.ref("show_keys"),
|
|
6530
|
+
shift: keyBindingHelp.showKeyBindings }),
|
|
6531
|
+
KeyBinding.of({ key: "Mod-Shift-/", run: keyBindingHelp.showKeyBindings }),
|
|
6532
|
+
];
|
|
6533
|
+
;return keyBindingHelp})(keyBindingHelp);
|
|
6534
|
+
|
|
6535
|
+
function offset(add, offset) {
|
|
6536
|
+
return (v, from, to) => add(v, from + offset, to == null ? undefined : to + offset);
|
|
6386
6537
|
}
|
|
6387
|
-
|
|
6388
|
-
|
|
6389
|
-
|
|
6390
|
-
|
|
6391
|
-
|
|
6392
|
-
})
|
|
6393
|
-
});
|
|
6394
|
-
const knownHeight = /*@__PURE__*/(() => new WeakMap())();
|
|
6395
|
-
const tooltipPlugin = /*@__PURE__*/Wordgard.Plugin.fromClass(class {
|
|
6396
|
-
wg;
|
|
6397
|
-
manager;
|
|
6398
|
-
above = [];
|
|
6399
|
-
inView = true;
|
|
6400
|
-
position;
|
|
6401
|
-
madeAbsolute = false;
|
|
6402
|
-
parent;
|
|
6403
|
-
classes;
|
|
6404
|
-
intersectionObserver;
|
|
6405
|
-
resizeObserver;
|
|
6406
|
-
lastTransaction = 0;
|
|
6407
|
-
measureTimeout = -1;
|
|
6408
|
-
constructor(wg) {
|
|
6409
|
-
this.wg = wg;
|
|
6410
|
-
let config = wg.state.facet(tooltipConfig);
|
|
6411
|
-
this.position = config.position;
|
|
6412
|
-
this.parent = config.parent;
|
|
6413
|
-
this.classes = wg.themeClasses;
|
|
6414
|
-
this.createContainer();
|
|
6415
|
-
this.measure = this.measure.bind(this);
|
|
6416
|
-
this.resizeObserver = typeof ResizeObserver == "function" ? new ResizeObserver(() => this.measureSoon()) : null;
|
|
6417
|
-
this.manager = new TooltipViewManager(wg, Tooltip.show, (t, p) => this.createTooltip(t, p), t => {
|
|
6418
|
-
if (this.resizeObserver)
|
|
6419
|
-
this.resizeObserver.unobserve(t.dom);
|
|
6420
|
-
t.dom.remove();
|
|
6538
|
+
function init(type, create, source, doc) {
|
|
6539
|
+
return create(add => {
|
|
6540
|
+
doc.iterate((node, pos) => {
|
|
6541
|
+
if (node.isPlot && doc.schema.matchNode(node.type, type))
|
|
6542
|
+
source(node, pos + 1, add);
|
|
6421
6543
|
});
|
|
6422
|
-
|
|
6423
|
-
|
|
6424
|
-
|
|
6425
|
-
|
|
6426
|
-
|
|
6427
|
-
|
|
6428
|
-
|
|
6429
|
-
|
|
6430
|
-
|
|
6431
|
-
|
|
6432
|
-
|
|
6433
|
-
|
|
6434
|
-
|
|
6435
|
-
|
|
6436
|
-
|
|
6437
|
-
|
|
6438
|
-
|
|
6439
|
-
|
|
6544
|
+
});
|
|
6545
|
+
}
|
|
6546
|
+
function refreshByPred(type, source, doc, deco, pred) {
|
|
6547
|
+
let recreate = [];
|
|
6548
|
+
doc.iterate((node, pos) => {
|
|
6549
|
+
if (doc.schema.matchNode(node.type, type) && pred(node))
|
|
6550
|
+
recreate.push({
|
|
6551
|
+
from: pos, to: pos + node.length,
|
|
6552
|
+
add: add => source(node, pos + 1, add)
|
|
6553
|
+
});
|
|
6554
|
+
});
|
|
6555
|
+
return recreate.length ? deco.modify({ replace: recreate }) : deco;
|
|
6556
|
+
}
|
|
6557
|
+
function update(config, create, source, deco, tr) {
|
|
6558
|
+
let doc = tr.newDoc;
|
|
6559
|
+
let refresh = config.refresh && config.refresh(tr);
|
|
6560
|
+
if (refresh === true)
|
|
6561
|
+
return init(config.type, create, source, doc);
|
|
6562
|
+
if (refresh)
|
|
6563
|
+
deco = refreshByPred(config.type, source, tr.startState.doc, deco, refresh);
|
|
6564
|
+
if (!tr.docChanged && !refresh)
|
|
6565
|
+
return deco;
|
|
6566
|
+
let recreate = [];
|
|
6567
|
+
let clear = [];
|
|
6568
|
+
tr.changes.iterChangedRanges((fromA, toA, fromB, toB) => {
|
|
6569
|
+
let covered = false;
|
|
6570
|
+
doc.iterate(fromB, toB, (node, pos) => {
|
|
6571
|
+
if (doc.schema.matchNode(node.type, config.type) && !recreate.some(r => r.from == pos)) {
|
|
6572
|
+
recreate.push({
|
|
6573
|
+
from: pos, to: pos + node.length,
|
|
6574
|
+
add: add => source(node, pos + 1, add)
|
|
6575
|
+
});
|
|
6576
|
+
if (pos < toB && pos + node.length > toB)
|
|
6577
|
+
covered = true;
|
|
6578
|
+
return false;
|
|
6579
|
+
}
|
|
6580
|
+
});
|
|
6581
|
+
if (!covered) {
|
|
6582
|
+
let end = tr.startState.doc.resolve(toA);
|
|
6583
|
+
let open = end.matchingParent(p => doc.schema.matchNode(p.type, config.type));
|
|
6584
|
+
if (open && open.before >= fromA)
|
|
6585
|
+
clear.push({ from: open.before, to: open.after });
|
|
6440
6586
|
}
|
|
6587
|
+
});
|
|
6588
|
+
if (clear.length)
|
|
6589
|
+
deco = deco.modify({ replace: clear });
|
|
6590
|
+
deco = deco.map(tr.changes, recreate);
|
|
6591
|
+
return deco;
|
|
6592
|
+
}
|
|
6593
|
+
function decoratePlots(config) {
|
|
6594
|
+
let result = [];
|
|
6595
|
+
let { type, points, ranges } = config;
|
|
6596
|
+
if (points) {
|
|
6597
|
+
let source = (plot, start, add) => points(plot, offset(add, start));
|
|
6598
|
+
let field = GardState.Field.define({
|
|
6599
|
+
create(state) { return init(type, PointSet.create, source, state.doc); },
|
|
6600
|
+
update(value, tr) { return update(config, PointSet.create, source, value, tr); }
|
|
6601
|
+
});
|
|
6602
|
+
result.push(field, Decoration.Point.source.of(s => s.field(field)));
|
|
6441
6603
|
}
|
|
6442
|
-
|
|
6443
|
-
|
|
6444
|
-
|
|
6445
|
-
|
|
6446
|
-
|
|
6604
|
+
if (ranges) {
|
|
6605
|
+
let source = (plot, start, add) => ranges(plot, offset(add, start));
|
|
6606
|
+
let field = GardState.Field.define({
|
|
6607
|
+
create(state) { return init(type, RangeSet.create, source, state.doc); },
|
|
6608
|
+
update(value, tr) { return update(config, RangeSet.create, source, value, tr); }
|
|
6609
|
+
});
|
|
6610
|
+
result.push(field, Decoration.Range.source.of(s => s.field(field)));
|
|
6611
|
+
}
|
|
6612
|
+
return result;
|
|
6613
|
+
}
|
|
6614
|
+
|
|
6615
|
+
const panelConfig = /*@__PURE__*/GardState.Facet.define({
|
|
6616
|
+
combine(configs) {
|
|
6617
|
+
let topContainer, bottomContainer;
|
|
6618
|
+
for (let c of configs) {
|
|
6619
|
+
topContainer ||= c.topContainer;
|
|
6620
|
+
bottomContainer ||= c.bottomContainer;
|
|
6447
6621
|
}
|
|
6622
|
+
return { topContainer, bottomContainer };
|
|
6448
6623
|
}
|
|
6449
|
-
|
|
6450
|
-
|
|
6451
|
-
|
|
6452
|
-
|
|
6453
|
-
|
|
6454
|
-
|
|
6624
|
+
});
|
|
6625
|
+
const panelPlugin = /*@__PURE__*/Wordgard.Plugin.fromClass(class {
|
|
6626
|
+
input;
|
|
6627
|
+
specs;
|
|
6628
|
+
panels;
|
|
6629
|
+
top;
|
|
6630
|
+
bottom;
|
|
6631
|
+
constructor(wg) {
|
|
6632
|
+
this.input = wg.state.facet(Panel.show);
|
|
6633
|
+
this.specs = this.input.filter(s => s);
|
|
6634
|
+
this.panels = this.specs.map(spec => spec(wg));
|
|
6635
|
+
for (let p of this.panels)
|
|
6636
|
+
p.dom.classList.add("wg-panel");
|
|
6637
|
+
let conf = wg.state.facet(panelConfig);
|
|
6638
|
+
this.top = new PanelGroup(wg, true, conf.topContainer);
|
|
6639
|
+
this.bottom = new PanelGroup(wg, false, conf.bottomContainer);
|
|
6640
|
+
this.top.sync(this.panels.filter(p => p.top), wg);
|
|
6641
|
+
this.bottom.sync(this.panels.filter(p => !p.top), wg);
|
|
6455
6642
|
}
|
|
6456
6643
|
update(update) {
|
|
6457
|
-
|
|
6458
|
-
|
|
6459
|
-
|
|
6460
|
-
|
|
6461
|
-
this.observeIntersection();
|
|
6462
|
-
let shouldMeasure = updated || update.geometryChanged;
|
|
6463
|
-
let newConfig = update.state.facet(tooltipConfig);
|
|
6464
|
-
if (newConfig.position != this.position && !this.madeAbsolute) {
|
|
6465
|
-
this.position = newConfig.position;
|
|
6466
|
-
for (let t of this.manager.tooltipViews)
|
|
6467
|
-
t.dom.style.position = this.position;
|
|
6468
|
-
shouldMeasure = true;
|
|
6644
|
+
let conf = update.state.facet(panelConfig);
|
|
6645
|
+
if (this.top.container != conf.topContainer) {
|
|
6646
|
+
this.top.sync([], update.editor);
|
|
6647
|
+
this.top = new PanelGroup(update.editor, true, conf.topContainer);
|
|
6469
6648
|
}
|
|
6470
|
-
if (
|
|
6471
|
-
|
|
6472
|
-
|
|
6473
|
-
this.parent = newConfig.parent;
|
|
6474
|
-
this.createContainer();
|
|
6475
|
-
for (let t of this.manager.tooltipViews)
|
|
6476
|
-
this.container.appendChild(t.dom);
|
|
6477
|
-
shouldMeasure = true;
|
|
6649
|
+
if (this.bottom.container != conf.bottomContainer) {
|
|
6650
|
+
this.bottom.sync([], update.editor);
|
|
6651
|
+
this.bottom = new PanelGroup(update.editor, false, conf.bottomContainer);
|
|
6478
6652
|
}
|
|
6479
|
-
|
|
6480
|
-
|
|
6653
|
+
this.top.syncClasses();
|
|
6654
|
+
this.bottom.syncClasses();
|
|
6655
|
+
let input = update.state.facet(Panel.show);
|
|
6656
|
+
if (input != this.input) {
|
|
6657
|
+
let specs = input.filter(x => x);
|
|
6658
|
+
let panels = [], top = [], bottom = [], mount = [];
|
|
6659
|
+
for (let spec of specs) {
|
|
6660
|
+
let known = this.specs.indexOf(spec), panel;
|
|
6661
|
+
if (known < 0) {
|
|
6662
|
+
panel = spec(update.editor);
|
|
6663
|
+
mount.push(panel);
|
|
6664
|
+
}
|
|
6665
|
+
else {
|
|
6666
|
+
panel = this.panels[known];
|
|
6667
|
+
if (panel.update)
|
|
6668
|
+
panel.update(update);
|
|
6669
|
+
}
|
|
6670
|
+
panels.push(panel);
|
|
6671
|
+
(panel.top ? top : bottom).push(panel);
|
|
6672
|
+
}
|
|
6673
|
+
this.specs = specs;
|
|
6674
|
+
this.panels = panels;
|
|
6675
|
+
this.top.sync(top, update.editor);
|
|
6676
|
+
this.bottom.sync(bottom, update.editor);
|
|
6677
|
+
for (let p of mount) {
|
|
6678
|
+
p.dom.classList.add("wg-panel");
|
|
6679
|
+
if (p.connect && update.editor.connected)
|
|
6680
|
+
p.connect(update.editor);
|
|
6681
|
+
}
|
|
6481
6682
|
}
|
|
6482
|
-
|
|
6483
|
-
this.
|
|
6484
|
-
|
|
6485
|
-
|
|
6486
|
-
let tooltipView = tooltip.create(this.wg);
|
|
6487
|
-
let before = prev ? prev.dom : null;
|
|
6488
|
-
tooltipView.dom.classList.add("wg-tooltip");
|
|
6489
|
-
if (tooltip.arrow && !tooltipView.dom.querySelector(".wg-tooltip > wg-tooltip-arrow")) {
|
|
6490
|
-
let arrow = document.createElement("wg-tooltip-arrow");
|
|
6491
|
-
tooltipView.dom.appendChild(arrow);
|
|
6683
|
+
else {
|
|
6684
|
+
for (let p of this.panels)
|
|
6685
|
+
if (p.update)
|
|
6686
|
+
p.update(update);
|
|
6492
6687
|
}
|
|
6493
|
-
tooltipView.dom.style.position = this.position;
|
|
6494
|
-
tooltipView.dom.style.top = Outside;
|
|
6495
|
-
tooltipView.dom.style.left = "0px";
|
|
6496
|
-
this.container.insertBefore(tooltipView.dom, before);
|
|
6497
|
-
if (this.wg.connected)
|
|
6498
|
-
tooltipView.connect?.(this.wg);
|
|
6499
|
-
if (this.resizeObserver && this.wg.connected)
|
|
6500
|
-
this.resizeObserver.observe(tooltipView.dom);
|
|
6501
|
-
return tooltipView;
|
|
6502
6688
|
}
|
|
6503
6689
|
connect(wg) {
|
|
6504
|
-
|
|
6505
|
-
|
|
6506
|
-
t.connect?.(wg);
|
|
6507
|
-
if (this.resizeObserver)
|
|
6508
|
-
this.resizeObserver.observe(t.dom);
|
|
6509
|
-
}
|
|
6510
|
-
this.observeIntersection();
|
|
6690
|
+
for (let p of this.panels)
|
|
6691
|
+
p.connect?.(wg);
|
|
6511
6692
|
}
|
|
6512
6693
|
disconnect(wg) {
|
|
6513
|
-
|
|
6514
|
-
|
|
6515
|
-
t.disconnect?.(wg);
|
|
6516
|
-
if (this.resizeObserver)
|
|
6517
|
-
this.resizeObserver.unobserve(t.dom);
|
|
6518
|
-
}
|
|
6519
|
-
if (this.intersectionObserver)
|
|
6520
|
-
this.intersectionObserver.disconnect();
|
|
6521
|
-
}
|
|
6522
|
-
remove() {
|
|
6523
|
-
for (let tooltipView of this.manager.tooltipViews) {
|
|
6524
|
-
tooltipView.dom.remove();
|
|
6525
|
-
if (this.wg.connected)
|
|
6526
|
-
tooltipView.disconnect?.(this.wg);
|
|
6527
|
-
tooltipView.remove?.(this.wg);
|
|
6528
|
-
}
|
|
6529
|
-
if (this.parent)
|
|
6530
|
-
this.container.remove();
|
|
6531
|
-
clearTimeout(this.measureTimeout);
|
|
6694
|
+
for (let p of this.panels)
|
|
6695
|
+
p.disconnect?.(wg);
|
|
6532
6696
|
}
|
|
6533
|
-
|
|
6534
|
-
|
|
6535
|
-
this.
|
|
6697
|
+
remove(wg) {
|
|
6698
|
+
this.top.sync([], wg);
|
|
6699
|
+
this.bottom.sync([], wg);
|
|
6536
6700
|
}
|
|
6537
|
-
|
|
6538
|
-
|
|
6539
|
-
|
|
6540
|
-
|
|
6541
|
-
|
|
6542
|
-
|
|
6543
|
-
|
|
6544
|
-
|
|
6545
|
-
|
|
6546
|
-
|
|
6701
|
+
}, plugin => Wordgard.coveredMargins.of(wg => {
|
|
6702
|
+
let value = wg.plugin(plugin);
|
|
6703
|
+
return value && { top: value.top.scrollMargin(), bottom: value.bottom.scrollMargin() };
|
|
6704
|
+
}));
|
|
6705
|
+
const Panel = /*@__PURE__*/(function (Panel) {
|
|
6706
|
+
Panel.show = GardState.Facet.define({
|
|
6707
|
+
enables: panelPlugin
|
|
6708
|
+
});
|
|
6709
|
+
function get(wg, constructor) {
|
|
6710
|
+
let plugin = wg.plugin(panelPlugin);
|
|
6711
|
+
let index = plugin ? plugin.specs.indexOf(constructor) : -1;
|
|
6712
|
+
return index > -1 ? plugin.panels[index] : null;
|
|
6713
|
+
}
|
|
6714
|
+
Panel.get = get;
|
|
6715
|
+
function configure(config) {
|
|
6716
|
+
return config ? [panelConfig.of(config)] : [];
|
|
6717
|
+
}
|
|
6718
|
+
Panel.configure = configure;
|
|
6719
|
+
;return Panel})({});
|
|
6720
|
+
class PanelGroup {
|
|
6721
|
+
wg;
|
|
6722
|
+
top;
|
|
6723
|
+
container;
|
|
6724
|
+
dom = undefined;
|
|
6725
|
+
classes = "";
|
|
6726
|
+
panels = [];
|
|
6727
|
+
constructor(wg, top, container) {
|
|
6728
|
+
this.wg = wg;
|
|
6729
|
+
this.top = top;
|
|
6730
|
+
this.container = container;
|
|
6731
|
+
this.syncClasses();
|
|
6732
|
+
}
|
|
6733
|
+
sync(panels, wg) {
|
|
6734
|
+
for (let p of this.panels)
|
|
6735
|
+
if (!panels.includes(p)) {
|
|
6736
|
+
if (wg.connected)
|
|
6737
|
+
p.disconnect?.(wg);
|
|
6738
|
+
p.remove?.(wg);
|
|
6547
6739
|
}
|
|
6548
|
-
|
|
6549
|
-
|
|
6550
|
-
|
|
6551
|
-
|
|
6552
|
-
|
|
6553
|
-
|
|
6740
|
+
this.panels = panels;
|
|
6741
|
+
this.syncDOM();
|
|
6742
|
+
}
|
|
6743
|
+
syncDOM() {
|
|
6744
|
+
if (this.panels.length == 0) {
|
|
6745
|
+
if (this.dom) {
|
|
6746
|
+
this.dom.remove();
|
|
6747
|
+
this.dom = undefined;
|
|
6554
6748
|
}
|
|
6749
|
+
return;
|
|
6555
6750
|
}
|
|
6556
|
-
|
|
6557
|
-
|
|
6558
|
-
|
|
6559
|
-
|
|
6560
|
-
parent
|
|
6561
|
-
pos: this.manager.tooltips.map((t, i) => {
|
|
6562
|
-
let tv = this.manager.tooltipViews[i];
|
|
6563
|
-
return tv.getCoords ? tv.getCoords(t.pos) : this.wg.coordsAtPos(t.pos);
|
|
6564
|
-
}),
|
|
6565
|
-
size: this.manager.tooltipViews.map(({ dom }) => dom.getBoundingClientRect()),
|
|
6566
|
-
space: this.wg.state.facet(tooltipConfig).tooltipSpace(this.wg),
|
|
6567
|
-
scaleX, scaleY, makeAbsolute
|
|
6568
|
-
};
|
|
6569
|
-
}
|
|
6570
|
-
writeMeasure(measured) {
|
|
6571
|
-
if (measured.makeAbsolute) {
|
|
6572
|
-
this.madeAbsolute = true;
|
|
6573
|
-
this.position = "absolute";
|
|
6574
|
-
for (let t of this.manager.tooltipViews)
|
|
6575
|
-
t.dom.style.position = "absolute";
|
|
6751
|
+
if (!this.dom) {
|
|
6752
|
+
this.dom = document.createElement("wg-panels");
|
|
6753
|
+
this.dom.className = this.top ? "wg-panels-top" : "wg-panels-bottom";
|
|
6754
|
+
let parent = this.container || this.wg.dom;
|
|
6755
|
+
parent.insertBefore(this.dom, this.top ? parent.firstChild : null);
|
|
6576
6756
|
}
|
|
6577
|
-
let
|
|
6578
|
-
let
|
|
6579
|
-
|
|
6580
|
-
|
|
6581
|
-
|
|
6582
|
-
|
|
6583
|
-
pos.top >= Math.min(visible.bottom, space.bottom) ||
|
|
6584
|
-
pos.right < Math.max(visible.left, space.left) - .1 ||
|
|
6585
|
-
pos.left > Math.min(visible.right, space.right) + .1)) {
|
|
6586
|
-
dom.style.top = Outside;
|
|
6587
|
-
continue;
|
|
6588
|
-
}
|
|
6589
|
-
let arrow = tooltip.arrow ? tView.dom.querySelector("wg-tooltip-arrow") : null;
|
|
6590
|
-
let arrowHeight = arrow ? 7 : 0;
|
|
6591
|
-
let width = size.right - size.left, height = knownHeight.get(tView) ?? size.bottom - size.top;
|
|
6592
|
-
let offset = tView.offset || noOffset, ltr = this.wg.state.textLTR;
|
|
6593
|
-
let left = size.width > space.right - space.left
|
|
6594
|
-
? (ltr ? space.left : space.right - size.width)
|
|
6595
|
-
: ltr ? Math.max(space.left, Math.min(pos.left - (arrow ? 14 : 0) + offset.x, space.right - width))
|
|
6596
|
-
: Math.min(Math.max(space.left, pos.left - width + (arrow ? 14 : 0) - offset.x), space.right - width);
|
|
6597
|
-
let above = this.above[i];
|
|
6598
|
-
if (!tooltip.strictSide && (above
|
|
6599
|
-
? pos.top - height - arrowHeight - offset.y < space.top
|
|
6600
|
-
: pos.bottom + height + arrowHeight + offset.y > space.bottom) &&
|
|
6601
|
-
above == (space.bottom - pos.bottom > pos.top - space.top))
|
|
6602
|
-
above = this.above[i] = !above;
|
|
6603
|
-
let spaceVert = (above ? pos.top - space.top : space.bottom - pos.bottom) - arrowHeight;
|
|
6604
|
-
if (spaceVert < height && tView.resize !== false) {
|
|
6605
|
-
if (spaceVert < 15) {
|
|
6606
|
-
dom.style.top = Outside;
|
|
6607
|
-
continue;
|
|
6608
|
-
}
|
|
6609
|
-
knownHeight.set(tView, height);
|
|
6610
|
-
dom.style.height = (height = spaceVert) / scaleY + "px";
|
|
6611
|
-
}
|
|
6612
|
-
else if (dom.style.height) {
|
|
6613
|
-
dom.style.height = "";
|
|
6614
|
-
}
|
|
6615
|
-
let top = above ? pos.top - height - arrowHeight - offset.y : pos.bottom + arrowHeight + offset.y;
|
|
6616
|
-
let right = left + width;
|
|
6617
|
-
if (tView.overlap !== true)
|
|
6618
|
-
for (let r of others)
|
|
6619
|
-
if (r.left < right && r.right > left && r.top < top + height && r.bottom > top)
|
|
6620
|
-
top = above ? r.top - height - 2 - arrowHeight : r.bottom + arrowHeight + 2;
|
|
6621
|
-
if (this.position == "absolute") {
|
|
6622
|
-
dom.style.top = (top - measured.parent.top) / scaleY + "px";
|
|
6623
|
-
setLeftStyle(dom, (left - measured.parent.left) / scaleX);
|
|
6757
|
+
let curDOM = this.dom.firstChild;
|
|
6758
|
+
for (let panel of this.panels) {
|
|
6759
|
+
if (panel.dom.parentNode == this.dom) {
|
|
6760
|
+
while (curDOM != panel.dom)
|
|
6761
|
+
curDOM = rmDOM(curDOM);
|
|
6762
|
+
curDOM = curDOM.nextSibling;
|
|
6624
6763
|
}
|
|
6625
6764
|
else {
|
|
6626
|
-
dom.
|
|
6627
|
-
setLeftStyle(dom, left / scaleX);
|
|
6628
|
-
}
|
|
6629
|
-
if (arrow) {
|
|
6630
|
-
let arrowLeft = pos.left + (ltr ? offset.x : -offset.x) - (left + 14 - 7);
|
|
6631
|
-
arrow.style.left = arrowLeft / scaleX + "px";
|
|
6765
|
+
this.dom.insertBefore(panel.dom, curDOM);
|
|
6632
6766
|
}
|
|
6633
|
-
if (tView.overlap !== true)
|
|
6634
|
-
others.push({ left, top, right, bottom: top + height });
|
|
6635
|
-
dom.classList.toggle("wg-tooltip-above", above);
|
|
6636
|
-
dom.classList.toggle("wg-tooltip-below", !above);
|
|
6637
|
-
if (tView.positioned)
|
|
6638
|
-
tView.positioned(measured.space);
|
|
6639
6767
|
}
|
|
6768
|
+
while (curDOM)
|
|
6769
|
+
curDOM = rmDOM(curDOM);
|
|
6640
6770
|
}
|
|
6641
|
-
|
|
6642
|
-
|
|
6643
|
-
|
|
6771
|
+
scrollMargin() {
|
|
6772
|
+
return !this.dom || this.container ? 0
|
|
6773
|
+
: Math.max(0, this.top ?
|
|
6774
|
+
this.dom.getBoundingClientRect().bottom - Math.max(0, this.wg.scrollDOM.getBoundingClientRect().top) :
|
|
6775
|
+
Math.min(innerHeight, this.wg.scrollDOM.getBoundingClientRect().bottom) - this.dom.getBoundingClientRect().top);
|
|
6776
|
+
}
|
|
6777
|
+
syncClasses() {
|
|
6778
|
+
if (!this.container || this.classes == this.wg.themeClasses)
|
|
6779
|
+
return;
|
|
6780
|
+
for (let cls of this.classes.split(" "))
|
|
6781
|
+
if (cls)
|
|
6782
|
+
this.container.classList.remove(cls);
|
|
6783
|
+
for (let cls of (this.classes = this.wg.themeClasses).split(" "))
|
|
6784
|
+
if (cls)
|
|
6785
|
+
this.container.classList.add(cls);
|
|
6644
6786
|
}
|
|
6645
|
-
}, plugin => plugin.eventObserver("scroll", (event, wg, value) => value.maybeMeasure()));
|
|
6646
|
-
function setLeftStyle(elt, value) {
|
|
6647
|
-
let current = parseInt(elt.style.left, 10);
|
|
6648
|
-
if (isNaN(current) || Math.abs(value - current) > 1)
|
|
6649
|
-
elt.style.left = value + "px";
|
|
6650
6787
|
}
|
|
6651
|
-
|
|
6652
|
-
|
|
6653
|
-
|
|
6654
|
-
|
|
6655
|
-
|
|
6656
|
-
|
|
6657
|
-
|
|
6658
|
-
|
|
6659
|
-
|
|
6660
|
-
|
|
6661
|
-
|
|
6662
|
-
|
|
6663
|
-
|
|
6664
|
-
|
|
6665
|
-
|
|
6666
|
-
|
|
6667
|
-
|
|
6668
|
-
|
|
6669
|
-
|
|
6670
|
-
|
|
6671
|
-
|
|
6672
|
-
|
|
6673
|
-
|
|
6674
|
-
|
|
6675
|
-
|
|
6676
|
-
|
|
6677
|
-
|
|
6678
|
-
|
|
6679
|
-
|
|
6680
|
-
|
|
6681
|
-
|
|
6682
|
-
|
|
6683
|
-
|
|
6684
|
-
|
|
6788
|
+
|
|
6789
|
+
let nextID = 0;
|
|
6790
|
+
function id(prefix) {
|
|
6791
|
+
return prefix + "-" + (nextID++ % 0xffffff).toString(16);
|
|
6792
|
+
}
|
|
6793
|
+
const SVG = "http://www.w3.org/2000/svg";
|
|
6794
|
+
function labelButton(wg, button, label) {
|
|
6795
|
+
button.textContent = "";
|
|
6796
|
+
if (!label) ;
|
|
6797
|
+
else if (typeof label == "function" || typeof label == "string") {
|
|
6798
|
+
let span = button.appendChild(document.createElement("span"));
|
|
6799
|
+
span.className = "wg-button-label";
|
|
6800
|
+
span.textContent = typeof label == "string" ? label : label(wg.state);
|
|
6801
|
+
}
|
|
6802
|
+
else if ("icon" in label) {
|
|
6803
|
+
let svg = button.appendChild(document.createElementNS(SVG, "svg"));
|
|
6804
|
+
svg.classList.add("wg-icon");
|
|
6805
|
+
svg.setAttribute("viewBox", "0 0 100 100");
|
|
6806
|
+
let path = svg.appendChild(document.createElementNS(SVG, "path"));
|
|
6807
|
+
path.setAttribute("d", label.icon);
|
|
6808
|
+
if (label.directional && !wg.state.textLTR)
|
|
6809
|
+
svg.setAttribute("transform", "scale(-1, 1)");
|
|
6810
|
+
}
|
|
6811
|
+
}
|
|
6812
|
+
class BarButton {
|
|
6813
|
+
item;
|
|
6814
|
+
dom;
|
|
6815
|
+
flags = 0;
|
|
6816
|
+
index = 0;
|
|
6817
|
+
constructor(item, wg) {
|
|
6818
|
+
this.item = item;
|
|
6819
|
+
this.dom = document.createElement("button");
|
|
6820
|
+
this.dom.className = "wg-menu-button";
|
|
6821
|
+
this.dom.type = "button";
|
|
6822
|
+
this.dom.tabIndex = -1;
|
|
6823
|
+
labelButton(wg, this.dom, item.label);
|
|
6824
|
+
this.setDesc(wg);
|
|
6825
|
+
}
|
|
6826
|
+
setDesc(wg) {
|
|
6827
|
+
let { item: { label, description } } = this;
|
|
6828
|
+
let someDesc = description || (typeof label == "string" || typeof label == "function" ? label : null);
|
|
6829
|
+
let key = someDesc ? KeyBinding.lookupByDescription(wg.state, someDesc) : null;
|
|
6830
|
+
let desc = typeof someDesc == "function" ? someDesc(wg.state) : someDesc;
|
|
6831
|
+
if (description)
|
|
6832
|
+
this.dom.setAttribute("aria-label", desc);
|
|
6833
|
+
else
|
|
6834
|
+
this.dom.removeAttribute("aria-label");
|
|
6835
|
+
if (key)
|
|
6836
|
+
this.dom.setAttribute("aria-keyshortcuts", key);
|
|
6837
|
+
else
|
|
6838
|
+
this.dom.removeAttribute("aria-keyshortcuts");
|
|
6839
|
+
this.dom.title = desc ? desc + (key ? ` (${key})` : "") : key || "";
|
|
6840
|
+
}
|
|
6841
|
+
get focusDOM() { return this.dom; }
|
|
6842
|
+
update(flags, wg, update) {
|
|
6843
|
+
if (flags != this.flags) {
|
|
6844
|
+
if ((flags & 32) != (this.flags & 32))
|
|
6845
|
+
this.dom.style.display = flags & 32 ? "none" : "";
|
|
6846
|
+
if ((flags & 8) != (this.flags & 8)) {
|
|
6847
|
+
if (flags & 8)
|
|
6848
|
+
this.dom.setAttribute("aria-disabled", "true");
|
|
6849
|
+
else
|
|
6850
|
+
this.dom.removeAttribute("aria-disabled");
|
|
6685
6851
|
}
|
|
6686
|
-
|
|
6687
|
-
|
|
6688
|
-
|
|
6689
|
-
|
|
6690
|
-
|
|
6691
|
-
|
|
6692
|
-
"&:after": {
|
|
6693
|
-
borderBottom: `${7}px solid var(--wg-panel-color)`,
|
|
6694
|
-
top: "1px"
|
|
6852
|
+
if ((flags & 4) != (this.flags & 4)) {
|
|
6853
|
+
if (flags & 4)
|
|
6854
|
+
this.dom.setAttribute("aria-selected", "true");
|
|
6855
|
+
else
|
|
6856
|
+
this.dom.removeAttribute("aria-selected");
|
|
6857
|
+
this.dom.tabIndex = flags & 4 ? 0 : -1;
|
|
6695
6858
|
}
|
|
6696
|
-
|
|
6697
|
-
|
|
6698
|
-
|
|
6699
|
-
|
|
6700
|
-
|
|
6701
|
-
|
|
6702
|
-
|
|
6859
|
+
if ((flags & 16) != (this.flags & 16)) {
|
|
6860
|
+
if (flags & 16)
|
|
6861
|
+
this.dom.setAttribute("aria-pressed", "true");
|
|
6862
|
+
else
|
|
6863
|
+
this.dom.removeAttribute("aria-pressed");
|
|
6864
|
+
}
|
|
6865
|
+
this.flags = flags;
|
|
6866
|
+
}
|
|
6703
6867
|
}
|
|
6704
|
-
|
|
6705
|
-
|
|
6706
|
-
|
|
6707
|
-
|
|
6708
|
-
|
|
6709
|
-
let plugin = wg.plugin(tooltipPlugin);
|
|
6710
|
-
if (!plugin)
|
|
6711
|
-
return null;
|
|
6712
|
-
let found = plugin.manager.tooltips.findIndex(typeof tooltip == "function" ? p => p.create == tooltip : p => p == tooltip);
|
|
6713
|
-
return found < 0 ? null : plugin.manager.tooltipViews[found];
|
|
6868
|
+
get children() { return null; }
|
|
6869
|
+
run(wg) {
|
|
6870
|
+
PositioningHint.runWith(() => this.dom.getBoundingClientRect(), () => {
|
|
6871
|
+
Command.dispatch(wg, this.item.run);
|
|
6872
|
+
});
|
|
6714
6873
|
}
|
|
6715
|
-
|
|
6716
|
-
|
|
6717
|
-
|
|
6718
|
-
|
|
6719
|
-
|
|
6874
|
+
}
|
|
6875
|
+
class BarControl {
|
|
6876
|
+
item;
|
|
6877
|
+
dom;
|
|
6878
|
+
focusDOM;
|
|
6879
|
+
flags = 0;
|
|
6880
|
+
index = 0;
|
|
6881
|
+
constructor(item, wg, done) {
|
|
6882
|
+
this.item = item;
|
|
6883
|
+
let { dom, focus } = item.render(wg, done);
|
|
6884
|
+
this.dom = dom;
|
|
6885
|
+
this.focusDOM = focus || dom;
|
|
6886
|
+
this.focusDOM.tabIndex = -1;
|
|
6720
6887
|
}
|
|
6721
|
-
|
|
6722
|
-
|
|
6723
|
-
|
|
6724
|
-
|
|
6725
|
-
|
|
6726
|
-
|
|
6727
|
-
|
|
6728
|
-
|
|
6729
|
-
|
|
6730
|
-
|
|
6731
|
-
|
|
6732
|
-
|
|
6733
|
-
|
|
6734
|
-
|
|
6735
|
-
|
|
6736
|
-
if (newPos != null) {
|
|
6737
|
-
let copy = Object.assign(Object.create(null), tooltip);
|
|
6738
|
-
copy.pos = newPos;
|
|
6739
|
-
if (copy.end != null)
|
|
6740
|
-
copy.end = tr.changes.mapPos(copy.end);
|
|
6741
|
-
mapped.push(copy);
|
|
6742
|
-
}
|
|
6743
|
-
}
|
|
6744
|
-
value = mapped;
|
|
6745
|
-
}
|
|
6746
|
-
}
|
|
6747
|
-
for (let effect of tr.effects) {
|
|
6748
|
-
if (effect.is(setHover))
|
|
6749
|
-
value = effect.value;
|
|
6750
|
-
if (effect.is(closeHoverTooltipEffect))
|
|
6751
|
-
value = [];
|
|
6752
|
-
}
|
|
6753
|
-
return value;
|
|
6754
|
-
},
|
|
6755
|
-
provide: f => showHoverTooltip.from(f)
|
|
6756
|
-
});
|
|
6757
|
-
return {
|
|
6758
|
-
active: hoverState,
|
|
6759
|
-
extension: [
|
|
6760
|
-
hoverState,
|
|
6761
|
-
Wordgard.Plugin.define(wg => new HoverPlugin(wg, source, hoverState, setHover, options.hoverTime || 300)),
|
|
6762
|
-
showHoverTooltipHost
|
|
6763
|
-
]
|
|
6764
|
-
};
|
|
6888
|
+
update(flags, wg, update) {
|
|
6889
|
+
if (flags != this.flags) {
|
|
6890
|
+
if ((flags & 32) != (this.flags & 32))
|
|
6891
|
+
this.dom.style.display = flags & 32 ? "none" : "";
|
|
6892
|
+
if ((flags & 8) != (this.flags & 8) && this.item.setEnabled)
|
|
6893
|
+
this.item.setEnabled(this.dom, !(flags & 8));
|
|
6894
|
+
if ((flags & 4) != (this.flags & 4)) {
|
|
6895
|
+
if (flags & 4)
|
|
6896
|
+
this.focusDOM.setAttribute("aria-selected", "true");
|
|
6897
|
+
else
|
|
6898
|
+
this.focusDOM.removeAttribute("aria-selected");
|
|
6899
|
+
this.focusDOM.tabIndex = flags & 4 ? 0 : -1;
|
|
6900
|
+
}
|
|
6901
|
+
this.flags = flags;
|
|
6902
|
+
}
|
|
6765
6903
|
}
|
|
6766
|
-
|
|
6767
|
-
|
|
6768
|
-
|
|
6769
|
-
|
|
6904
|
+
get children() { return null; }
|
|
6905
|
+
get run() { return null; }
|
|
6906
|
+
}
|
|
6907
|
+
class BarSubmenu {
|
|
6908
|
+
item;
|
|
6909
|
+
dom;
|
|
6910
|
+
button;
|
|
6911
|
+
list;
|
|
6912
|
+
flags = 0;
|
|
6913
|
+
activeChild = -3;
|
|
6914
|
+
index = 0;
|
|
6915
|
+
children;
|
|
6916
|
+
constructor(item, children, wg) {
|
|
6917
|
+
this.item = item;
|
|
6918
|
+
this.dom = document.createElement("wg-submenu");
|
|
6919
|
+
this.button = this.dom.appendChild(document.createElement("button"));
|
|
6920
|
+
this.button.type = "button";
|
|
6921
|
+
this.button.tabIndex = -1;
|
|
6922
|
+
this.button.className = "wg-menu-button";
|
|
6923
|
+
this.button.setAttribute("aria-haspopup", "true");
|
|
6924
|
+
this.button.setAttribute("aria-expanded", "false");
|
|
6925
|
+
if (item.description) {
|
|
6926
|
+
let desc = typeof item.description == "function" ? item.description(wg.state) : item.description;
|
|
6927
|
+
this.dom.title = desc;
|
|
6928
|
+
this.dom.setAttribute("aria-label", desc);
|
|
6929
|
+
}
|
|
6930
|
+
if (item.label) {
|
|
6931
|
+
labelButton(wg, this.button, item.label);
|
|
6932
|
+
this.activeChild = -2;
|
|
6933
|
+
}
|
|
6934
|
+
if (item.width != null)
|
|
6935
|
+
this.dom.style.setProperty("--wg-submenu-width", item.width + "ch");
|
|
6936
|
+
if (item.arrow)
|
|
6937
|
+
this.button.classList.add("wg-submenu-arrow");
|
|
6938
|
+
this.list = this.dom.appendChild(document.createElement("wg-menu-list"));
|
|
6939
|
+
this.list.style.display = "none";
|
|
6940
|
+
this.list.role = "menu";
|
|
6941
|
+
this.list.id = id("wg-popup");
|
|
6942
|
+
this.list.setAttribute("aria-label", this.button.title);
|
|
6943
|
+
this.button.setAttribute("aria-controls", this.list.id);
|
|
6944
|
+
this.children = children.filter((ch) => !(ch instanceof BarSpacer));
|
|
6945
|
+
for (let child of children) {
|
|
6946
|
+
this.list.appendChild(child.dom);
|
|
6947
|
+
if (!(child instanceof BarSpacer))
|
|
6948
|
+
child.focusDOM.role = "menuitem";
|
|
6949
|
+
}
|
|
6950
|
+
}
|
|
6951
|
+
get focusDOM() { return this.button; }
|
|
6952
|
+
update(flags, wg) {
|
|
6953
|
+
if (flags != this.flags) {
|
|
6954
|
+
if ((flags & 32) != (this.flags & 32))
|
|
6955
|
+
this.dom.style.display = flags & 32 ? "none" : "";
|
|
6956
|
+
if ((flags & 8) != (this.flags & 8)) {
|
|
6957
|
+
if (flags & 8)
|
|
6958
|
+
this.button.setAttribute("aria-disabled", "true");
|
|
6959
|
+
else
|
|
6960
|
+
this.button.removeAttribute("aria-disabled");
|
|
6961
|
+
}
|
|
6962
|
+
if ((flags & 4) != (this.flags & 4)) {
|
|
6963
|
+
if (flags & 4)
|
|
6964
|
+
this.button.setAttribute("aria-selected", "true");
|
|
6965
|
+
else
|
|
6966
|
+
this.button.removeAttribute("aria-selected");
|
|
6967
|
+
this.button.tabIndex = flags & 4 ? 0 : -1;
|
|
6968
|
+
}
|
|
6969
|
+
if ((flags & 2) != (this.flags & 2))
|
|
6970
|
+
this.list.style.display = flags & 2 ? "" : "none";
|
|
6971
|
+
this.flags = flags;
|
|
6770
6972
|
}
|
|
6771
|
-
|
|
6772
|
-
|
|
6773
|
-
|
|
6774
|
-
|
|
6775
|
-
|
|
6776
|
-
|
|
6777
|
-
|
|
6778
|
-
}
|
|
6779
|
-
|
|
6780
|
-
|
|
6781
|
-
|
|
6973
|
+
if (this.activeChild != -2) {
|
|
6974
|
+
let activeChild = this.children.findIndex(ch => ch.flags & 16);
|
|
6975
|
+
if (this.activeChild != activeChild) {
|
|
6976
|
+
this.activeChild = activeChild;
|
|
6977
|
+
let label = activeChild < 0 ? this.item.defaultLabel : this.children[activeChild].item.label;
|
|
6978
|
+
labelButton(wg, this.button, label);
|
|
6979
|
+
}
|
|
6980
|
+
}
|
|
6981
|
+
}
|
|
6982
|
+
get run() { return null; }
|
|
6983
|
+
}
|
|
6984
|
+
class BarSpacer {
|
|
6782
6985
|
dom;
|
|
6783
|
-
|
|
6784
|
-
|
|
6785
|
-
return new HoverTooltipHost(wg);
|
|
6986
|
+
constructor() {
|
|
6987
|
+
this.dom = document.createElement("wg-menu-spacer");
|
|
6786
6988
|
}
|
|
6989
|
+
}
|
|
6990
|
+
function instantiate(item, bar, flat) {
|
|
6991
|
+
let elt;
|
|
6992
|
+
if (item instanceof Menu.Submenu.Resolved)
|
|
6993
|
+
elt = new BarSubmenu(item.item, item.content.map(i => instantiate(i, bar, flat)), bar.wg);
|
|
6994
|
+
else if (item === "|")
|
|
6995
|
+
return new BarSpacer();
|
|
6996
|
+
else if (item instanceof Menu.Button)
|
|
6997
|
+
elt = new BarButton(item, bar.wg);
|
|
6998
|
+
else
|
|
6999
|
+
elt = new BarControl(item, bar.wg, () => bar.up());
|
|
7000
|
+
elt.index = flat.length;
|
|
7001
|
+
flat.push(elt);
|
|
7002
|
+
return elt;
|
|
7003
|
+
}
|
|
7004
|
+
class MenuBar {
|
|
7005
|
+
wg;
|
|
7006
|
+
dom;
|
|
7007
|
+
focusTimeout = -1;
|
|
7008
|
+
items;
|
|
6787
7009
|
constructor(wg) {
|
|
6788
7010
|
this.wg = wg;
|
|
6789
|
-
this.dom = document.createElement("wg-
|
|
6790
|
-
this.
|
|
6791
|
-
|
|
6792
|
-
|
|
6793
|
-
|
|
6794
|
-
|
|
6795
|
-
this.
|
|
6796
|
-
|
|
6797
|
-
hostedView.connect(this.wg);
|
|
6798
|
-
return hostedView;
|
|
6799
|
-
}
|
|
6800
|
-
connect(wg) {
|
|
6801
|
-
for (let t of this.manager.tooltipViews)
|
|
6802
|
-
t.connect?.(wg);
|
|
6803
|
-
this.connected = true;
|
|
6804
|
-
}
|
|
6805
|
-
disconnect(wg) {
|
|
6806
|
-
for (let t of this.manager.tooltipViews)
|
|
6807
|
-
t.disconnect?.(wg);
|
|
6808
|
-
this.connected = false;
|
|
7011
|
+
this.dom = document.createElement("wg-menubar");
|
|
7012
|
+
this.dom.role = "toolbar";
|
|
7013
|
+
this.dom.addEventListener("keydown", this.key.bind(this));
|
|
7014
|
+
this.dom.addEventListener("mousedown", this.click.bind(this));
|
|
7015
|
+
this.dom.addEventListener("focusout", this.focusout.bind(this));
|
|
7016
|
+
this.items = wg.state.facet(Menu.Item.source);
|
|
7017
|
+
this.init();
|
|
7018
|
+
this.globalClick = this.globalClick.bind(this);
|
|
6809
7019
|
}
|
|
6810
|
-
|
|
6811
|
-
|
|
6812
|
-
|
|
6813
|
-
|
|
6814
|
-
|
|
7020
|
+
static create(wg) { return new MenuBar(wg); }
|
|
7021
|
+
init() {
|
|
7022
|
+
let elts = [];
|
|
7023
|
+
this.elts = elts;
|
|
7024
|
+
let children = Menu.resolve(this.items, this.wg.state.facet(barTemplate)).map(i => instantiate(i, this, elts));
|
|
7025
|
+
this.children = children.filter((ch) => !(ch instanceof BarSpacer));
|
|
7026
|
+
for (let elt of children)
|
|
7027
|
+
this.dom.appendChild(elt.dom);
|
|
7028
|
+
this.selection = this.children.length ? [this.children[0]] : [];
|
|
7029
|
+
this.updateElts(true, this.selection);
|
|
6815
7030
|
}
|
|
6816
7031
|
update(update) {
|
|
6817
|
-
|
|
7032
|
+
let items = update.state.facet(Menu.Item.source);
|
|
7033
|
+
if (items != this.items ||
|
|
7034
|
+
update.startState.facet(barTemplate) != update.state.facet(barTemplate) ||
|
|
7035
|
+
update.startState.textLTR != update.state.textLTR ||
|
|
7036
|
+
PhraseSet.didChange(update.startState, update.state)) {
|
|
7037
|
+
this.items = items;
|
|
7038
|
+
this.dom.textContent = "";
|
|
7039
|
+
this.init();
|
|
7040
|
+
}
|
|
7041
|
+
else {
|
|
7042
|
+
this.updateElts(update, this.selection);
|
|
7043
|
+
if (update.startState.facet(KeyBinding.source) != update.state.facet(KeyBinding.source)) {
|
|
7044
|
+
for (let elt of this.elts)
|
|
7045
|
+
if (elt instanceof BarButton)
|
|
7046
|
+
elt.setDesc(update.editor);
|
|
7047
|
+
}
|
|
7048
|
+
}
|
|
6818
7049
|
}
|
|
6819
|
-
|
|
6820
|
-
|
|
6821
|
-
t.remove?.(wg);
|
|
7050
|
+
connect() {
|
|
7051
|
+
this.dom.setAttribute("aria-controls", this.wg.contentDOM.id);
|
|
6822
7052
|
}
|
|
6823
|
-
|
|
6824
|
-
let
|
|
6825
|
-
|
|
6826
|
-
|
|
6827
|
-
|
|
6828
|
-
|
|
6829
|
-
|
|
6830
|
-
|
|
6831
|
-
|
|
7053
|
+
updateElts(update, selection) {
|
|
7054
|
+
let { state } = this.wg;
|
|
7055
|
+
let changed = typeof update == "boolean" ? update : update.docChanged || update.selectionSet;
|
|
7056
|
+
let updateObj = typeof update == "boolean" ? null : update;
|
|
7057
|
+
for (let i = 0; i < this.elts.length; i++) {
|
|
7058
|
+
let elt = this.elts[i], flags;
|
|
7059
|
+
if (update && (update === true || (elt.item.updateFor ? update.transactions.some(tr => elt.item.updateFor(tr)) : changed))) {
|
|
7060
|
+
flags = ((elt.item.select ? elt.item.select(state) : true) ? 0 : 32) |
|
|
7061
|
+
((elt.item.enable ? elt.item.enable(state) : true) ? 0 : 8) |
|
|
7062
|
+
((elt.item instanceof Menu.Button && elt.item.active ? elt.item.active(state) : false) ? 16 : 0);
|
|
6832
7063
|
}
|
|
7064
|
+
else {
|
|
7065
|
+
flags = elt.flags & (32 | 8 | 16);
|
|
7066
|
+
}
|
|
7067
|
+
if (selection.length) {
|
|
7068
|
+
let selected = selection.indexOf(elt);
|
|
7069
|
+
if (selected == selection.length - 1)
|
|
7070
|
+
flags |= 4;
|
|
7071
|
+
else if (selected > -1)
|
|
7072
|
+
flags |= 2;
|
|
7073
|
+
}
|
|
7074
|
+
elt.update(flags, this.wg, updateObj);
|
|
7075
|
+
}
|
|
7076
|
+
if (update && selection.some(e => e.flags & 32)) {
|
|
7077
|
+
let reset = selection[0].flags & 32 ? findChild(this.children, true) : selection[0];
|
|
7078
|
+
this.setSelection(reset ? [reset] : [], this.dom.contains(this.wg.root.activeElement));
|
|
6833
7079
|
}
|
|
6834
|
-
return value;
|
|
6835
7080
|
}
|
|
6836
|
-
|
|
6837
|
-
|
|
6838
|
-
|
|
6839
|
-
|
|
6840
|
-
|
|
6841
|
-
|
|
6842
|
-
|
|
6843
|
-
if (tooltips.length === 0)
|
|
6844
|
-
return null;
|
|
6845
|
-
return {
|
|
6846
|
-
pos: Math.min(...tooltips.map(t => t.pos)),
|
|
6847
|
-
end: Math.max(...tooltips.map(t => t.end ?? t.pos)),
|
|
6848
|
-
create: HoverTooltipHost.create,
|
|
6849
|
-
above: tooltips[0].above,
|
|
6850
|
-
arrow: tooltips.some(t => t.arrow),
|
|
6851
|
-
};
|
|
6852
|
-
});
|
|
6853
|
-
class HoverPlugin {
|
|
6854
|
-
wg;
|
|
6855
|
-
source;
|
|
6856
|
-
field;
|
|
6857
|
-
setHover;
|
|
6858
|
-
hoverTime;
|
|
6859
|
-
lastMove;
|
|
6860
|
-
hoverTimeout = -1;
|
|
6861
|
-
restartTimeout = -1;
|
|
6862
|
-
pending = null;
|
|
6863
|
-
constructor(wg, source, field, setHover, hoverTime) {
|
|
6864
|
-
this.wg = wg;
|
|
6865
|
-
this.source = source;
|
|
6866
|
-
this.field = field;
|
|
6867
|
-
this.setHover = setHover;
|
|
6868
|
-
this.hoverTime = hoverTime;
|
|
6869
|
-
this.lastMove = { x: 0, y: 0, target: wg.dom, time: 0 };
|
|
6870
|
-
this.checkHover = this.checkHover.bind(this);
|
|
6871
|
-
wg.dom.addEventListener("mouseleave", this.mouseleave = this.mouseleave.bind(this));
|
|
6872
|
-
wg.dom.addEventListener("mousemove", this.mousemove = this.mousemove.bind(this));
|
|
7081
|
+
setSelection(selection, focus = true) {
|
|
7082
|
+
this.updateElts(false, selection);
|
|
7083
|
+
if (selection.length > 1 && this.selection.length <= 1)
|
|
7084
|
+
this.dom.ownerDocument.addEventListener("mousedown", this.globalClick);
|
|
7085
|
+
this.selection = selection;
|
|
7086
|
+
if (focus && selection.length)
|
|
7087
|
+
selection[selection.length - 1].focusDOM.focus();
|
|
6873
7088
|
}
|
|
6874
|
-
|
|
6875
|
-
if (
|
|
6876
|
-
|
|
6877
|
-
|
|
6878
|
-
|
|
7089
|
+
key(event) {
|
|
7090
|
+
if (event.ctrlKey || event.altKey || event.metaKey || event.defaultPrevented)
|
|
7091
|
+
return;
|
|
7092
|
+
let sLen = this.selection.length;
|
|
7093
|
+
if (event.key == "ArrowLeft" || event.key == "ArrowRight") {
|
|
7094
|
+
if (sLen) {
|
|
7095
|
+
let forward = (event.key == "ArrowRight") == (getComputedStyle(this.dom).direction == "ltr");
|
|
7096
|
+
let next = findNextChild(this.children, this.selection[0], forward ? 1 : -1);
|
|
7097
|
+
this.setSelection(next ? [next] : []);
|
|
7098
|
+
}
|
|
7099
|
+
}
|
|
7100
|
+
else if (event.key == "ArrowDown" || event.key == "ArrowUp") {
|
|
7101
|
+
if (sLen > 1) {
|
|
7102
|
+
let parent = this.selection[sLen - 2];
|
|
7103
|
+
let next = findNextChild(parent.children, this.selection[sLen - 1], event.key == "ArrowUp" ? -1 : 1);
|
|
7104
|
+
if (next)
|
|
7105
|
+
this.setSelection(this.selection.slice(0, sLen - 1).concat(next));
|
|
7106
|
+
}
|
|
7107
|
+
else if (sLen == 1 && this.selection[0].children) {
|
|
7108
|
+
let inner = defaultChild(this.selection[0].children);
|
|
7109
|
+
if (inner)
|
|
7110
|
+
this.setSelection([this.selection[0], inner]);
|
|
7111
|
+
}
|
|
7112
|
+
}
|
|
7113
|
+
else if (event.key == "Home" || event.key == "End") {
|
|
7114
|
+
let child = findChild(sLen > 1 ? this.selection[sLen - 2].children : this.children, event.key == "Home");
|
|
7115
|
+
if (child)
|
|
7116
|
+
this.setSelection(this.selection.slice(0, sLen - 1).concat(child));
|
|
7117
|
+
}
|
|
7118
|
+
else if (event.key == " " || event.key == "Enter") {
|
|
7119
|
+
if (sLen) {
|
|
7120
|
+
let child = this.selection[sLen - 1];
|
|
7121
|
+
if (child.flags & 8) ;
|
|
7122
|
+
else if (child.children) {
|
|
7123
|
+
let inner = defaultChild(child.children);
|
|
7124
|
+
if (inner)
|
|
7125
|
+
this.setSelection(this.selection.concat(inner));
|
|
7126
|
+
}
|
|
7127
|
+
else {
|
|
7128
|
+
if (child.run)
|
|
7129
|
+
child.run(this.wg);
|
|
7130
|
+
this.setSelection([this.selection[0]]);
|
|
7131
|
+
}
|
|
7132
|
+
}
|
|
7133
|
+
}
|
|
7134
|
+
else if (event.key == "Escape" && sLen > 1) {
|
|
7135
|
+
this.setSelection(this.selection.slice(0, sLen - 1));
|
|
7136
|
+
}
|
|
7137
|
+
else {
|
|
7138
|
+
return;
|
|
6879
7139
|
}
|
|
7140
|
+
event.preventDefault();
|
|
6880
7141
|
}
|
|
6881
|
-
|
|
6882
|
-
|
|
6883
|
-
}
|
|
6884
|
-
checkHover() {
|
|
6885
|
-
this.hoverTimeout = -1;
|
|
6886
|
-
if (this.active.length)
|
|
7142
|
+
click(event) {
|
|
7143
|
+
if (event.defaultPrevented)
|
|
6887
7144
|
return;
|
|
6888
|
-
let
|
|
6889
|
-
|
|
6890
|
-
|
|
6891
|
-
|
|
6892
|
-
this.
|
|
6893
|
-
|
|
6894
|
-
|
|
6895
|
-
|
|
6896
|
-
|
|
6897
|
-
|
|
6898
|
-
|
|
6899
|
-
|
|
6900
|
-
|
|
6901
|
-
|
|
6902
|
-
|
|
6903
|
-
this.
|
|
6904
|
-
if (
|
|
6905
|
-
|
|
7145
|
+
let target, idx;
|
|
7146
|
+
for (let node = event.target;; node = node.parentNode) {
|
|
7147
|
+
if (!node || node == this.dom)
|
|
7148
|
+
return;
|
|
7149
|
+
target = this.elts.find(e => e.dom == node);
|
|
7150
|
+
if (target)
|
|
7151
|
+
break;
|
|
7152
|
+
}
|
|
7153
|
+
if (target.flags & 8) ;
|
|
7154
|
+
else if (target.children) {
|
|
7155
|
+
if ((idx = this.selection.indexOf(target)) > -1 && idx < this.selection.length - 1) {
|
|
7156
|
+
this.setSelection(this.selection.slice(0, idx + 1), false);
|
|
7157
|
+
}
|
|
7158
|
+
else {
|
|
7159
|
+
for (let i = 0; i < this.selection.length; i++) {
|
|
7160
|
+
let { children } = i ? this.selection[i - 1] : this;
|
|
7161
|
+
if (children.includes(target)) {
|
|
7162
|
+
let next = defaultChild(target.children);
|
|
7163
|
+
if (next)
|
|
7164
|
+
this.setSelection(this.selection.slice(0, i).concat([target, next]), false);
|
|
7165
|
+
}
|
|
6906
7166
|
}
|
|
6907
|
-
}
|
|
7167
|
+
}
|
|
6908
7168
|
}
|
|
6909
|
-
else
|
|
6910
|
-
|
|
7169
|
+
else {
|
|
7170
|
+
if (target.run)
|
|
7171
|
+
target.run(this.wg);
|
|
7172
|
+
this.setSelection(this.children.includes(target) ? [target] : this.selection.length ? [this.selection[0]] : [], false);
|
|
6911
7173
|
}
|
|
7174
|
+
event.preventDefault();
|
|
6912
7175
|
}
|
|
6913
|
-
|
|
6914
|
-
|
|
6915
|
-
|
|
6916
|
-
|
|
6917
|
-
|
|
6918
|
-
mousemove(event) {
|
|
6919
|
-
this.lastMove = { x: event.clientX, y: event.clientY, target: event.target, time: Date.now() };
|
|
6920
|
-
if (this.hoverTimeout < 0)
|
|
6921
|
-
this.hoverTimeout = setTimeout(this.checkHover, this.hoverTime);
|
|
6922
|
-
let { active, tooltip } = this;
|
|
6923
|
-
if (active.length && tooltip && !isInTooltip(tooltip.dom, event) || this.pending) {
|
|
6924
|
-
let { pos } = active[0] || this.pending, end = active[0]?.end ?? pos;
|
|
6925
|
-
if ((pos == end ? this.wg.posAtCoords(this.lastMove).pos != pos
|
|
6926
|
-
: !isOverRange(this.wg, pos, end, event.clientX, event.clientY))) {
|
|
6927
|
-
this.wg.dispatch({ effects: this.setHover.of([]) });
|
|
6928
|
-
this.pending = null;
|
|
6929
|
-
}
|
|
7176
|
+
globalClick(event) {
|
|
7177
|
+
if (!event.composedPath().includes(this.dom)) {
|
|
7178
|
+
this.dom.ownerDocument.removeEventListener("mousedown", this.globalClick);
|
|
7179
|
+
if (this.selection.length > 1)
|
|
7180
|
+
this.setSelection([this.selection[0]], false);
|
|
6930
7181
|
}
|
|
6931
7182
|
}
|
|
6932
|
-
|
|
6933
|
-
clearTimeout(this.
|
|
6934
|
-
this.
|
|
6935
|
-
|
|
6936
|
-
|
|
6937
|
-
|
|
6938
|
-
|
|
6939
|
-
|
|
6940
|
-
|
|
6941
|
-
|
|
6942
|
-
|
|
7183
|
+
focusout() {
|
|
7184
|
+
clearTimeout(this.focusTimeout);
|
|
7185
|
+
if (this.selection.length > 1) {
|
|
7186
|
+
this.focusTimeout = setTimeout(() => {
|
|
7187
|
+
let active = this.wg.root.activeElement;
|
|
7188
|
+
for (let i = 0; i < this.selection.length - 1; i++) {
|
|
7189
|
+
if (!active || !this.selection[i].dom.contains(active)) {
|
|
7190
|
+
this.setSelection([this.selection[0]], false);
|
|
7191
|
+
break;
|
|
7192
|
+
}
|
|
7193
|
+
}
|
|
7194
|
+
}, 20);
|
|
6943
7195
|
}
|
|
6944
7196
|
}
|
|
6945
|
-
|
|
6946
|
-
|
|
6947
|
-
|
|
6948
|
-
if (this.active.length && !this.wg.dom.contains(event.relatedTarget))
|
|
6949
|
-
this.wg.dispatch({ effects: this.setHover.of([]) });
|
|
6950
|
-
};
|
|
6951
|
-
tooltip.addEventListener("mouseleave", watch);
|
|
7197
|
+
up() {
|
|
7198
|
+
if (this.selection.length > 1)
|
|
7199
|
+
this.setSelection([this.selection[0]], false);
|
|
6952
7200
|
}
|
|
6953
|
-
|
|
6954
|
-
|
|
6955
|
-
|
|
6956
|
-
|
|
7201
|
+
get top() { return true; }
|
|
7202
|
+
}
|
|
7203
|
+
const menuBarPanel = /*@__PURE__*/(() => Panel.show.of(MenuBar.create))();
|
|
7204
|
+
function findChild(children, start) {
|
|
7205
|
+
for (let i = start ? 0 : children.length - 1; start ? i < children.length : i >= 0; start ? i++ : i--) {
|
|
7206
|
+
let child = children[i];
|
|
7207
|
+
if (!(child.flags & 8))
|
|
7208
|
+
return child;
|
|
6957
7209
|
}
|
|
7210
|
+
return null;
|
|
6958
7211
|
}
|
|
6959
|
-
|
|
6960
|
-
|
|
6961
|
-
|
|
6962
|
-
|
|
6963
|
-
|
|
6964
|
-
|
|
6965
|
-
|
|
7212
|
+
function findNextChild(children, child, dir) {
|
|
7213
|
+
let index = children.indexOf(child);
|
|
7214
|
+
if (index < 0)
|
|
7215
|
+
return null;
|
|
7216
|
+
for (let i = index + dir;; i += dir) {
|
|
7217
|
+
if (i < 0)
|
|
7218
|
+
i = children.length - 1;
|
|
7219
|
+
else if (i >= children.length)
|
|
7220
|
+
i = 0;
|
|
7221
|
+
if (i == index)
|
|
7222
|
+
return null;
|
|
7223
|
+
let child = children[i];
|
|
7224
|
+
if (!(child.flags & 32))
|
|
7225
|
+
return child;
|
|
6966
7226
|
}
|
|
6967
|
-
return event.clientX >= left - tooltipMargin && event.clientX <= right + tooltipMargin &&
|
|
6968
|
-
event.clientY >= top - tooltipMargin && event.clientY <= bottom + tooltipMargin;
|
|
6969
7227
|
}
|
|
6970
|
-
function
|
|
6971
|
-
|
|
6972
|
-
|
|
6973
|
-
|
|
6974
|
-
|
|
6975
|
-
|
|
7228
|
+
function defaultChild(children) {
|
|
7229
|
+
return children.length ? children.find(ch => ch.flags & 16) || children[0] : null;
|
|
7230
|
+
}
|
|
7231
|
+
const theme = /*@__PURE__*/Wordgard.styles({
|
|
7232
|
+
"&": {
|
|
7233
|
+
"--wg-menu-item-size": "20px"
|
|
7234
|
+
},
|
|
7235
|
+
"&light": {
|
|
7236
|
+
"--wg-menu-color": "#555"
|
|
7237
|
+
},
|
|
7238
|
+
"&dark": {
|
|
7239
|
+
"--wg-menu-color": "#ccc"
|
|
7240
|
+
},
|
|
7241
|
+
"wg-menubar": {
|
|
7242
|
+
display: "flex",
|
|
7243
|
+
flexWrap: "wrap",
|
|
7244
|
+
gap: "5px",
|
|
7245
|
+
padding: "3px",
|
|
7246
|
+
color: "var(--wg-menu-color)",
|
|
7247
|
+
borderBottom: "1px solid var(--wg-border-color)",
|
|
7248
|
+
},
|
|
7249
|
+
".wg-menu-button:focus": {
|
|
7250
|
+
outline: "1.5px solid var(--wg-highlight-color)"
|
|
7251
|
+
},
|
|
7252
|
+
".wg-menu-button": {
|
|
7253
|
+
border: 0,
|
|
7254
|
+
padding: "3px",
|
|
7255
|
+
borderRadius: "4px",
|
|
7256
|
+
boxSizing: "content-box",
|
|
7257
|
+
backgroundColor: "transparent",
|
|
7258
|
+
font: "inherit",
|
|
7259
|
+
color: "inherit",
|
|
7260
|
+
height: "var(--wg-menu-item-size)",
|
|
7261
|
+
textAlign: "left",
|
|
7262
|
+
"&[aria-disabled]": {
|
|
7263
|
+
opacity: "0.3"
|
|
7264
|
+
},
|
|
7265
|
+
"&[aria-pressed]": {
|
|
7266
|
+
color: "var(--wg-highlight-color)"
|
|
7267
|
+
},
|
|
7268
|
+
"&:hover": {
|
|
7269
|
+
backgroundColor: "#88888820",
|
|
7270
|
+
},
|
|
7271
|
+
},
|
|
7272
|
+
".wg-button-label": {
|
|
7273
|
+
display: "inline-block",
|
|
7274
|
+
minWidth: "var(--wg-submenu-width)",
|
|
7275
|
+
padding: "0 3px",
|
|
7276
|
+
},
|
|
7277
|
+
"svg.wg-icon": {
|
|
7278
|
+
fill: "currentColor",
|
|
7279
|
+
width: "var(--wg-menu-item-size)",
|
|
7280
|
+
height: "var(--wg-menu-item-size)",
|
|
7281
|
+
},
|
|
7282
|
+
"wg-menu-spacer": {
|
|
7283
|
+
display: "block",
|
|
7284
|
+
width: "7px"
|
|
7285
|
+
},
|
|
7286
|
+
"wg-submenu": {
|
|
7287
|
+
display: "block",
|
|
7288
|
+
position: "relative",
|
|
7289
|
+
lineHeight: ".6",
|
|
7290
|
+
whiteSpace: "nowrap"
|
|
7291
|
+
},
|
|
7292
|
+
"wg-menu-list": {
|
|
7293
|
+
display: "flex",
|
|
7294
|
+
flexDirection: "column",
|
|
7295
|
+
alignItems: "stretch",
|
|
7296
|
+
gap: "5px",
|
|
7297
|
+
padding: "5px",
|
|
7298
|
+
borderRadius: "4px",
|
|
7299
|
+
backgroundColor: "var(--wg-panel-color)",
|
|
7300
|
+
position: "absolute",
|
|
7301
|
+
zIndex: "10",
|
|
7302
|
+
top: "100%",
|
|
7303
|
+
boxShadow: "0 2px 8px 0 rgba(128, 128, 128, 0.2)",
|
|
7304
|
+
"& wg-menu-list": {
|
|
7305
|
+
left: "100%",
|
|
7306
|
+
top: 0
|
|
7307
|
+
}
|
|
7308
|
+
},
|
|
7309
|
+
".wg-submenu-arrow:after": {
|
|
7310
|
+
padding: "0 2px",
|
|
7311
|
+
fontSize: "80%",
|
|
7312
|
+
verticalAlign: "10%",
|
|
7313
|
+
opacity: "0.4",
|
|
7314
|
+
content: "'▾'"
|
|
7315
|
+
},
|
|
7316
|
+
".wg-submenu-arrow.wg-submenu-arrow-open:after": {
|
|
7317
|
+
content: "'▴'"
|
|
7318
|
+
},
|
|
7319
|
+
});
|
|
7320
|
+
const barTemplate = /*@__PURE__*/GardState.Facet.define({
|
|
7321
|
+
combine: inputs => inputs.length ? inputs[0] : [Menu.Group.top.template()]
|
|
7322
|
+
});
|
|
7323
|
+
function menuBar(config = {}) {
|
|
7324
|
+
let extensions = [menuBarPanel, theme];
|
|
7325
|
+
if (config.template)
|
|
7326
|
+
extensions.push(barTemplate.of(Array.isArray(config.template) ? config.template : [config.template]));
|
|
7327
|
+
return extensions;
|
|
6976
7328
|
}
|
|
6977
7329
|
|
|
6978
7330
|
const inputRule = /*@__PURE__*/GardState.Facet.define();
|
|
@@ -7237,4 +7589,4 @@ function dropCursor() {
|
|
|
7237
7589
|
return [dropCursorPos, drawDropCursor];
|
|
7238
7590
|
}
|
|
7239
7591
|
|
|
7240
|
-
export { Decoration, Dialog, InputRule, KeyBinding, Panel, Tooltip, Widget, Wordgard, decoratePlots, dropCursor, menuBar, placeholder };
|
|
7592
|
+
export { Decoration, Dialog, InputRule, KeyBinding, Panel, PositioningHint, Tooltip, Widget, Wordgard, decoratePlots, dropCursor, keyBindingHelp, menuBar, placeholder };
|