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