@nerd-bible/wordgard 0.3.3
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/LICENSE +22 -0
- package/README.md +24 -0
- package/dist/collab.d.ts +105 -0
- package/dist/collab.js +218 -0
- package/dist/command.d.ts +796 -0
- package/dist/command.js +1451 -0
- package/dist/doc.d.ts +2210 -0
- package/dist/doc.js +3814 -0
- package/dist/editor.d.ts +1920 -0
- package/dist/editor.js +7154 -0
- package/dist/history.d.ts +90 -0
- package/dist/history.js +278 -0
- package/dist/index.d.ts +10 -0
- package/dist/index.js +10 -0
- package/dist/phrases.d.ts +90 -0
- package/dist/phrases.js +141 -0
- package/dist/schema.d.ts +579 -0
- package/dist/schema.js +1341 -0
- package/dist/state.d.ts +1388 -0
- package/dist/state.js +2024 -0
- package/dist/table.d.ts +215 -0
- package/dist/table.js +1302 -0
- package/dist/types.d.ts +196 -0
- package/dist/types.js +288 -0
- package/package.json +52 -0
package/dist/editor.d.ts
ADDED
|
@@ -0,0 +1,1920 @@
|
|
|
1
|
+
import * as wordgard_doc from 'wordgard/doc';
|
|
2
|
+
import { Elt, Node as Node$1, ChangeSet, Plot, Pos } from 'wordgard/doc';
|
|
3
|
+
import { GardState, TextblockMap, Transaction, GardSelection } from 'wordgard/state';
|
|
4
|
+
import { PhraseSet } from 'wordgard/phrases';
|
|
5
|
+
import { StyleModule, StyleSpec } from 'style-mod';
|
|
6
|
+
import { Command, Menu } from 'wordgard/command';
|
|
7
|
+
|
|
8
|
+
type MakeSelectionStyle = (wg: Wordgard, event: MouseEvent) => Wordgard.MouseSelectionStyle | null;
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
A widget describes a piece of DOM content that can be used to
|
|
12
|
+
render a node, a part of a node, or an extra element added via a
|
|
13
|
+
decoration. The `Widget` object is separate from its DOM
|
|
14
|
+
representation. It describes how the DOM widget is to be rendered
|
|
15
|
+
and how it behaves, but it itself is an immutable value.
|
|
16
|
+
*/
|
|
17
|
+
declare class Widget<Param = unknown> {
|
|
18
|
+
/**
|
|
19
|
+
The parameter for this widget.
|
|
20
|
+
*/
|
|
21
|
+
readonly value: Param;
|
|
22
|
+
private constructor();
|
|
23
|
+
/**
|
|
24
|
+
Compare this widget to another widget object.
|
|
25
|
+
*/
|
|
26
|
+
eq(other: any): boolean;
|
|
27
|
+
/**
|
|
28
|
+
Define a widget type.
|
|
29
|
+
*/
|
|
30
|
+
static define<Param>(spec: Widget.Spec<Param>): Widget.Type<Param>;
|
|
31
|
+
/**
|
|
32
|
+
Create a singleton widget.
|
|
33
|
+
*/
|
|
34
|
+
static create(spec: Widget.Spec<null>): Widget<null>;
|
|
35
|
+
/**
|
|
36
|
+
This widget's type. The type mangling is a kludge to make sure
|
|
37
|
+
`Widget<Param>` is a subtype of `Widget<unknown>`.
|
|
38
|
+
*/
|
|
39
|
+
readonly type: Widget.Type<unknown extends Param ? any : Param>;
|
|
40
|
+
}
|
|
41
|
+
declare namespace Widget {
|
|
42
|
+
/**
|
|
43
|
+
Specifies a widget type.
|
|
44
|
+
*/
|
|
45
|
+
type Spec<Param> = {
|
|
46
|
+
/**
|
|
47
|
+
How to render the widget as DOM content.
|
|
48
|
+
*/
|
|
49
|
+
render: (value: Param) => Element | Text;
|
|
50
|
+
/**
|
|
51
|
+
Compare the widget value for equality. Will default to `===`.
|
|
52
|
+
*/
|
|
53
|
+
eq?: (a: Param, b: Param) => boolean;
|
|
54
|
+
/**
|
|
55
|
+
Called when a widget of this type is added to an editor that
|
|
56
|
+
is connected to a DOM document, or an editor with the widget
|
|
57
|
+
in it is connected.
|
|
58
|
+
*/
|
|
59
|
+
connect?: (value: Param, dom: Element | Text) => void;
|
|
60
|
+
/**
|
|
61
|
+
Called when a widget of this type is removed from an editor
|
|
62
|
+
that is connected to a document, or when the editor containing
|
|
63
|
+
the widget is disconnected.
|
|
64
|
+
*/
|
|
65
|
+
disconnect?: (value: Param, dom: Element | Text) => void;
|
|
66
|
+
/**
|
|
67
|
+
Called before the editor handles a DOM event that comes from
|
|
68
|
+
inside the widget. May return true to indicate that no further
|
|
69
|
+
handling of the event should happen.
|
|
70
|
+
*/
|
|
71
|
+
handleEvent?: (event: Event, wg: Wordgard) => boolean;
|
|
72
|
+
/**
|
|
73
|
+
Set this to false for widgets that either aren't visible or
|
|
74
|
+
are positioned outside of the regular document flow.
|
|
75
|
+
*/
|
|
76
|
+
inFlow?: boolean;
|
|
77
|
+
};
|
|
78
|
+
/**
|
|
79
|
+
Each widget has an associated type that describes how it
|
|
80
|
+
behaves.
|
|
81
|
+
*/
|
|
82
|
+
class Type<Param> {
|
|
83
|
+
private constructor();
|
|
84
|
+
/**
|
|
85
|
+
Create an instance of this widget type.
|
|
86
|
+
*/
|
|
87
|
+
of(value: Param): Widget<Param>;
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
type DecoElt = Elt<Widget | string>;
|
|
91
|
+
declare namespace Decoration {
|
|
92
|
+
/**
|
|
93
|
+
Node shapes can be either a widget or an element which may
|
|
94
|
+
contain widgets.
|
|
95
|
+
*/
|
|
96
|
+
type Shape = Widget | DecoElt;
|
|
97
|
+
namespace Tag {
|
|
98
|
+
/**
|
|
99
|
+
Override the way a given node type is drawn in the editor. By
|
|
100
|
+
default, the {@link doc.Node.Spec.shape `shape`} field in the
|
|
101
|
+
type's definition will be used, but extensions created with
|
|
102
|
+
this function can provide an alternative shape for a given
|
|
103
|
+
type.
|
|
104
|
+
|
|
105
|
+
When providing a function for the shape, keep in mind that the
|
|
106
|
+
result will be cached by tag, and you should make sure your
|
|
107
|
+
function is pure.
|
|
108
|
+
|
|
109
|
+
When providing a function that returns a shape that changes
|
|
110
|
+
whether the node is rendered as an atom, you need to provide
|
|
111
|
+
the `atom`.
|
|
112
|
+
*/
|
|
113
|
+
function shape<T extends Node$1.Type.Ref<any>>(type: T, shape: Shape | ((tag: Node$1.Tag.For<T>) => Shape), config?: {
|
|
114
|
+
atom?: boolean;
|
|
115
|
+
}): GardState.Extension;
|
|
116
|
+
namespace shape {
|
|
117
|
+
/**
|
|
118
|
+
This function allows you to define a {@link Decoration.Tag.shape
|
|
119
|
+
custom node shape} that depends on the editor state. It will
|
|
120
|
+
automatically track what slots (see {@link
|
|
121
|
+
GardState.Facet.compute}) you use, and make sure the nodes
|
|
122
|
+
are redrawn when those change.
|
|
123
|
+
|
|
124
|
+
If your shape function returns a function from a tag, you
|
|
125
|
+
must be careful do any state access you need in the _outer_
|
|
126
|
+
function, not the returned function, or it won't be tracked.
|
|
127
|
+
|
|
128
|
+
You generally don't want to make your shapes depend on
|
|
129
|
+
constantly-changing slots like the document or selection,
|
|
130
|
+
because when the document is big, there's a non-trivial
|
|
131
|
+
amount of work involved when a node shape changes (or may
|
|
132
|
+
have changed).
|
|
133
|
+
|
|
134
|
+
When providing a shape for a plot that changes whether it is
|
|
135
|
+
rendered as an atom, provide the `atom` option.
|
|
136
|
+
*/
|
|
137
|
+
function dynamic<T extends Node$1.Type<any>>(// FIXME find better name?
|
|
138
|
+
type: T, shape: (state: GardState) => Shape | ((tag: Node$1.Tag.For<T>) => Shape), config?: {
|
|
139
|
+
atom?: boolean;
|
|
140
|
+
}): GardState.Extension;
|
|
141
|
+
}
|
|
142
|
+
/**
|
|
143
|
+
Define a wrapper to be added around a given node type, or some
|
|
144
|
+
part of it. The given elt should include a hole (`0`) to
|
|
145
|
+
indicate where the original shape goes.
|
|
146
|
+
|
|
147
|
+
If a `target` option is given, and matching some element in
|
|
148
|
+
the node's existing shape, only that element will be wrapped.
|
|
149
|
+
Uses a subset of CSS selectors that supports only tag name and
|
|
150
|
+
class names (`img.x.y`).
|
|
151
|
+
*/
|
|
152
|
+
function wrapper(type: Node$1.Type.Ref<any>, wrapper: DecoElt, options?: {
|
|
153
|
+
target?: string;
|
|
154
|
+
}): GardState.Extension;
|
|
155
|
+
/**
|
|
156
|
+
Add a widget to every instance of the given node type. Such
|
|
157
|
+
widgets can appear before or after the node, and for plots
|
|
158
|
+
that aren't rendered as atoms, at its start or end.
|
|
159
|
+
|
|
160
|
+
When a function, `widget` will be cached by tag, and should be
|
|
161
|
+
pure.
|
|
162
|
+
*/
|
|
163
|
+
function widget<T extends Node$1.Type.Ref<any>>(type: T, place: "before" | "after" | "start" | "end", widget: Widget | ((tag: Node$1.Tag.For<T>) => Widget)): GardState.Extension;
|
|
164
|
+
namespace widget {
|
|
165
|
+
/**
|
|
166
|
+
Define a node widget decoration that depends on some aspect
|
|
167
|
+
of the editor state. See the notes for {@link
|
|
168
|
+
Decoration.Tag.shape.dynamic}.
|
|
169
|
+
*/
|
|
170
|
+
function dynamic<T extends Node$1.Type.Ref<any>>(type: T, place: "before" | "after" | "start" | "end", widget: (state: GardState) => Widget | ((tag: Node$1.Tag.For<T>) => Widget)): GardState.Extension;
|
|
171
|
+
}
|
|
172
|
+
/**
|
|
173
|
+
Add an attribute to the representation of a given node type.
|
|
174
|
+
|
|
175
|
+
By default, the attribute is added to the outer element (or a
|
|
176
|
+
wrapper element if the node is rendered as a widget). If the
|
|
177
|
+
`target` option is given, and
|
|
178
|
+
[matches](#editor.Decoration.Tag.wrapper.options.target) an
|
|
179
|
+
element in the representation, it will be added to that
|
|
180
|
+
element instead.
|
|
181
|
+
*/
|
|
182
|
+
function attribute<T extends Node$1.Type.Ref<any>>(type: T, attr: string, value: string | ((tag: Node$1.Tag.For<T>) => string), options?: {
|
|
183
|
+
target?: string;
|
|
184
|
+
}): GardState.Extension;
|
|
185
|
+
}
|
|
186
|
+
/**
|
|
187
|
+
A point decoration is a decoration that targets a given position
|
|
188
|
+
in the document, or the node after a given position. Sets of
|
|
189
|
+
point decorations can be provided as point sets through {@link
|
|
190
|
+
Decoration.Point.source}.
|
|
191
|
+
*/
|
|
192
|
+
abstract class Point implements PointSet.Value {
|
|
193
|
+
abstract eq(other: PointSet.Value): boolean;
|
|
194
|
+
abstract side: number;
|
|
195
|
+
abstract trackMode: ChangeSet.TrackMode | undefined;
|
|
196
|
+
/**
|
|
197
|
+
Display a widget at this point.
|
|
198
|
+
*/
|
|
199
|
+
static widget(widget: Widget, options?: {
|
|
200
|
+
/**
|
|
201
|
+
Determines where this widget appears relative to the cursor
|
|
202
|
+
(negative means before, positive after, zero means to make
|
|
203
|
+
it depend on the cursor's own side) and other widgets in the
|
|
204
|
+
same position. Defaults to zero.
|
|
205
|
+
*/
|
|
206
|
+
side?: number;
|
|
207
|
+
/**
|
|
208
|
+
What side to track when changes happen around the widget.
|
|
209
|
+
The default is to keep the widget around unless the content
|
|
210
|
+
on both sides is deleted. You can pass undefined to indicate
|
|
211
|
+
the widget should not be deleted by changes, or
|
|
212
|
+
`"before"`/`"after"` to use one specific side.
|
|
213
|
+
*/
|
|
214
|
+
trackMode?: ChangeSet.TrackMode | undefined;
|
|
215
|
+
}): Point;
|
|
216
|
+
/**
|
|
217
|
+
Add a set of attributes to the node after this decoration's
|
|
218
|
+
position.
|
|
219
|
+
|
|
220
|
+
You can target a [specific
|
|
221
|
+
element](#editor.Decoration.Tag.wrapper.options.target) in the
|
|
222
|
+
node's representation with the `target` option.
|
|
223
|
+
*/
|
|
224
|
+
static attributes(attrs: Record<string, string>, options?: {
|
|
225
|
+
target?: string;
|
|
226
|
+
}): Point;
|
|
227
|
+
/**
|
|
228
|
+
Override the shape of the node after the decoration's point
|
|
229
|
+
with the given one.
|
|
230
|
+
*/
|
|
231
|
+
static shape(shape: Shape): Point;
|
|
232
|
+
/**
|
|
233
|
+
Wrap the node, or inner node selected with `target`, at the
|
|
234
|
+
given position with a wrapper.
|
|
235
|
+
*/
|
|
236
|
+
static wrapper(wrapper: DecoElt, spec?: {
|
|
237
|
+
target?: string;
|
|
238
|
+
}): Point;
|
|
239
|
+
/**
|
|
240
|
+
The facet used to register a point decoration source.
|
|
241
|
+
Functions provided in this way will be called on every editor
|
|
242
|
+
update, so computing the set on the fly will only perform well
|
|
243
|
+
for very simple decoration sets, and you'll usually want to
|
|
244
|
+
keep your set in a state field and update it incrementally.
|
|
245
|
+
*/
|
|
246
|
+
static source: GardState.Facet<(state: GardState) => PointSet<Point>, readonly ((state: GardState) => PointSet<Point>)[]>;
|
|
247
|
+
}
|
|
248
|
+
/**
|
|
249
|
+
Range decorations apply to a document range. They are stored in
|
|
250
|
+
{@link RangeSet}s and registered in an editor configuration with
|
|
251
|
+
{@link Decoration.Range.source}.
|
|
252
|
+
*/
|
|
253
|
+
abstract class Range implements RangeSet.Value {
|
|
254
|
+
/**
|
|
255
|
+
@hidden
|
|
256
|
+
*/
|
|
257
|
+
protected constructor(spec: Decoration.Range.Spec);
|
|
258
|
+
get inclusiveStart(): boolean;
|
|
259
|
+
get inclusiveEnd(): boolean;
|
|
260
|
+
abstract eq(other: RangeSet.Value): boolean;
|
|
261
|
+
/**
|
|
262
|
+
Create a range decoration that wraps nodes in a range with
|
|
263
|
+
an element, using the given tag name.
|
|
264
|
+
*/
|
|
265
|
+
static wrapper(tagName: string, spec: Decoration.Range.WrapperSpec): Range;
|
|
266
|
+
/**
|
|
267
|
+
Create a range decoration that adds an attribute to nodes in a
|
|
268
|
+
range.
|
|
269
|
+
*/
|
|
270
|
+
static attribute(attr: string, value: string, options?: Decoration.Range.Spec): Range;
|
|
271
|
+
/**
|
|
272
|
+
The facet used to register range decoration sources. The
|
|
273
|
+
source function will be called on every update. Generating big
|
|
274
|
+
range sets on the fly will not perform well, so you'll often
|
|
275
|
+
want to store these in a state field.
|
|
276
|
+
*/
|
|
277
|
+
static source: GardState.Facet<(state: GardState) => RangeSet<Range>, readonly ((state: GardState) => RangeSet<Range>)[]>;
|
|
278
|
+
}
|
|
279
|
+
namespace Range {
|
|
280
|
+
/**
|
|
281
|
+
Configuration object for range decorations.
|
|
282
|
+
*/
|
|
283
|
+
interface Spec {
|
|
284
|
+
/**
|
|
285
|
+
Determines whether content inserted next to the range is
|
|
286
|
+
included when mapping the range through a change. Defaults
|
|
287
|
+
to false.
|
|
288
|
+
*/
|
|
289
|
+
inclusive?: boolean | "start" | "end";
|
|
290
|
+
/**
|
|
291
|
+
If given, apply this decoration only to matching nodes.
|
|
292
|
+
*/
|
|
293
|
+
query?: Node$1.Query;
|
|
294
|
+
/**
|
|
295
|
+
The type of nodes in the range to apply the decoration to.
|
|
296
|
+
Defaults to `"atom"`.
|
|
297
|
+
*/
|
|
298
|
+
scope?: "atom" | "inlineatom" | "all";
|
|
299
|
+
}
|
|
300
|
+
/**
|
|
301
|
+
Configuration object for wrapper range decorations.
|
|
302
|
+
*/
|
|
303
|
+
interface WrapperSpec extends Decoration.Range.Spec {
|
|
304
|
+
/**
|
|
305
|
+
Attributes to add to the wrapper element.
|
|
306
|
+
*/
|
|
307
|
+
attributes?: Record<string, string>;
|
|
308
|
+
/**
|
|
309
|
+
A wrapper's rank determines the nesting order between it and
|
|
310
|
+
other wrappers created by range decorations or marks. Should be
|
|
311
|
+
a number between 0 and 100, if given.
|
|
312
|
+
*/
|
|
313
|
+
rank?: number;
|
|
314
|
+
/**
|
|
315
|
+
Whether this wrapper may span multiple sibling nodes.
|
|
316
|
+
Non-spanning wrappers will be created separately for each
|
|
317
|
+
node. Defaults to true.
|
|
318
|
+
*/
|
|
319
|
+
spanning?: boolean;
|
|
320
|
+
}
|
|
321
|
+
}
|
|
322
|
+
}
|
|
323
|
+
/**
|
|
324
|
+
Data structure used to store sets of points and then track them
|
|
325
|
+
across document changes. Mostly used for {@link Decoration.Point
|
|
326
|
+
point decorations}, but can also track your own types, if you make
|
|
327
|
+
sure they implement the {@link PointSet.Value} interface.
|
|
328
|
+
*/
|
|
329
|
+
declare class PointSet<T extends PointSet.Value = PointSet.Value> {
|
|
330
|
+
/**
|
|
331
|
+
The values in this set.
|
|
332
|
+
*/
|
|
333
|
+
readonly values: readonly T[];
|
|
334
|
+
/**
|
|
335
|
+
The positions of the values in this set.
|
|
336
|
+
*/
|
|
337
|
+
readonly positions: readonly number[];
|
|
338
|
+
private constructor();
|
|
339
|
+
/**
|
|
340
|
+
The number of points in this set.
|
|
341
|
+
*/
|
|
342
|
+
get length(): number;
|
|
343
|
+
/**
|
|
344
|
+
Adjust the points for a set of document changes. Returns a new
|
|
345
|
+
set with the adjusted points. May delete points when the content
|
|
346
|
+
around them was deleted.
|
|
347
|
+
*/
|
|
348
|
+
map(changes: ChangeSet): PointSet<T>;
|
|
349
|
+
/**
|
|
350
|
+
Returns the union of this set and the given set.
|
|
351
|
+
*/
|
|
352
|
+
merge(other: PointSet<T>): PointSet<T>;
|
|
353
|
+
/**
|
|
354
|
+
Get the value at the given position, if any. If there's multiple
|
|
355
|
+
values at that position, the one with the lowest side is
|
|
356
|
+
returned.
|
|
357
|
+
*/
|
|
358
|
+
at(pos: number): T | undefined;
|
|
359
|
+
/**
|
|
360
|
+
Create a point set from an iterable of `[position, value]`
|
|
361
|
+
tuples, or a function that calls its argument for every point to
|
|
362
|
+
add.
|
|
363
|
+
*/
|
|
364
|
+
static create<T extends PointSet.Value>(source: Iterable<[number, T]> | ((add: (pos: number, value: T) => void) => void)): PointSet<T>;
|
|
365
|
+
/**
|
|
366
|
+
The empty point set.
|
|
367
|
+
*/
|
|
368
|
+
static empty: PointSet<any>;
|
|
369
|
+
}
|
|
370
|
+
declare namespace PointSet {
|
|
371
|
+
/**
|
|
372
|
+
Objects stored in a point set must conform to this interface.
|
|
373
|
+
*/
|
|
374
|
+
interface Value {
|
|
375
|
+
/**
|
|
376
|
+
The side of the point. Used to provide a sorting of points at
|
|
377
|
+
the same position
|
|
378
|
+
*/
|
|
379
|
+
side: number;
|
|
380
|
+
/**
|
|
381
|
+
Specifies whether the point should be deleted when content
|
|
382
|
+
next to it is deleted. See {@link ChangeSet.mapPos}.
|
|
383
|
+
*/
|
|
384
|
+
trackMode: ChangeSet.TrackMode | undefined;
|
|
385
|
+
/**
|
|
386
|
+
Method to compare this value to another.
|
|
387
|
+
*/
|
|
388
|
+
eq(other: PointSet.Value): boolean;
|
|
389
|
+
}
|
|
390
|
+
}
|
|
391
|
+
/**
|
|
392
|
+
Data structure that stores sets of ranges, for use with {@link
|
|
393
|
+
Decoration.Range range decorations} or other data types
|
|
394
|
+
implementing {@link RangeSet.Value}.
|
|
395
|
+
*/
|
|
396
|
+
declare class RangeSet<T extends RangeSet.Value = RangeSet.Value> {
|
|
397
|
+
/**
|
|
398
|
+
The value associated with the ranges in the set.
|
|
399
|
+
*/
|
|
400
|
+
readonly values: readonly T[];
|
|
401
|
+
/**
|
|
402
|
+
The start positions of the ranges in this set.
|
|
403
|
+
*/
|
|
404
|
+
readonly from: readonly number[];
|
|
405
|
+
/**
|
|
406
|
+
The end positions of the ranges.
|
|
407
|
+
*/
|
|
408
|
+
readonly to: readonly number[];
|
|
409
|
+
private constructor();
|
|
410
|
+
/**
|
|
411
|
+
The number of ranges stored in this set.
|
|
412
|
+
*/
|
|
413
|
+
get length(): number;
|
|
414
|
+
/**
|
|
415
|
+
Adjust the positions of the ranges for the given change set.
|
|
416
|
+
Returns a set with the updated ranges.
|
|
417
|
+
*/
|
|
418
|
+
map(changes: ChangeSet): RangeSet<T>;
|
|
419
|
+
/**
|
|
420
|
+
Create a range set from an iterable of `[from, to, value]`
|
|
421
|
+
tuples, or a function that calls its argument for every range to
|
|
422
|
+
add.
|
|
423
|
+
*/
|
|
424
|
+
static create<T extends RangeSet.Value>(source: Iterable<[number, number, T]> | ((add: (from: number, to: number, value: T) => void) => void)): RangeSet<T>;
|
|
425
|
+
/**
|
|
426
|
+
The empty range set.
|
|
427
|
+
*/
|
|
428
|
+
static empty: RangeSet<any>;
|
|
429
|
+
}
|
|
430
|
+
declare namespace RangeSet {
|
|
431
|
+
/**
|
|
432
|
+
Values stored in a range set must conform to this interface.
|
|
433
|
+
*/
|
|
434
|
+
interface Value {
|
|
435
|
+
/**
|
|
436
|
+
Whether content inserted at the start of this value's range is
|
|
437
|
+
included in the range.
|
|
438
|
+
*/
|
|
439
|
+
inclusiveStart: boolean;
|
|
440
|
+
/**
|
|
441
|
+
Whether content inserted at the end is included.
|
|
442
|
+
*/
|
|
443
|
+
inclusiveEnd: boolean;
|
|
444
|
+
/**
|
|
445
|
+
Compare this value to another.
|
|
446
|
+
*/
|
|
447
|
+
eq(other: Value): boolean;
|
|
448
|
+
}
|
|
449
|
+
}
|
|
450
|
+
|
|
451
|
+
declare const enum TileFlag {
|
|
452
|
+
None = 0,
|
|
453
|
+
NodeInner = 1,
|
|
454
|
+
PlotContent = 2,
|
|
455
|
+
Spanning = 4,
|
|
456
|
+
Wrapper = 8,
|
|
457
|
+
Point = 16,
|
|
458
|
+
PointBefore = 32,
|
|
459
|
+
PointAfter = 64,
|
|
460
|
+
PointSide = 96,
|
|
461
|
+
Composition = 128,
|
|
462
|
+
Synced = 256,// Node has been synced. DOM content matches child list / text content, child array becomes read-only
|
|
463
|
+
Atom = 512,// Composite tile whose length isn't determined by child length
|
|
464
|
+
HasContent = 1024,// EltTile whose elt has a content hole
|
|
465
|
+
AfterContent = 2048,// Tiles that sit after their parent's content position
|
|
466
|
+
ContentNotLast = 4096,// EltTile that has children with AfterContent flag
|
|
467
|
+
Dirty = 8192
|
|
468
|
+
}
|
|
469
|
+
declare const enum Orientation {
|
|
470
|
+
Row = 0,
|
|
471
|
+
Col = 1
|
|
472
|
+
}
|
|
473
|
+
declare class CoordPos {
|
|
474
|
+
readonly pos: number;
|
|
475
|
+
readonly target: number | null;
|
|
476
|
+
readonly side: -1 | 1;
|
|
477
|
+
readonly vertOutside: boolean;
|
|
478
|
+
constructor(pos: number, target: number | null, side: -1 | 1, vertOutside: boolean);
|
|
479
|
+
map(mapping: ChangeSet): CoordPos;
|
|
480
|
+
static create(pos: number, side: -1 | 1, target?: number | null, vertOutside?: boolean): CoordPos;
|
|
481
|
+
}
|
|
482
|
+
declare abstract class Tile {
|
|
483
|
+
dom: Element | Text;
|
|
484
|
+
parent: CompositeTile | null;
|
|
485
|
+
abstract children: Tile[];
|
|
486
|
+
length: number;
|
|
487
|
+
flags: TileFlag;
|
|
488
|
+
constructor(dom: Element | Text, flags: number);
|
|
489
|
+
get isAtom(): boolean;
|
|
490
|
+
get isNodeOuter(): boolean;
|
|
491
|
+
get isNodeInner(): boolean;
|
|
492
|
+
get isNode(): boolean;
|
|
493
|
+
get isPlotContent(): boolean;
|
|
494
|
+
get isText(): boolean;
|
|
495
|
+
get isDoc(): boolean;
|
|
496
|
+
get isWrapper(): boolean;
|
|
497
|
+
get isSpanning(): boolean;
|
|
498
|
+
get isComposition(): boolean;
|
|
499
|
+
get isPoint(): boolean;
|
|
500
|
+
get node(): Node$1 | null;
|
|
501
|
+
posBeforeChild(child: Tile, ownStart?: number): number;
|
|
502
|
+
get posBefore(): number;
|
|
503
|
+
get posAtStart(): number;
|
|
504
|
+
get posAfter(): number;
|
|
505
|
+
get posAtEnd(): number;
|
|
506
|
+
get boundary(): 0 | 1;
|
|
507
|
+
get firstChild(): Tile | null;
|
|
508
|
+
get lastChild(): Tile | null;
|
|
509
|
+
handleEvent(event: Event, wg: Wordgard): boolean;
|
|
510
|
+
get ignoreMutations(): boolean;
|
|
511
|
+
toString(): string;
|
|
512
|
+
sync(): void;
|
|
513
|
+
connect(): void;
|
|
514
|
+
disconnect(reused?: Map<Tile, Reused>): void;
|
|
515
|
+
nearestNode(): Tile;
|
|
516
|
+
posAtCoords(state: GardState, x: number, y: number): CoordPos;
|
|
517
|
+
abstract posAtCoordsInner(start: number, state: GardState, x: number, y: number, textblock: TextblockMap | null, orientation: Orientation): CoordPos;
|
|
518
|
+
static get(node: DOMNode): Tile | undefined;
|
|
519
|
+
}
|
|
520
|
+
declare class CompositeTile extends Tile {
|
|
521
|
+
children: Tile[];
|
|
522
|
+
dom: Element;
|
|
523
|
+
addChild(child: Tile): void;
|
|
524
|
+
sync(): void;
|
|
525
|
+
syncChildren(): void;
|
|
526
|
+
posAtCoordsInner(start: number, state: GardState, x: number, y: number, textblock: TextblockMap | null, orientation: Orientation): CoordPos;
|
|
527
|
+
posAtCoordsRow(start: number, state: GardState, x: number, y: number, textblock: TextblockMap | null): CoordPos | null;
|
|
528
|
+
posAtCoordsCol(start: number, state: GardState, x: number, y: number, textblock: TextblockMap | null): CoordPos;
|
|
529
|
+
}
|
|
530
|
+
declare const enum Reused {
|
|
531
|
+
Full = 1,
|
|
532
|
+
DOM = 2
|
|
533
|
+
}
|
|
534
|
+
|
|
535
|
+
type DOMNode = Node;
|
|
536
|
+
declare global {
|
|
537
|
+
interface Node {
|
|
538
|
+
wgTile?: Tile;
|
|
539
|
+
}
|
|
540
|
+
}
|
|
541
|
+
|
|
542
|
+
/**
|
|
543
|
+
This class implements the editor's user interface. It wraps the
|
|
544
|
+
editable DOM surface and possibly other elements such as panels.
|
|
545
|
+
*/
|
|
546
|
+
declare class Wordgard {
|
|
547
|
+
/**
|
|
548
|
+
Construct a new editor. You'll want to either provide a `parent`
|
|
549
|
+
option, or put the editor's {@link Wordgard.dom DOM element}
|
|
550
|
+
into your document after creating an editor, so that the user
|
|
551
|
+
can see it.
|
|
552
|
+
*/
|
|
553
|
+
static create(spec: Wordgard.Spec): Wordgard;
|
|
554
|
+
/**
|
|
555
|
+
The current editor state.
|
|
556
|
+
*/
|
|
557
|
+
get state(): GardState;
|
|
558
|
+
/**
|
|
559
|
+
Indicates whether the user is currently composing text via
|
|
560
|
+
[IME](https://en.wikipedia.org/wiki/Input_method), and at least
|
|
561
|
+
one change has been made in the current composition.
|
|
562
|
+
*/
|
|
563
|
+
get composing(): boolean;
|
|
564
|
+
/**
|
|
565
|
+
Indicates whether the user is currently in composing state. Note
|
|
566
|
+
that on some platforms, like Android, this will be the case a
|
|
567
|
+
lot, since just putting the cursor on a word starts a
|
|
568
|
+
composition there.
|
|
569
|
+
*/
|
|
570
|
+
get compositionStarted(): boolean | null;
|
|
571
|
+
/**
|
|
572
|
+
Queries whether the editor's DOM is {@link Wordgard#editable
|
|
573
|
+
editable}.
|
|
574
|
+
*/
|
|
575
|
+
get editable(): boolean;
|
|
576
|
+
/**
|
|
577
|
+
Returns true if the editor can be focused (is {@link
|
|
578
|
+
Wordgard.editable editable} or has a tabindex).
|
|
579
|
+
*/
|
|
580
|
+
get focusable(): boolean;
|
|
581
|
+
/**
|
|
582
|
+
The document or shadow root that the editor lives in.
|
|
583
|
+
*/
|
|
584
|
+
root: DocumentOrShadowRoot;
|
|
585
|
+
/**
|
|
586
|
+
The outer DOM element that represents the editor.
|
|
587
|
+
*/
|
|
588
|
+
readonly dom: HTMLElement;
|
|
589
|
+
/**
|
|
590
|
+
The DOM element that can be styled to scroll. (Note that it may
|
|
591
|
+
not have been, so you can't assume this is scrollable.)
|
|
592
|
+
*/
|
|
593
|
+
readonly scrollDOM: HTMLElement;
|
|
594
|
+
/**
|
|
595
|
+
The editable DOM element holding the editor content. You should
|
|
596
|
+
not, usually, interact with this content directly though the
|
|
597
|
+
DOM, since the editor will immediately undo most of the changes
|
|
598
|
+
you make. Instead, {@link Wordgard.dispatch dispatch} {@link
|
|
599
|
+
Transaction transactions} to modify content, and {@link
|
|
600
|
+
Decoration decorations} to style it.
|
|
601
|
+
*/
|
|
602
|
+
readonly contentDOM: HTMLElement;
|
|
603
|
+
private announceDOM;
|
|
604
|
+
private id;
|
|
605
|
+
private pluginMap;
|
|
606
|
+
private editorAttrs;
|
|
607
|
+
private contentAttrs;
|
|
608
|
+
private styleModules;
|
|
609
|
+
private flushing;
|
|
610
|
+
private willFlush;
|
|
611
|
+
private flushFunc;
|
|
612
|
+
private autoColorScheme;
|
|
613
|
+
private domReaders;
|
|
614
|
+
private domWriters;
|
|
615
|
+
private pendingTransactionListeners;
|
|
616
|
+
private constructor();
|
|
617
|
+
/**
|
|
618
|
+
All editor state updates go through this. It takes a transaction
|
|
619
|
+
or transaction spec and updates the editor to show the new state
|
|
620
|
+
produced by that transaction. This function is bound to the editor
|
|
621
|
+
instance, so it does not have to be called as a method.
|
|
622
|
+
|
|
623
|
+
Will apply {@link Transaction.appender transaction appenders}
|
|
624
|
+
and include any extra transactions they produce in the editor's
|
|
625
|
+
state.
|
|
626
|
+
|
|
627
|
+
Updates will be immediately be reflected in the object's `state`
|
|
628
|
+
property, but updating the DOM will be deferred to the next
|
|
629
|
+
display update.
|
|
630
|
+
*/
|
|
631
|
+
dispatch(tr: Transaction | Transaction.Spec): void;
|
|
632
|
+
/**
|
|
633
|
+
Force a flush on the editor content, updating its DOM
|
|
634
|
+
representation for any pending changes.
|
|
635
|
+
*/
|
|
636
|
+
flush(): void;
|
|
637
|
+
private scrollTo;
|
|
638
|
+
private runUpdate;
|
|
639
|
+
private updatePlugins;
|
|
640
|
+
private updateAttrs;
|
|
641
|
+
private checkDir;
|
|
642
|
+
private showAnnouncements;
|
|
643
|
+
private mountStyles;
|
|
644
|
+
/**
|
|
645
|
+
Schedule a function that needs to read from the (flushed) DOM.
|
|
646
|
+
During an editor update, when doing anything that needs to
|
|
647
|
+
access the DOM layout, it is important to schedule it with this
|
|
648
|
+
method, to avoid forcing unnecessary DOM layouts.
|
|
649
|
+
*/
|
|
650
|
+
scheduleDOMRead(read: (wg: Wordgard) => void): void;
|
|
651
|
+
/**
|
|
652
|
+
Schedule a function that needs to modify the DOM. When doing any
|
|
653
|
+
kind of DOM mutation that depends on a {@link
|
|
654
|
+
Wordgard.scheduleDOMRead | DOM read}, use this method, so that
|
|
655
|
+
read and write phases remain separate.
|
|
656
|
+
*/
|
|
657
|
+
scheduleDOMWrite(write: (wg: Wordgard) => void): void;
|
|
658
|
+
/**
|
|
659
|
+
Get the value of a specific plugin, if present. Note that
|
|
660
|
+
plugins that crash can be dropped from an editor, so even when
|
|
661
|
+
you know you registered a given plugin, it is recommended to
|
|
662
|
+
check the return value of this method.
|
|
663
|
+
*/
|
|
664
|
+
plugin<T extends Wordgard.Plugin.Value>(plugin: Wordgard.Plugin<T>): T | null;
|
|
665
|
+
private ensureFlushed;
|
|
666
|
+
/**
|
|
667
|
+
Find the position at the end or start of the (wrapped) line. If
|
|
668
|
+
the given position isn't in a textblock, this will return null.
|
|
669
|
+
*/
|
|
670
|
+
moveToLineBoundary(start: GardSelection, forward: boolean): GardSelection.Text | null;
|
|
671
|
+
/**
|
|
672
|
+
Move a cursor position vertically. When `distance` isn't given,
|
|
673
|
+
it defaults to moving to the vertical element below or above the
|
|
674
|
+
start position. Otherwise, `distance` should provide a positive
|
|
675
|
+
distance in pixels.
|
|
676
|
+
|
|
677
|
+
When `start` has a
|
|
678
|
+
{@link GardSelection.goalColumn `goalColumn`}, the vertical
|
|
679
|
+
motion will use that as a target horizontal position. Otherwise,
|
|
680
|
+
the cursor's own horizontal position is used. The returned
|
|
681
|
+
cursor will have its goal column set to whichever column was
|
|
682
|
+
used. If `allowNode` is true, this may return a node selection
|
|
683
|
+
on a block node.
|
|
684
|
+
*/
|
|
685
|
+
moveVertically(start: GardSelection, forward: boolean, distance?: number, allowNode?: boolean): GardSelection | null;
|
|
686
|
+
/**
|
|
687
|
+
Find the DOM parent node and offset (child offset if `node` is
|
|
688
|
+
an element, character offset when it is a text node) at the
|
|
689
|
+
given document position.
|
|
690
|
+
*/
|
|
691
|
+
domAtPos(pos: number, assoc?: -1 | 1): {
|
|
692
|
+
node: DOMNode;
|
|
693
|
+
offset: number;
|
|
694
|
+
};
|
|
695
|
+
/**
|
|
696
|
+
Get the DOM element for the node at the given position, if any.
|
|
697
|
+
*/
|
|
698
|
+
nodeDOM(pos: number): Element | null;
|
|
699
|
+
/**
|
|
700
|
+
Find the document position at the given DOM node. Can be useful
|
|
701
|
+
for associating positions with DOM events. Will raise an error
|
|
702
|
+
when `node` isn't part of the editor content.
|
|
703
|
+
*/
|
|
704
|
+
posAtDOM(node: DOMNode, offset?: number): number;
|
|
705
|
+
/**
|
|
706
|
+
Find the Wordgard node represented by the given DOM node, or one
|
|
707
|
+
of its parent nodes, if any. Will not return the outer document node.
|
|
708
|
+
*/
|
|
709
|
+
nodeFromDOM(node: Element): {
|
|
710
|
+
pos: number;
|
|
711
|
+
node: Node$1;
|
|
712
|
+
} | null;
|
|
713
|
+
/**
|
|
714
|
+
Get the document position at the given screen coordinates.
|
|
715
|
+
*/
|
|
716
|
+
posAtCoords(coords: {
|
|
717
|
+
x: number;
|
|
718
|
+
y: number;
|
|
719
|
+
}): {
|
|
720
|
+
pos: number;
|
|
721
|
+
side: -1 | 1;
|
|
722
|
+
target: number | null;
|
|
723
|
+
};
|
|
724
|
+
/**
|
|
725
|
+
Get the screen coordinates at the given document position.
|
|
726
|
+
`side` determines whether the coordinates are based on the
|
|
727
|
+
element before (-1) or after (1) the position (if no element is
|
|
728
|
+
available on the given side, the method will transparently use
|
|
729
|
+
another strategy to get reasonable coordinates).
|
|
730
|
+
*/
|
|
731
|
+
coordsAtPos(pos: number, assoc?: -1 | 1): DOMRect;
|
|
732
|
+
/**
|
|
733
|
+
Return the rectangle around a given node or character. If there
|
|
734
|
+
is no element directly after `pos`, this will return null. For
|
|
735
|
+
space characters that are a line wrap point, this will return
|
|
736
|
+
the position before the line break.
|
|
737
|
+
*/
|
|
738
|
+
coordsForElement(pos: number): DOMRect | null;
|
|
739
|
+
/**
|
|
740
|
+
Check whether the editor has focus.
|
|
741
|
+
*/
|
|
742
|
+
get hasFocus(): boolean;
|
|
743
|
+
/**
|
|
744
|
+
Put focus on the editor.
|
|
745
|
+
*/
|
|
746
|
+
focus(): void;
|
|
747
|
+
/**
|
|
748
|
+
Get the CSS classes for the currently active editor themes.
|
|
749
|
+
*/
|
|
750
|
+
get themeClasses(): string;
|
|
751
|
+
/**
|
|
752
|
+
Returns an effect that can be {@link Transaction.Spec.effects
|
|
753
|
+
added} to a transaction to cause it to scroll the given position
|
|
754
|
+
or range into view.
|
|
755
|
+
*/
|
|
756
|
+
static scrollIntoView(pos: number | GardSelection, options?: Wordgard.ScrollSpec): Transaction.Effect<unknown>;
|
|
757
|
+
/**
|
|
758
|
+
Add an
|
|
759
|
+
[`aria-label`](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Reference/Attributes/aria-label)
|
|
760
|
+
attribute to the editable element holding the given string or
|
|
761
|
+
phrase.
|
|
762
|
+
*/
|
|
763
|
+
static label(label: string | PhraseSet.Ref): GardState.Extension;
|
|
764
|
+
/**
|
|
765
|
+
Filter functions provided through this facet will be run on a
|
|
766
|
+
slice before it is serialized to the clipboard.
|
|
767
|
+
*/
|
|
768
|
+
static clipboardOutputFilter: GardState.Facet<(content: wordgard_doc.Slice, state: GardState) => wordgard_doc.Slice, readonly ((content: wordgard_doc.Slice, state: GardState) => wordgard_doc.Slice)[]>;
|
|
769
|
+
/**
|
|
770
|
+
Filter functions provided through this facet will be run on an
|
|
771
|
+
HTML string before it put onto the clipboard.
|
|
772
|
+
*/
|
|
773
|
+
static clipboardOutputHTMLFilter: GardState.Facet<(html: string, state: GardState) => string, readonly ((html: string, state: GardState) => string)[]>;
|
|
774
|
+
/**
|
|
775
|
+
This can be used to provide a function that converts a document
|
|
776
|
+
slice to a string that is put onto the plain-text clipboard.
|
|
777
|
+
Serializers are tried in order of precedence until one returns
|
|
778
|
+
a string.
|
|
779
|
+
*/
|
|
780
|
+
static clipboardTextSerializer: GardState.Facet<(slice: wordgard_doc.Slice, context: readonly wordgard_doc.Plot.Tag[], state: GardState) => string | null, readonly ((slice: wordgard_doc.Slice, context: readonly wordgard_doc.Plot.Tag[], state: GardState) => string | null)[]>;
|
|
781
|
+
/**
|
|
782
|
+
Filter to run on the plain text representation of content put
|
|
783
|
+
onto the clipboard.
|
|
784
|
+
*/
|
|
785
|
+
static clipboardOutputTextFilter: GardState.Facet<(html: string, state: GardState) => string, readonly ((html: string, state: GardState) => string)[]>;
|
|
786
|
+
/**
|
|
787
|
+
Filter functions provided through this facet will be run on a
|
|
788
|
+
slice after it is read from the clipboard.
|
|
789
|
+
*/
|
|
790
|
+
static clipboardInputFilter: GardState.Facet<(content: wordgard_doc.Slice, state: GardState) => wordgard_doc.Slice, readonly ((content: wordgard_doc.Slice, state: GardState) => wordgard_doc.Slice)[]>;
|
|
791
|
+
/**
|
|
792
|
+
Filter functions to run on HTML text that is read from the
|
|
793
|
+
clipboard.
|
|
794
|
+
*/
|
|
795
|
+
static clipboardInputHTMLFilter: GardState.Facet<(html: string, state: GardState) => string, readonly ((html: string, state: GardState) => string)[]>;
|
|
796
|
+
/**
|
|
797
|
+
When the editor reads plain text from the clipboard, this facet
|
|
798
|
+
can be used to provide a custom parser. Each provided function
|
|
799
|
+
is tried in order of precedence, until one returns a slice.
|
|
800
|
+
*/
|
|
801
|
+
static clipboardTextParser: GardState.Facet<(text: string, state: GardState) => wordgard_doc.Slice | null, readonly ((text: string, state: GardState) => wordgard_doc.Slice | null)[]>;
|
|
802
|
+
/**
|
|
803
|
+
Filter to run on plain text read from the clipboard.
|
|
804
|
+
*/
|
|
805
|
+
static clipboardInputTextFilter: GardState.Facet<(html: string, state: GardState) => string, readonly ((html: string, state: GardState) => string)[]>;
|
|
806
|
+
/**
|
|
807
|
+
Facet that allows you to register handlers to override paste
|
|
808
|
+
behavior.
|
|
809
|
+
*/
|
|
810
|
+
static pasteHandler: GardState.Facet<(wg: Wordgard, event: ClipboardEvent, slice: wordgard_doc.Slice, context: readonly wordgard_doc.Plot.Tag[]) => boolean, readonly ((wg: Wordgard, event: ClipboardEvent, slice: wordgard_doc.Slice, context: readonly wordgard_doc.Plot.Tag[]) => boolean)[]>;
|
|
811
|
+
/**
|
|
812
|
+
Facet for custom drop handlers. When the drop is done inside the
|
|
813
|
+
editor and should move an existing range, the `move` parameter
|
|
814
|
+
will hold the origin range.
|
|
815
|
+
*/
|
|
816
|
+
static dropHandler: GardState.Facet<(wg: Wordgard, event: DragEvent, pos: number, move: {
|
|
817
|
+
from: number;
|
|
818
|
+
to: number;
|
|
819
|
+
} | null, slice: wordgard_doc.Slice, context: readonly wordgard_doc.Plot.Tag[]) => boolean, readonly ((wg: Wordgard, event: DragEvent, pos: number, move: {
|
|
820
|
+
from: number;
|
|
821
|
+
to: number;
|
|
822
|
+
} | null, slice: wordgard_doc.Slice, context: readonly wordgard_doc.Plot.Tag[]) => boolean)[]>;
|
|
823
|
+
/**
|
|
824
|
+
This annotation is added to transactions created because the
|
|
825
|
+
editor's focused status changed. It holds `true` when the editor
|
|
826
|
+
gained focus, `false` when it lost focus.
|
|
827
|
+
*/
|
|
828
|
+
static isFocusChange: Transaction.Annotation.Type<boolean>;
|
|
829
|
+
/**
|
|
830
|
+
Facet to add a [style
|
|
831
|
+
module](https://github.com/marijnh/style-mod#documentation) to
|
|
832
|
+
an editor. The editor will ensure that the module is mounted in
|
|
833
|
+
its {@link Wordgard.root document root}.
|
|
834
|
+
*/
|
|
835
|
+
static styleModule: GardState.Facet<StyleModule, readonly StyleModule[]>;
|
|
836
|
+
/**
|
|
837
|
+
Returns an extension that can be used to add a DOM event handler
|
|
838
|
+
to the editor. For any given event, such functions are ordered
|
|
839
|
+
by extension precedence, and the first handler to return true
|
|
840
|
+
will be assumed to have handled that event, and no other
|
|
841
|
+
handlers or built-in behavior will be activated for it. These
|
|
842
|
+
are registered on the {@link Wordgard.contentDOM content
|
|
843
|
+
element}, except for `scroll` handlers, which will be called any
|
|
844
|
+
time the editor's {@link Wordgard.scrollDOM scroll element} or
|
|
845
|
+
one of its parent nodes is scrolled.
|
|
846
|
+
*/
|
|
847
|
+
static domEventHandler<Event extends keyof HTMLElementEventMap>(event: Event, handler: (event: HTMLElementEventMap[Event], wg: Wordgard) => boolean | void): GardState.Extension;
|
|
848
|
+
/**
|
|
849
|
+
Create an extension that registers a DOM event observers. Contrary
|
|
850
|
+
to event {@link Wordgard.domEventHandler handlers},
|
|
851
|
+
observers can't be prevented from running by a higher-precedence
|
|
852
|
+
handler returning true. They also don't prevent other handlers
|
|
853
|
+
and observers from running when they return true, and should not
|
|
854
|
+
call `preventDefault`.
|
|
855
|
+
*/
|
|
856
|
+
static domEventObserver<Event extends keyof HTMLElementEventMap>(event: Event, observer: (event: HTMLElementEventMap[Event], wg: Wordgard) => void): GardState.Extension;
|
|
857
|
+
/**
|
|
858
|
+
Scroll handlers can override how editor content is scrolled into
|
|
859
|
+
view. If they return `true`, no further handling happens for the
|
|
860
|
+
scrolling. If they return false, the default scroll behavior is
|
|
861
|
+
applied. Scroll handlers should never initiate editor updates.
|
|
862
|
+
*/
|
|
863
|
+
static scrollHandler: GardState.Facet<(wg: Wordgard, target: {
|
|
864
|
+
from: number;
|
|
865
|
+
to: number;
|
|
866
|
+
} & Wordgard.ScrollSpec) => boolean, readonly ((wg: Wordgard, target: {
|
|
867
|
+
from: number;
|
|
868
|
+
to: number;
|
|
869
|
+
} & Wordgard.ScrollSpec) => boolean)[]>;
|
|
870
|
+
/**
|
|
871
|
+
Allows you to provide a function that should be called when the
|
|
872
|
+
library catches an exception from an extension (mostly from
|
|
873
|
+
plugins, but may be used by other extensions to route exceptions
|
|
874
|
+
from user-code-provided callbacks). This is mostly useful for
|
|
875
|
+
debugging and logging. See {@link Wordgard.logException}.
|
|
876
|
+
*/
|
|
877
|
+
static exceptionSink: GardState.Facet<(exception: any) => void, readonly ((exception: any) => void)[]>;
|
|
878
|
+
/**
|
|
879
|
+
Registers a listener function to be called whenever a set of
|
|
880
|
+
transactions is applied to the editor. This function may
|
|
881
|
+
dispatch additional transactions, if needed.
|
|
882
|
+
*/
|
|
883
|
+
static transactionListener: GardState.Facet<(trs: readonly Transaction[], wg: Wordgard) => void, readonly ((trs: readonly Transaction[], wg: Wordgard) => void)[]>;
|
|
884
|
+
private runTransactionListeners;
|
|
885
|
+
/**
|
|
886
|
+
A facet that can be used to register a function to be called
|
|
887
|
+
after the editor flushes updates to the DOM. Dispatching
|
|
888
|
+
transactions from such a function is allowed, but will cause a
|
|
889
|
+
new, separate update to happen.
|
|
890
|
+
*/
|
|
891
|
+
static updateListener: GardState.Facet<(update: Wordgard.Update) => void, readonly ((update: Wordgard.Update) => void)[]>;
|
|
892
|
+
/**
|
|
893
|
+
Facet that controls whether the editor content DOM is editable.
|
|
894
|
+
When its highest-precedence value is `false`, the element will
|
|
895
|
+
not have its `contenteditable` attribute set. (Note that this
|
|
896
|
+
doesn't affect API calls that change the editor content, even
|
|
897
|
+
when those are bound to keys or buttons. See the {@link
|
|
898
|
+
GardState.readOnly `readOnly` facet} for that.)
|
|
899
|
+
|
|
900
|
+
A non-editable editor will, by default, not be focusable. You
|
|
901
|
+
can set a {@link Wordgard.contentAttributes content attribute}
|
|
902
|
+
of `tabindex: 0` to make an uneditable Wordgard focusable.
|
|
903
|
+
*/
|
|
904
|
+
static editable: GardState.Facet<boolean, boolean>;
|
|
905
|
+
/**
|
|
906
|
+
Controls the length of a full cursor blink cycle, in milliseconds.
|
|
907
|
+
Defaults to 1200. Can be set to 0 to disable blinking.
|
|
908
|
+
*/
|
|
909
|
+
static cursorBlinkRate: GardState.Facet<number, number>;
|
|
910
|
+
/**
|
|
911
|
+
Allows you to influence the way mouse selection happens. The
|
|
912
|
+
functions in this facet will be called for a `mousedown` event
|
|
913
|
+
on the editor, and can return an object that overrides the way a
|
|
914
|
+
selection is computed from that mouse click or drag.
|
|
915
|
+
*/
|
|
916
|
+
static mouseSelectionStyle: GardState.Facet<MakeSelectionStyle, readonly MakeSelectionStyle[]>;
|
|
917
|
+
/**
|
|
918
|
+
Facet used to configure whether a given selection drag event
|
|
919
|
+
should move or copy the selection. The given predicate will be
|
|
920
|
+
called with the `mousedown` event, and can return `true` when
|
|
921
|
+
the drag should move the content. The default behavior is to
|
|
922
|
+
copy when holding Alt on Mac and Control on other platforms, and
|
|
923
|
+
move otherwise.
|
|
924
|
+
*/
|
|
925
|
+
static dragMovesSelection: GardState.Facet<(event: MouseEvent) => boolean, readonly ((event: MouseEvent) => boolean)[]>;
|
|
926
|
+
/**
|
|
927
|
+
Create a theme extension. The first argument can be a
|
|
928
|
+
[`style-mod`](https://github.com/marijnh/style-mod#documentation)
|
|
929
|
+
style spec providing the styles for the theme. These will be
|
|
930
|
+
prefixed with a generated scope class.
|
|
931
|
+
|
|
932
|
+
Because the selectors are prefixed, rules that directly match
|
|
933
|
+
the editor's {@link Wordgard.dom wrapper element} (to which the
|
|
934
|
+
scope class will be added) need to be explicitly differentiated
|
|
935
|
+
by adding an `&` to the selector for that element—for example
|
|
936
|
+
`&:has(wg-content:focus)`.
|
|
937
|
+
*/
|
|
938
|
+
static theme(spec: Record<string, StyleSpec>): GardState.Extension;
|
|
939
|
+
/**
|
|
940
|
+
This facet controls whether a dark or light color scheme is
|
|
941
|
+
active, which determines whether style rules with a `&dark` or
|
|
942
|
+
`&light` selector are applied. Defaults to `"light"`. If set to
|
|
943
|
+
`"auto"`, the editor uses a CSS `prefers-color-scheme: dark`
|
|
944
|
+
query to determine whether to enable light or dark mode.
|
|
945
|
+
|
|
946
|
+
Note that setting this to dark will not automatically make the
|
|
947
|
+
editor look dark. The default styling does not override the
|
|
948
|
+
inherited background and color of the editor. In case of a
|
|
949
|
+
page-wide `prefers-color-scheme` selection, those might already
|
|
950
|
+
be dark. But when setting an editor on a light background to
|
|
951
|
+
explicitly to use a dark theme, you'll need to make sure you
|
|
952
|
+
also load styles for that.
|
|
953
|
+
*/
|
|
954
|
+
static colorScheme: GardState.Facet<"auto" | "dark" | "light", "auto" | "dark" | "light">;
|
|
955
|
+
/**
|
|
956
|
+
Create an extension that loads a set of style rules. Like
|
|
957
|
+
with {@link Wordgard.theme `theme`}, use `&` to indicate the
|
|
958
|
+
place of the editor wrapper element when directly targeting
|
|
959
|
+
that. You can also use `&dark` or `&light` instead to only
|
|
960
|
+
target editors with a dark or light {@link Wordgard.colorScheme
|
|
961
|
+
color scheme}.
|
|
962
|
+
*/
|
|
963
|
+
static styles(spec: Record<string, StyleSpec>): GardState.Extension;
|
|
964
|
+
/**
|
|
965
|
+
Creates a simple theme that sets a height (given in pixels or,
|
|
966
|
+
if a string, a CSS number + unit) and automatic overflow
|
|
967
|
+
scrolling on the editor. (The default styling makes the editor
|
|
968
|
+
height fit its content.)
|
|
969
|
+
*/
|
|
970
|
+
static scrolling(height: number | string): GardState.Extension;
|
|
971
|
+
/**
|
|
972
|
+
Provides a Content Security Policy nonce to use when creating
|
|
973
|
+
the style sheets for the editor. Holds the empty string when no
|
|
974
|
+
nonce has been provided.
|
|
975
|
+
*/
|
|
976
|
+
static cspNonce: GardState.Facet<string, string>;
|
|
977
|
+
/**
|
|
978
|
+
Facet that provides additional DOM attributes for the editor's
|
|
979
|
+
editable DOM element, either directly, or as a function from the
|
|
980
|
+
editor state.
|
|
981
|
+
*/
|
|
982
|
+
static contentAttributes: GardState.Facet<AttrSource, readonly AttrSource[]>;
|
|
983
|
+
/**
|
|
984
|
+
Facet that provides DOM attributes for the editor's outer
|
|
985
|
+
element.
|
|
986
|
+
*/
|
|
987
|
+
static editorAttributes: GardState.Facet<AttrSource, readonly AttrSource[]>;
|
|
988
|
+
/**
|
|
989
|
+
State effect used to include screen reader announcements in a
|
|
990
|
+
transaction. These will be added to the DOM in a visually hidden
|
|
991
|
+
element with `aria-live="polite"` set, and should be used to
|
|
992
|
+
describe effects that are visually obvious but may not be
|
|
993
|
+
noticed by screen reader users (such as moving to the next
|
|
994
|
+
search match).
|
|
995
|
+
*/
|
|
996
|
+
static announce: Transaction.Effect.Type<string>;
|
|
997
|
+
/**
|
|
998
|
+
Facet that allows extensions to indicate that some amount of
|
|
999
|
+
space around the sides of the scrolling element should be
|
|
1000
|
+
considered blocked from view when scrolling something into view.
|
|
1001
|
+
This is only used by plugins that introduce elements that cover
|
|
1002
|
+
part of the editor (for example a gutter).
|
|
1003
|
+
*/
|
|
1004
|
+
static coveredMargins: GardState.Facet<(wg: Wordgard) => Partial<DOMRect> | null, readonly ((wg: Wordgard) => Partial<DOMRect> | null)[]>;
|
|
1005
|
+
}
|
|
1006
|
+
declare namespace Wordgard {
|
|
1007
|
+
/**
|
|
1008
|
+
The type of object given to {@link Wordgard.create}.
|
|
1009
|
+
*/
|
|
1010
|
+
interface Spec extends Partial<GardState.Spec> {
|
|
1011
|
+
/**
|
|
1012
|
+
The editor's initial state. If not given, a new state is
|
|
1013
|
+
created by passing this configuration object to {@link
|
|
1014
|
+
GardState.create}, using its `doc`, `selection`, and
|
|
1015
|
+
`config` fields (if provided).
|
|
1016
|
+
*/
|
|
1017
|
+
state?: GardState;
|
|
1018
|
+
/**
|
|
1019
|
+
When present, the editor is immediately appended to the given
|
|
1020
|
+
element on creation. (Otherwise, you'll have to place the
|
|
1021
|
+
editor {@link Wordgard.dom element} in the document yourself.)
|
|
1022
|
+
*/
|
|
1023
|
+
parent?: Element | DocumentFragment;
|
|
1024
|
+
/**
|
|
1025
|
+
Pass an effect created with {@link Wordgard.scrollIntoView}
|
|
1026
|
+
here to set an initial scroll position.
|
|
1027
|
+
*/
|
|
1028
|
+
scrollTo?: Transaction.Effect<any>;
|
|
1029
|
+
}
|
|
1030
|
+
/**
|
|
1031
|
+
Options passed to {@link Wordgard.scrollIntoView}.
|
|
1032
|
+
*/
|
|
1033
|
+
type ScrollSpec = {
|
|
1034
|
+
/**
|
|
1035
|
+
By default (`"nearest"`) the position will be vertically
|
|
1036
|
+
scrolled only the minimal amount required to move the given
|
|
1037
|
+
position into view. You can set this to `"start"` to move it
|
|
1038
|
+
to the top of the editor, `"end"` to move it to the bottom, or
|
|
1039
|
+
`"center"` to move it to the center.
|
|
1040
|
+
*/
|
|
1041
|
+
y?: "nearest" | "start" | "end" | "center";
|
|
1042
|
+
/**
|
|
1043
|
+
Effect similar to `y`, but for the horizontal scroll position.
|
|
1044
|
+
*/
|
|
1045
|
+
x?: "nearest" | "start" | "end" | "center";
|
|
1046
|
+
/**
|
|
1047
|
+
Extra vertical distance to add when moving something into
|
|
1048
|
+
view. Not used with the `"center"` strategy. Defaults to 5.
|
|
1049
|
+
Must be less than the height of the editor.
|
|
1050
|
+
*/
|
|
1051
|
+
yMargin?: number;
|
|
1052
|
+
/**
|
|
1053
|
+
Extra horizontal distance to add. Not used with the `"center"`
|
|
1054
|
+
strategy. Defaults to 5. Must be less than the width of the
|
|
1055
|
+
editor.
|
|
1056
|
+
*/
|
|
1057
|
+
xMargin?: number;
|
|
1058
|
+
};
|
|
1059
|
+
/**
|
|
1060
|
+
The interface that objects registered with {@link
|
|
1061
|
+
Wordgard.mouseSelectionStyle} must conform to.
|
|
1062
|
+
*/
|
|
1063
|
+
interface MouseSelectionStyle {
|
|
1064
|
+
/**
|
|
1065
|
+
Return a new selection for the mouse gesture that starts with
|
|
1066
|
+
the event that was originally given to the constructor, and ends
|
|
1067
|
+
with the event passed here. In case of a plain click, those may
|
|
1068
|
+
both be the `mousedown` event, in case of a drag gesture, the
|
|
1069
|
+
latest `mousemove` event will be passed.
|
|
1070
|
+
|
|
1071
|
+
When `extend` is true, that means the new selection should, if
|
|
1072
|
+
possible, extend the start selection.
|
|
1073
|
+
*/
|
|
1074
|
+
get: (curEvent: MouseEvent, extend: boolean) => GardSelection;
|
|
1075
|
+
/**
|
|
1076
|
+
Called when the editor is updated while the gesture is in
|
|
1077
|
+
progress. When the document changes, it may be necessary to map
|
|
1078
|
+
some data (like the original selection or start position)
|
|
1079
|
+
through the changes.
|
|
1080
|
+
|
|
1081
|
+
This may return `true` to indicate that the `get` method should
|
|
1082
|
+
get queried again after the update, because something in the
|
|
1083
|
+
update could change its result. Be wary of infinite loops when
|
|
1084
|
+
using this (where `get` returns a new selection, which will
|
|
1085
|
+
trigger `update`, which schedules another `get` in response).
|
|
1086
|
+
*/
|
|
1087
|
+
update: (update: Wordgard.Update) => boolean | void;
|
|
1088
|
+
}
|
|
1089
|
+
/**
|
|
1090
|
+
Log or report an unhandled exception in client code. Should
|
|
1091
|
+
probably only be used by extension code that allows client code to
|
|
1092
|
+
provide functions, and calls those functions in a context where an
|
|
1093
|
+
exception can't be propagated to calling code in a reasonable way
|
|
1094
|
+
(for example when in an event handler).
|
|
1095
|
+
|
|
1096
|
+
Either calls a handler registered with {@link
|
|
1097
|
+
Wordgard.exceptionSink}, `window.onerror`, if defined, or
|
|
1098
|
+
`console.error` (in which case it'll pass `context`, when given,
|
|
1099
|
+
as first argument).
|
|
1100
|
+
*/
|
|
1101
|
+
function logException(state: GardState, exception: any, context?: string): void;
|
|
1102
|
+
/**
|
|
1103
|
+
Plugins associate stateful values with an editor. They can be
|
|
1104
|
+
useful for displaying interface elements, or keeping ephemeral
|
|
1105
|
+
interface state.
|
|
1106
|
+
*/
|
|
1107
|
+
class Plugin<V extends Wordgard.Plugin.Value> {
|
|
1108
|
+
/**
|
|
1109
|
+
Instances of this class act as extensions.
|
|
1110
|
+
*/
|
|
1111
|
+
extension: GardState.Extension;
|
|
1112
|
+
private constructor();
|
|
1113
|
+
/**
|
|
1114
|
+
Define a plugin from a constructor function that creates the
|
|
1115
|
+
plugin's value, given an editor.
|
|
1116
|
+
*/
|
|
1117
|
+
static define<V extends Wordgard.Plugin.Value>(create: (wg: Wordgard) => V, provide?: (plugin: Wordgard.Plugin<V>) => GardState.Extension): Plugin<V>;
|
|
1118
|
+
/**
|
|
1119
|
+
Create a plugin for a class whose constructor takes an editor
|
|
1120
|
+
as only argument.
|
|
1121
|
+
*/
|
|
1122
|
+
static fromClass<V extends Wordgard.Plugin.Value>(cls: {
|
|
1123
|
+
new (wg: Wordgard): V;
|
|
1124
|
+
}, provide?: (plugin: Wordgard.Plugin<V>) => GardState.Extension): Plugin<V>;
|
|
1125
|
+
/**
|
|
1126
|
+
Create an {@link Wordgard.domEventHandler event handler} for this
|
|
1127
|
+
plugin. Usually called from the plugin's `provide` function.
|
|
1128
|
+
*/
|
|
1129
|
+
eventHandler<Event extends keyof HTMLElementEventMap>(event: Event, handler: (event: HTMLElementEventMap[Event], wg: Wordgard, value: V) => boolean | void): GardState.Extension;
|
|
1130
|
+
/**
|
|
1131
|
+
Create an {@link Wordgard.domEventObserver event observer} for this
|
|
1132
|
+
plugin.
|
|
1133
|
+
*/
|
|
1134
|
+
eventObserver<Event extends keyof HTMLElementEventMap>(event: Event, observer: (event: HTMLElementEventMap[Event], wg: Wordgard, value: V) => void): GardState.Extension;
|
|
1135
|
+
}
|
|
1136
|
+
namespace Plugin {
|
|
1137
|
+
/**
|
|
1138
|
+
This is the interface plugin objects must expose.
|
|
1139
|
+
*/
|
|
1140
|
+
interface Value {
|
|
1141
|
+
/**
|
|
1142
|
+
Notifies the plugin of an update that happened in the
|
|
1143
|
+
editor. This is called _before_ the editor updates its own
|
|
1144
|
+
DOM. It is responsible for updating the plugin's internal
|
|
1145
|
+
state (including any state that may be read by plugin
|
|
1146
|
+
fields) and _writing_ to the DOM for the changes in the
|
|
1147
|
+
update. To avoid unnecessary layout recomputations, it
|
|
1148
|
+
should _not_ read the DOM layout—use {@link
|
|
1149
|
+
Wordgard.scheduleDOMRead} to schedule your
|
|
1150
|
+
code in a DOM reading phase if you need to.
|
|
1151
|
+
*/
|
|
1152
|
+
update?(update: Wordgard.Update): void;
|
|
1153
|
+
/**
|
|
1154
|
+
When present, this will be called when an update causes any
|
|
1155
|
+
changes in the DOM representation of the document.
|
|
1156
|
+
*/
|
|
1157
|
+
docUpdate?(wg: Wordgard): void;
|
|
1158
|
+
/**
|
|
1159
|
+
Called when the editor is attached to the DOM. If the plugin
|
|
1160
|
+
needs to allocate any resource that must be released, or modify
|
|
1161
|
+
something outside the editor, it should do it in this method,
|
|
1162
|
+
and make sure to release/undo it in its `disconnect` method.
|
|
1163
|
+
*/
|
|
1164
|
+
connect?(wg: Wordgard): void;
|
|
1165
|
+
/**
|
|
1166
|
+
Called when the editor is removed from the DOM, or the
|
|
1167
|
+
plugin is removed from the editor.
|
|
1168
|
+
*/
|
|
1169
|
+
disconnect?(wg: Wordgard): void;
|
|
1170
|
+
/**
|
|
1171
|
+
Called when the plugin is removed from an editor. This
|
|
1172
|
+
should clean up any changes it made to the editor itself. If
|
|
1173
|
+
the editor was connected to a document, {@link
|
|
1174
|
+
Wordgard.Plugin.Value.disconnect `disconnect`} will be called
|
|
1175
|
+
before this.
|
|
1176
|
+
*/
|
|
1177
|
+
remove?(wg: Wordgard): void;
|
|
1178
|
+
}
|
|
1179
|
+
}
|
|
1180
|
+
/**
|
|
1181
|
+
Editor {@link Wordgard.Plugin plugins} and {@link
|
|
1182
|
+
Wordgard.updateListener update listeners} are given instances of
|
|
1183
|
+
this class whenever the editor is updated.
|
|
1184
|
+
*/
|
|
1185
|
+
class Update {
|
|
1186
|
+
/**
|
|
1187
|
+
The editor that the update is associated with.
|
|
1188
|
+
*/
|
|
1189
|
+
readonly editor: Wordgard;
|
|
1190
|
+
/**
|
|
1191
|
+
The previous editor state.
|
|
1192
|
+
*/
|
|
1193
|
+
readonly startState: GardState;
|
|
1194
|
+
/**
|
|
1195
|
+
The new editor state.
|
|
1196
|
+
*/
|
|
1197
|
+
readonly state: GardState;
|
|
1198
|
+
/**
|
|
1199
|
+
The transactions involved in the update. May be empty.
|
|
1200
|
+
*/
|
|
1201
|
+
readonly transactions: readonly Transaction[];
|
|
1202
|
+
/**
|
|
1203
|
+
The changes made to the document by this update.
|
|
1204
|
+
*/
|
|
1205
|
+
readonly changes: ChangeSet;
|
|
1206
|
+
private constructor();
|
|
1207
|
+
/**
|
|
1208
|
+
Returns true when the document was modified or when the size
|
|
1209
|
+
of the editor, or elements within the editor, changed.
|
|
1210
|
+
*/
|
|
1211
|
+
get geometryChanged(): boolean;
|
|
1212
|
+
/**
|
|
1213
|
+
True when this update indicates a focus change.
|
|
1214
|
+
*/
|
|
1215
|
+
get focusChanged(): boolean;
|
|
1216
|
+
/**
|
|
1217
|
+
Whether the document changed in this update.
|
|
1218
|
+
*/
|
|
1219
|
+
get docChanged(): boolean;
|
|
1220
|
+
/**
|
|
1221
|
+
Whether the selection was explicitly set in this update.
|
|
1222
|
+
*/
|
|
1223
|
+
get selectionSet(): boolean;
|
|
1224
|
+
}
|
|
1225
|
+
}
|
|
1226
|
+
type AttrSource = Record<string, string | null> | ((wg: Wordgard) => Record<string, string | null>);
|
|
1227
|
+
|
|
1228
|
+
/**
|
|
1229
|
+
Key bindings associate keys with functions that should be run when
|
|
1230
|
+
a matching keyboard event happens.
|
|
1231
|
+
|
|
1232
|
+
A key binding can either specify a specific {@link
|
|
1233
|
+
KeyBinding.Spec.char character} to match on, which will be
|
|
1234
|
+
compared against the actual character produced by a key event, or
|
|
1235
|
+
describe a {@link KeyBinding.Spec.key key combination}.
|
|
1236
|
+
|
|
1237
|
+
Bindings for a given key event are evaluated in order of
|
|
1238
|
+
precedence, with each getting a chance to handle the event,
|
|
1239
|
+
stopping when the first handler returns true.
|
|
1240
|
+
|
|
1241
|
+
Key combinations are described by strings like
|
|
1242
|
+
`"Shift-Ctrl-Enter"`—a key identifier prefixed with zero or more
|
|
1243
|
+
modifiers. Key identifiers are based on the strings that can
|
|
1244
|
+
appear in
|
|
1245
|
+
[`KeyEvent.key`](https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/key).
|
|
1246
|
+
Use lowercase letters to refer to letter keys. You can use
|
|
1247
|
+
`"Space"` as an alias for the `" "` name.
|
|
1248
|
+
|
|
1249
|
+
Modifiers can be given in any order. `Shift-` (or `s-`), `Alt-` (or
|
|
1250
|
+
`a-`), `Ctrl-` (or `c-` or `Control-`) and `Cmd-` (or `m-` or
|
|
1251
|
+
`Meta-`) are recognized.
|
|
1252
|
+
|
|
1253
|
+
You can use `Mod-` as a shorthand for `Cmd-` on Mac and `Ctrl-` on
|
|
1254
|
+
other platforms. So `Mod-b` is `Ctrl-b` on Linux but `Cmd-b` on
|
|
1255
|
+
macOS.
|
|
1256
|
+
|
|
1257
|
+
Unlike character bindings, key combination bindings should refer
|
|
1258
|
+
to the unmodified base key that is being pressed, not the
|
|
1259
|
+
character produced by combining that key with Shift or AltGraph.
|
|
1260
|
+
Keyboard mappings that rearrange the positions of Latin characters
|
|
1261
|
+
_are_ taken into account for this (the mapped position is used),
|
|
1262
|
+
but the library tries to 'see through' keyboard mappings that
|
|
1263
|
+
assign non-Latin characters to keys (so that both the Latin and
|
|
1264
|
+
the non-Latin name can be used).
|
|
1265
|
+
*/
|
|
1266
|
+
declare class KeyBinding {
|
|
1267
|
+
/**
|
|
1268
|
+
The configuration object used to define this binding.
|
|
1269
|
+
*/
|
|
1270
|
+
readonly spec: KeyBinding.Spec;
|
|
1271
|
+
/**
|
|
1272
|
+
Bindings count as extensions and can be included in an editor
|
|
1273
|
+
configuration.
|
|
1274
|
+
*/
|
|
1275
|
+
extension: GardState.Extension;
|
|
1276
|
+
private constructor();
|
|
1277
|
+
/**
|
|
1278
|
+
Define a binding.
|
|
1279
|
+
*/
|
|
1280
|
+
static of(spec: KeyBinding.Spec): KeyBinding;
|
|
1281
|
+
}
|
|
1282
|
+
declare namespace KeyBinding {
|
|
1283
|
+
/**
|
|
1284
|
+
A description of a key binding.
|
|
1285
|
+
*/
|
|
1286
|
+
interface Spec {
|
|
1287
|
+
/**
|
|
1288
|
+
A textual character that this binding should trigger for.
|
|
1289
|
+
*/
|
|
1290
|
+
char?: string;
|
|
1291
|
+
/**
|
|
1292
|
+
A key combination to use for this binding. If the
|
|
1293
|
+
platform-specific property (`mac`, `win`, or `linux`) for the
|
|
1294
|
+
current platform is used as well in the binding, that one takes
|
|
1295
|
+
precedence. If `key` isn't defined and the platform-specific
|
|
1296
|
+
binding isn't either, a binding is ignored.
|
|
1297
|
+
*/
|
|
1298
|
+
key?: string;
|
|
1299
|
+
/**
|
|
1300
|
+
Key to use specifically on macOS.
|
|
1301
|
+
*/
|
|
1302
|
+
mac?: string;
|
|
1303
|
+
/**
|
|
1304
|
+
Key to use specifically on Windows.
|
|
1305
|
+
*/
|
|
1306
|
+
win?: string;
|
|
1307
|
+
/**
|
|
1308
|
+
Key to use specifically on Linux.
|
|
1309
|
+
*/
|
|
1310
|
+
linux?: string;
|
|
1311
|
+
/**
|
|
1312
|
+
The command to execute when this binding is triggered.
|
|
1313
|
+
*/
|
|
1314
|
+
run: Command.Bound | Command;
|
|
1315
|
+
/**
|
|
1316
|
+
When given, this defines a second binding, using the (possibly
|
|
1317
|
+
platform-specific) key name, prefixed with `Shift-`, to activate
|
|
1318
|
+
this command.
|
|
1319
|
+
*/
|
|
1320
|
+
shift?: Command.Bound | Command;
|
|
1321
|
+
/**
|
|
1322
|
+
When this property is present, the function is called for every
|
|
1323
|
+
key, and may return true to indicate the key was handled.
|
|
1324
|
+
*/
|
|
1325
|
+
any?: (wg: Wordgard, event: KeyboardEvent) => boolean;
|
|
1326
|
+
/**
|
|
1327
|
+
By default, key bindings apply when focus is on the editor
|
|
1328
|
+
content (the `"editor"` scope). Some extensions, mostly those
|
|
1329
|
+
that define their own panels, might want to allow registering
|
|
1330
|
+
bindings local to that panel. Such bindings should use a custom
|
|
1331
|
+
scope name. You may also assign multiple scope names to a
|
|
1332
|
+
binding, separating them by spaces.
|
|
1333
|
+
*/
|
|
1334
|
+
scope?: string;
|
|
1335
|
+
/**
|
|
1336
|
+
By default, all keys events for which a handler exists have
|
|
1337
|
+
their `preventDefault` called, even if no handler returns
|
|
1338
|
+
true. You can set this to true to disable that behavior.
|
|
1339
|
+
*/
|
|
1340
|
+
allowDefault?: boolean;
|
|
1341
|
+
}
|
|
1342
|
+
/**
|
|
1343
|
+
Run the key handlers registered for a given scope. The event
|
|
1344
|
+
object should be a `"keydown"` event. Returns true if any of the
|
|
1345
|
+
handlers handled it.
|
|
1346
|
+
*/
|
|
1347
|
+
function runScopeHandlers(wg: Wordgard, event: KeyboardEvent, scope: string): boolean;
|
|
1348
|
+
/**
|
|
1349
|
+
Facet used for registering key bindings. Extension precedence
|
|
1350
|
+
determines the order in which bindings that match the same key
|
|
1351
|
+
are called. When a handler has returned `true` for a given key,
|
|
1352
|
+
no further handlers are called.
|
|
1353
|
+
*/
|
|
1354
|
+
const source: GardState.Facet<KeyBinding, readonly KeyBinding[]>;
|
|
1355
|
+
/**
|
|
1356
|
+
By default, the {@link KeyBinding.defaultKeymap default keymap}
|
|
1357
|
+
is automatically active. You can configure this to false if you
|
|
1358
|
+
want to completely replace it.
|
|
1359
|
+
*/
|
|
1360
|
+
const useDefaultKeymap: GardState.Facet<boolean, boolean>;
|
|
1361
|
+
/**
|
|
1362
|
+
The editor's set of default key bindings. Binds the following
|
|
1363
|
+
keys. Most cursor motion bindings include a `Shift-` variant
|
|
1364
|
+
that passes the `extend` flag to the command. Enabled by default
|
|
1365
|
+
unless {@link KeyBinding.useDefaultKeymap} is disabled.
|
|
1366
|
+
|
|
1367
|
+
- `Enter` to {@link command.enter}
|
|
1368
|
+
- `Shift-Enter` to {@link command.insertLineBreak}
|
|
1369
|
+
- `Backspace` to {@link command.deleteUnit} (`"backward"`)
|
|
1370
|
+
- `Delete` to {@link command.deleteUnit} (`"forward"`)
|
|
1371
|
+
- `Ctrl-Backspace` (`Alt-Backspace` on MacOS) to {@link command.deleteWord} (`"backward"`)
|
|
1372
|
+
- `Ctrl-Delete` (`Alt-Delete` on MacOS) to {@link command.deleteWord} (`"forward"`)
|
|
1373
|
+
- `Cmd-Backspace` (MacOS) to {@link command.deleteToLineEnd} (`"backward"`)
|
|
1374
|
+
- `Cmd-Delete` (MacOS) to {@link command.deleteToLineEnd} (`"forward"`)
|
|
1375
|
+
- `ArrowLeft` to {@link command.moveByUnit} (`{dir: "left"}`)
|
|
1376
|
+
- `ArrowRight` to {@link command.moveByUnit} (`{dir: "right"}`)
|
|
1377
|
+
- `ArrowUp` to {@link command.moveByLine} (`{dir: "up"}`)
|
|
1378
|
+
- `ArrowDown` to {@link command.moveByLine} (`{dir: "down"}`)
|
|
1379
|
+
- `Ctrl-AllowLeft` (`Cmd-ArrowLeft` on MacOS) to {@link command.moveByWord} (`{dir: "left"}`)
|
|
1380
|
+
- `Ctrl-AllowRight` (`Cmd-ArrowRight` on MacOS) to {@link command.moveByWord} (`{dir: "right"}`)
|
|
1381
|
+
- `Cmd-ArrowUp` (MacOS) to {@link command.moveToDocSide} (`{side: "start"}`)
|
|
1382
|
+
- `Cmd-ArrowDown` (MacOS) to {@link command.moveToDocSide} (`{side: "end"}`)
|
|
1383
|
+
- `Ctrl-ArrowUp` (MacOS) to {@link command.moveByPage} (`{dir: "up"}`)
|
|
1384
|
+
- `Ctrl-ArrowDown` (MacOS) to {@link command.moveByPage} (`{dir: "down"}`)
|
|
1385
|
+
- `PageUp` to {@link command.moveByPage} (`{dir: "up"}`)
|
|
1386
|
+
- `PageDown` to {@link command.moveByPage} (`{dir: "down"}`)
|
|
1387
|
+
- `Home` to {@link command.moveToLineSide} (`{dir: "backward"}`)
|
|
1388
|
+
- `End` to {@link command.moveToLineSide} (`{dir: "forward"}`)
|
|
1389
|
+
- `Ctrl-Home` (`Cmd-Home` on MacOS) to {@link command.moveToDocSide} (`{side: "start"}`)
|
|
1390
|
+
- `Ctrl-End` (`Cmd-End` on MacOS) to {@link command.moveToDocSide} (`{side: "end"}`)
|
|
1391
|
+
- `Ctrl-a` (`Cmd-a` on MacOS) to {@link command.selectAll}
|
|
1392
|
+
- `Ctrl-z` (`Cmd-z` on MacOS) to {@link command.undo}
|
|
1393
|
+
- `Ctrl-y` (`Shift-Cmd-z` on MacOS) to {@link command.redo}
|
|
1394
|
+
|
|
1395
|
+
On MacOS, the following Emacs-style bindings are available:
|
|
1396
|
+
|
|
1397
|
+
- `Ctrl-b` to {@link command.moveByUnit} (`{dir: "backward"}`)
|
|
1398
|
+
- `Ctrl-f` to {@link command.moveByUnit} (`{dir: "forward"}`)
|
|
1399
|
+
- `Ctrl-p` to {@link command.moveByLine} (`{dir: "up"}`)
|
|
1400
|
+
- `Ctrl-n` to {@link command.moveByLine} (`{dir: "down"}`)
|
|
1401
|
+
- `Ctrl-a` to {@link command.moveToTextblockSide} (`{dir: "backward"}`)
|
|
1402
|
+
- `Ctrl-e` to {@link command.moveToTextblockSide} (`{dir: "forward"}`)
|
|
1403
|
+
- `Ctrl-d` to {@link command.deleteUnit} (`"forward"`)
|
|
1404
|
+
- `Ctrl-h` to {@link command.deleteUnit} (`"backward"`)
|
|
1405
|
+
- `Ctrl-k` to {@link command.deleteToLineEnd} (`"forward"`)
|
|
1406
|
+
- `Ctrl-Alt-h` to {@link command.deleteWord} (`"backward"`)
|
|
1407
|
+
- `Ctrl-o` to {@link command.insertLineBreak}
|
|
1408
|
+
- `Ctrl-t` to {@link command.transposeChars}
|
|
1409
|
+
- `Ctrl-v` to {@link command.moveByPage} (`{dir: "down"}`)
|
|
1410
|
+
*/
|
|
1411
|
+
const defaultKeymap: readonly KeyBinding[];
|
|
1412
|
+
}
|
|
1413
|
+
|
|
1414
|
+
type PanelConfig = {
|
|
1415
|
+
/**
|
|
1416
|
+
By default, panels will be placed inside the editor's DOM
|
|
1417
|
+
structure. You can use this option to override where panels with
|
|
1418
|
+
`top: true` are placed.
|
|
1419
|
+
*/
|
|
1420
|
+
topContainer?: HTMLElement;
|
|
1421
|
+
/**
|
|
1422
|
+
Override where panels with `top: false` are placed.
|
|
1423
|
+
*/
|
|
1424
|
+
bottomContainer?: HTMLElement;
|
|
1425
|
+
};
|
|
1426
|
+
/**
|
|
1427
|
+
Object that describes an active panel.
|
|
1428
|
+
*/
|
|
1429
|
+
interface Panel {
|
|
1430
|
+
/**
|
|
1431
|
+
The element representing this panel. The library will add the
|
|
1432
|
+
`"wg-panel"` DOM class to this.
|
|
1433
|
+
*/
|
|
1434
|
+
dom: HTMLElement;
|
|
1435
|
+
/**
|
|
1436
|
+
Controls whether the panel should be at the top or bottom of the
|
|
1437
|
+
editor. Defaults to false.
|
|
1438
|
+
*/
|
|
1439
|
+
top?: boolean;
|
|
1440
|
+
/**
|
|
1441
|
+
Update the panel DOM for a given editor update.
|
|
1442
|
+
*/
|
|
1443
|
+
update?(update: Wordgard.Update): void;
|
|
1444
|
+
/**
|
|
1445
|
+
Called, when present, when the panel has been added the DOM.
|
|
1446
|
+
*/
|
|
1447
|
+
connect?(wg: Wordgard): void;
|
|
1448
|
+
/**
|
|
1449
|
+
Called when the editor with the panel is disconnected from the
|
|
1450
|
+
DOM, or the panel is removed from an editor.
|
|
1451
|
+
*/
|
|
1452
|
+
disconnect?(wg: Wordgard): void;
|
|
1453
|
+
/**
|
|
1454
|
+
Called when the panel is removed from the editor.
|
|
1455
|
+
*/
|
|
1456
|
+
remove?(wg: Wordgard): void;
|
|
1457
|
+
}
|
|
1458
|
+
declare namespace Panel {
|
|
1459
|
+
/**
|
|
1460
|
+
A function that initializes a panel. Used in {@link Panel.show}.
|
|
1461
|
+
*/
|
|
1462
|
+
type Constructor = (wg: Wordgard) => Panel;
|
|
1463
|
+
/**
|
|
1464
|
+
Opening a panel is done by providing a constructor function for
|
|
1465
|
+
the panel through this facet. (The panel is closed again when its
|
|
1466
|
+
constructor is no longer provided.) Values of `null` are ignored.
|
|
1467
|
+
*/
|
|
1468
|
+
const show: GardState.Facet<Constructor | null, readonly (Constructor | null)[]>;
|
|
1469
|
+
/**
|
|
1470
|
+
Get the active panel created by the given constructor, if any.
|
|
1471
|
+
This can be useful when you need access to your panels' DOM
|
|
1472
|
+
structure.
|
|
1473
|
+
*/
|
|
1474
|
+
function get<T extends Panel>(wg: Wordgard, constructor: (wg: Wordgard) => T): T | null;
|
|
1475
|
+
/**
|
|
1476
|
+
Configures the panel-managing extension.
|
|
1477
|
+
*/
|
|
1478
|
+
function configure(config?: PanelConfig): GardState.Extension;
|
|
1479
|
+
}
|
|
1480
|
+
|
|
1481
|
+
/**
|
|
1482
|
+
Provides a menu bar that displays menu items defined via the
|
|
1483
|
+
{@link command.Menu menu system} in a button bar at the top of the
|
|
1484
|
+
editor. The same menu items can be used by custom menu
|
|
1485
|
+
implementations, but this extension provides a solid default menu
|
|
1486
|
+
style.
|
|
1487
|
+
*/
|
|
1488
|
+
declare function menuBar(config?: {
|
|
1489
|
+
template?: Menu.Template | readonly Menu.Template[];
|
|
1490
|
+
}): GardState.Extension;
|
|
1491
|
+
|
|
1492
|
+
/**
|
|
1493
|
+
Dialogs are {@link Panel panels} opened as a side-effect, and
|
|
1494
|
+
closed by user action. This interface is used to describe them.
|
|
1495
|
+
*/
|
|
1496
|
+
interface Dialog {
|
|
1497
|
+
/**
|
|
1498
|
+
A function to render the content of the dialog. The result
|
|
1499
|
+
should contain at least one `<form>` element. Submit handlers
|
|
1500
|
+
and a handler for the Escape key will be added to the form.
|
|
1501
|
+
|
|
1502
|
+
If this is not given, the `label`, `input`, and `submitLabel`
|
|
1503
|
+
fields will be used to create a simple form for you.
|
|
1504
|
+
*/
|
|
1505
|
+
content?: (wg: Wordgard, close: () => void) => Element;
|
|
1506
|
+
/**
|
|
1507
|
+
When `content` isn't given, this provides the text shown in the
|
|
1508
|
+
dialog.
|
|
1509
|
+
*/
|
|
1510
|
+
label?: string;
|
|
1511
|
+
/**
|
|
1512
|
+
The attributes for an input element shown next to the label. If
|
|
1513
|
+
not given, no input element is added.
|
|
1514
|
+
*/
|
|
1515
|
+
input?: {
|
|
1516
|
+
[attr: string]: string;
|
|
1517
|
+
};
|
|
1518
|
+
/**
|
|
1519
|
+
The label for the button that submits the form. Defaults to
|
|
1520
|
+
`"OK"`.
|
|
1521
|
+
*/
|
|
1522
|
+
submitLabel?: string;
|
|
1523
|
+
/**
|
|
1524
|
+
Extra classes to add to the panel.
|
|
1525
|
+
*/
|
|
1526
|
+
class?: string;
|
|
1527
|
+
/**
|
|
1528
|
+
A query selector to find the field that should be focused when
|
|
1529
|
+
the dialog is opened. When set to true, this picks the first
|
|
1530
|
+
`<input>` or `<button>` element in the form. When set to
|
|
1531
|
+
`false`, focus is not moved into the dialog.
|
|
1532
|
+
*/
|
|
1533
|
+
focus?: string | boolean;
|
|
1534
|
+
/**
|
|
1535
|
+
By default, dialogs are shown above the editor. Set this to
|
|
1536
|
+
`false` to have it show up at the bottom.
|
|
1537
|
+
*/
|
|
1538
|
+
top?: boolean;
|
|
1539
|
+
}
|
|
1540
|
+
declare namespace Dialog {
|
|
1541
|
+
/**
|
|
1542
|
+
Show a dialog to display a message or prompt the user for input.
|
|
1543
|
+
Returns an effect that can be dispatched to close the dialog,
|
|
1544
|
+
and a promise that resolves when the dialog is closed or a form
|
|
1545
|
+
inside of it is submitted.
|
|
1546
|
+
|
|
1547
|
+
You are encouraged, if your handling of the result of the promise
|
|
1548
|
+
dispatches a transaction, to include the `close` effect in it. If
|
|
1549
|
+
you don't, this function will automatically dispatch a separate
|
|
1550
|
+
transaction right after.
|
|
1551
|
+
*/
|
|
1552
|
+
function show(wg: Wordgard, config: Dialog): {
|
|
1553
|
+
close: Transaction.Effect<unknown>;
|
|
1554
|
+
result: Promise<HTMLFormElement | null>;
|
|
1555
|
+
};
|
|
1556
|
+
/**
|
|
1557
|
+
Find the {@link Panel} for an open dialog, using a class name as
|
|
1558
|
+
identifier.
|
|
1559
|
+
*/
|
|
1560
|
+
function get(wg: Wordgard, className: string): Panel | null;
|
|
1561
|
+
/**
|
|
1562
|
+
Close the {@link Panel} for an open dialog, by class name.
|
|
1563
|
+
*/
|
|
1564
|
+
function close(wg: Wordgard, className: string): boolean;
|
|
1565
|
+
}
|
|
1566
|
+
|
|
1567
|
+
/**
|
|
1568
|
+
Describes a tooltip. Values of this type, when provided through
|
|
1569
|
+
the {@link Tooltip.show} facet, provide the active tooltips on an
|
|
1570
|
+
editor.
|
|
1571
|
+
*/
|
|
1572
|
+
interface Tooltip {
|
|
1573
|
+
/**
|
|
1574
|
+
The document position at which to show the tooltip.
|
|
1575
|
+
*/
|
|
1576
|
+
pos: number;
|
|
1577
|
+
/**
|
|
1578
|
+
The end of the range annotated by this tooltip, if different
|
|
1579
|
+
from `pos`.
|
|
1580
|
+
*/
|
|
1581
|
+
end?: number;
|
|
1582
|
+
/**
|
|
1583
|
+
A constructor function that creates the tooltip's {@link
|
|
1584
|
+
Tooltip.View DOM representation}.
|
|
1585
|
+
*/
|
|
1586
|
+
create(wg: Wordgard): Tooltip.View;
|
|
1587
|
+
/**
|
|
1588
|
+
Whether the tooltip should be shown above or below the target
|
|
1589
|
+
position. Not guaranteed to be respected for hover tooltips
|
|
1590
|
+
since all hover tooltips for the same range are always
|
|
1591
|
+
positioned together. Defaults to false.
|
|
1592
|
+
*/
|
|
1593
|
+
above?: boolean;
|
|
1594
|
+
/**
|
|
1595
|
+
Whether the `above` option should be honored when there isn't
|
|
1596
|
+
enough space on that side to show the tooltip inside the
|
|
1597
|
+
viewport. Defaults to false.
|
|
1598
|
+
*/
|
|
1599
|
+
strictSide?: boolean;
|
|
1600
|
+
/**
|
|
1601
|
+
When set to true, show a triangle connecting the tooltip element
|
|
1602
|
+
to position `pos`.
|
|
1603
|
+
*/
|
|
1604
|
+
arrow?: boolean;
|
|
1605
|
+
/**
|
|
1606
|
+
By default, tooltips are hidden when their position is outside
|
|
1607
|
+
of the visible editor content. Set this to false to turn that
|
|
1608
|
+
off.
|
|
1609
|
+
*/
|
|
1610
|
+
clip?: boolean;
|
|
1611
|
+
}
|
|
1612
|
+
declare namespace Tooltip {
|
|
1613
|
+
/**
|
|
1614
|
+
Creates an extension that configures tooltip behavior.
|
|
1615
|
+
*/
|
|
1616
|
+
function configure(config?: {
|
|
1617
|
+
/**
|
|
1618
|
+
By default, tooltips use `"fixed"`
|
|
1619
|
+
[positioning](https://developer.mozilla.org/en-US/docs/Web/CSS/position),
|
|
1620
|
+
which has the advantage that tooltips don't get cut off by
|
|
1621
|
+
scrollable parent elements. However, CSS rules like `contain:
|
|
1622
|
+
layout` can break fixed positioning in child nodes, which can be
|
|
1623
|
+
worked about by using `"absolute"` here.
|
|
1624
|
+
|
|
1625
|
+
On iOS, which at the time of writing still doesn't properly
|
|
1626
|
+
support fixed positioning, the library always uses absolute
|
|
1627
|
+
positioning.
|
|
1628
|
+
|
|
1629
|
+
If the tooltip parent element sits in a transformed element, the
|
|
1630
|
+
library also falls back to absolute positioning.
|
|
1631
|
+
*/
|
|
1632
|
+
position?: "fixed" | "absolute";
|
|
1633
|
+
/**
|
|
1634
|
+
The element to put the tooltips into. By default, they are put
|
|
1635
|
+
in the editor (`<wordgard-editor>`) element, and that is
|
|
1636
|
+
usually what you want. But in some layouts that can lead to
|
|
1637
|
+
positioning issues, and you need to use a different parent to
|
|
1638
|
+
work around those.
|
|
1639
|
+
*/
|
|
1640
|
+
parent?: HTMLElement;
|
|
1641
|
+
/**
|
|
1642
|
+
By default, when figuring out whether there is room for a
|
|
1643
|
+
tooltip at a given position, the extension considers the entire
|
|
1644
|
+
space between 0,0 and
|
|
1645
|
+
`documentElement.clientWidth`/`clientHeight` to be available for
|
|
1646
|
+
showing tooltips. You can provide a function here that returns
|
|
1647
|
+
an alternative rectangle.
|
|
1648
|
+
*/
|
|
1649
|
+
tooltipSpace?: (wg: Wordgard) => DOMRect;
|
|
1650
|
+
}): GardState.Extension;
|
|
1651
|
+
/**
|
|
1652
|
+
Describes the way a tooltip is displayed.
|
|
1653
|
+
*/
|
|
1654
|
+
interface View {
|
|
1655
|
+
/**
|
|
1656
|
+
The DOM element to position over the editor.
|
|
1657
|
+
*/
|
|
1658
|
+
dom: HTMLElement;
|
|
1659
|
+
/**
|
|
1660
|
+
Adjust the position of the tooltip relative to its anchor
|
|
1661
|
+
position. A positive `x` value will move the tooltip
|
|
1662
|
+
horizontally along with the text direction (so right in
|
|
1663
|
+
left-to-right context, left in right-to-left). A positive `y`
|
|
1664
|
+
will move the tooltip up when it is above its anchor, and down
|
|
1665
|
+
otherwise.
|
|
1666
|
+
*/
|
|
1667
|
+
offset?: {
|
|
1668
|
+
x: number;
|
|
1669
|
+
y: number;
|
|
1670
|
+
};
|
|
1671
|
+
/**
|
|
1672
|
+
By default, a tooltip's screen position will be based on the
|
|
1673
|
+
document position of its `pos` property. This method can be
|
|
1674
|
+
provided to make the tooltip view itself responsible for finding
|
|
1675
|
+
its screen position.
|
|
1676
|
+
*/
|
|
1677
|
+
getCoords?: (pos: number) => DOMRect;
|
|
1678
|
+
/**
|
|
1679
|
+
By default, tooltips are moved when they overlap with other
|
|
1680
|
+
tooltips. Set this to `true` to disable that behavior for this
|
|
1681
|
+
tooltip.
|
|
1682
|
+
*/
|
|
1683
|
+
overlap?: boolean;
|
|
1684
|
+
/**
|
|
1685
|
+
Update the DOM element for a change in the view's state.
|
|
1686
|
+
*/
|
|
1687
|
+
update?(update: Wordgard.Update): void;
|
|
1688
|
+
/**
|
|
1689
|
+
Called when the tooltip is added to a DOM-connected editor.
|
|
1690
|
+
*/
|
|
1691
|
+
connect?(wg: Wordgard): void;
|
|
1692
|
+
/**
|
|
1693
|
+
Called when the editor containing the tooltip is disconnected,
|
|
1694
|
+
or before the tooltip is removed.
|
|
1695
|
+
*/
|
|
1696
|
+
disconnect?(wg: Wordgard): void;
|
|
1697
|
+
/**
|
|
1698
|
+
Called when the tooltip is removed from the editor.
|
|
1699
|
+
*/
|
|
1700
|
+
remove?(wg: Wordgard): void;
|
|
1701
|
+
/**
|
|
1702
|
+
Called when the tooltip has been (re)positioned. The argument
|
|
1703
|
+
is the {@link Tooltip.configure.config.tooltipSpace space}
|
|
1704
|
+
available to the tooltip.
|
|
1705
|
+
*/
|
|
1706
|
+
positioned?(space: DOMRect): void;
|
|
1707
|
+
/**
|
|
1708
|
+
By default, the library will restrict the size of tooltips so
|
|
1709
|
+
that they don't stick out of the available space. Set this to
|
|
1710
|
+
false to disable that.
|
|
1711
|
+
*/
|
|
1712
|
+
resize?: boolean;
|
|
1713
|
+
}
|
|
1714
|
+
/**
|
|
1715
|
+
Facet to which an extension can add a value to show a tooltip.
|
|
1716
|
+
*/
|
|
1717
|
+
const show: GardState.Facet<Tooltip | null, readonly (Tooltip | null)[]>;
|
|
1718
|
+
/**
|
|
1719
|
+
Get the active tooltip view for a given tooltip or tooltip
|
|
1720
|
+
constructor, if available.
|
|
1721
|
+
*/
|
|
1722
|
+
function get<T extends Tooltip>(wg: Wordgard, tooltip: T): ReturnType<T["create"]> | null;
|
|
1723
|
+
function get<T extends Tooltip.View>(wg: Wordgard, create: (wg: Wordgard) => T): T | null;
|
|
1724
|
+
/**
|
|
1725
|
+
Tell the tooltip extension to recompute the position of the active
|
|
1726
|
+
tooltips. This can be useful when something happens (such as a
|
|
1727
|
+
re-positioning or CSS change affecting the editor) that could
|
|
1728
|
+
invalidate the existing tooltip positions but isn't detected by
|
|
1729
|
+
the extension.
|
|
1730
|
+
*/
|
|
1731
|
+
function reposition(wg: Wordgard): void;
|
|
1732
|
+
/**
|
|
1733
|
+
Set up a hover tooltip, which shows up when the pointer hovers
|
|
1734
|
+
over ranges of text. The callback is called when the mouse hovers
|
|
1735
|
+
over the document text. It should, if there is a tooltip
|
|
1736
|
+
associated with position `pos`, return the tooltip description
|
|
1737
|
+
(either directly or in a promise). The `side` argument indicates
|
|
1738
|
+
on which side of the position the pointer is—it will be -1 if the
|
|
1739
|
+
pointer is before the position, 1 if after the position.
|
|
1740
|
+
|
|
1741
|
+
Note that all hover tooltips are hosted within a single tooltip
|
|
1742
|
+
container element. This allows multiple tooltips over the same
|
|
1743
|
+
range to be "merged" together without overlapping.
|
|
1744
|
+
|
|
1745
|
+
Returns an {@link GardState.Extension editor extension} that
|
|
1746
|
+
installs the hover behavior and a state field that can be used
|
|
1747
|
+
to read the currently active tooltips produced by this
|
|
1748
|
+
extension.
|
|
1749
|
+
*/
|
|
1750
|
+
function hover(source: HoverTooltipSource, options?: hover.Spec): {
|
|
1751
|
+
extension: GardState.Extension;
|
|
1752
|
+
active: GardState.Field<readonly Tooltip[]>;
|
|
1753
|
+
};
|
|
1754
|
+
namespace hover {
|
|
1755
|
+
/**
|
|
1756
|
+
Options given to {@link Tooltip.hover}.
|
|
1757
|
+
*/
|
|
1758
|
+
type Spec = {
|
|
1759
|
+
/**
|
|
1760
|
+
Controls whether a transaction hides the tooltip. The default
|
|
1761
|
+
is to not hide.
|
|
1762
|
+
*/
|
|
1763
|
+
hideOn?: (tr: Transaction, tooltip: Tooltip) => boolean;
|
|
1764
|
+
/**
|
|
1765
|
+
When enabled (this defaults to false), close the tooltip
|
|
1766
|
+
whenever the document changes or the selection is set.
|
|
1767
|
+
*/
|
|
1768
|
+
hideOnChange?: boolean | "touch";
|
|
1769
|
+
/**
|
|
1770
|
+
Hover time after which the tooltip should appear, in
|
|
1771
|
+
milliseconds. Defaults to 300ms.
|
|
1772
|
+
*/
|
|
1773
|
+
hoverTime?: number;
|
|
1774
|
+
};
|
|
1775
|
+
/**
|
|
1776
|
+
Returns true if any hover tooltips are currently active.
|
|
1777
|
+
*/
|
|
1778
|
+
function has(state: GardState): boolean;
|
|
1779
|
+
/**
|
|
1780
|
+
Transaction effect that closes all hover tooltips.
|
|
1781
|
+
*/
|
|
1782
|
+
const closeAll: Transaction.Effect<null>;
|
|
1783
|
+
}
|
|
1784
|
+
}
|
|
1785
|
+
/**
|
|
1786
|
+
The type of function that can be used as a {@hoverTooltip.source
|
|
1787
|
+
hover tooltip source}.
|
|
1788
|
+
*/
|
|
1789
|
+
type HoverTooltipSource = (wg: Wordgard, pos: number, side: -1 | 1) => Tooltip | readonly Tooltip[] | null | Promise<Tooltip | readonly Tooltip[] | null>;
|
|
1790
|
+
|
|
1791
|
+
/**
|
|
1792
|
+
Objects of this type represent input rules.
|
|
1793
|
+
*/
|
|
1794
|
+
declare class InputRule {
|
|
1795
|
+
/**
|
|
1796
|
+
Rules can be added to a configuration as extension values.
|
|
1797
|
+
*/
|
|
1798
|
+
extension: GardState.Extension;
|
|
1799
|
+
private constructor();
|
|
1800
|
+
/**
|
|
1801
|
+
Define an input rule.
|
|
1802
|
+
*/
|
|
1803
|
+
static define(spec: InputRule.Spec): InputRule;
|
|
1804
|
+
/**
|
|
1805
|
+
Build an input rule for automatically wrapping a textblock when
|
|
1806
|
+
a given string is typed. You'll probably want the regexp to
|
|
1807
|
+
start with `^`, so that the pattern can only occur at the start
|
|
1808
|
+
of a textblock. `tag` gives the type of plot to wrap in.
|
|
1809
|
+
|
|
1810
|
+
When `empty` is given as `true`, the rule only applies when the
|
|
1811
|
+
expression matches the textblock's entire content.
|
|
1812
|
+
*/
|
|
1813
|
+
static wrapping(expr: RegExp, tag: Plot.Tag | ((match: InputRule.MatchArray) => Plot.Tag), empty?: boolean): InputRule;
|
|
1814
|
+
/**
|
|
1815
|
+
Build an input rule that changes the type of a textblock when the
|
|
1816
|
+
matched text is typed into it. You'll usually want to start your
|
|
1817
|
+
regexp with `^` so that it is only matched at the start of a
|
|
1818
|
+
textblock. The optional `getAttrs` parameter can be used to compute
|
|
1819
|
+
the new node's attributes, and works the same as in the
|
|
1820
|
+
`InputRule.wrapping` function.
|
|
1821
|
+
*/
|
|
1822
|
+
static textblockType(expr: RegExp, tag: Plot.Tag | ((match: InputRule.MatchArray) => Plot.Tag), empty?: boolean): InputRule;
|
|
1823
|
+
}
|
|
1824
|
+
declare namespace InputRule {
|
|
1825
|
+
/**
|
|
1826
|
+
Configuration given to {@link InputRule.define}.
|
|
1827
|
+
*/
|
|
1828
|
+
interface Spec {
|
|
1829
|
+
/**
|
|
1830
|
+
The regular expression to match against the text before the
|
|
1831
|
+
input. This expression should end in a `$` marker.
|
|
1832
|
+
*/
|
|
1833
|
+
expr: RegExp;
|
|
1834
|
+
/**
|
|
1835
|
+
Handler to call when this rule matches. `match` will contain
|
|
1836
|
+
the document positions of the full match and all matched
|
|
1837
|
+
groups in `expr`. Should return `true` when it has taken an
|
|
1838
|
+
action, `false` when it didn't. You probably want to include
|
|
1839
|
+
{@link history.history.isolate}`.of(true)` in any
|
|
1840
|
+
transactions you dispatch from a rule handler, so that users
|
|
1841
|
+
can undo the adjustment if it wasn't what they wanted.
|
|
1842
|
+
|
|
1843
|
+
When given as a string, the full match will be replaced by
|
|
1844
|
+
that string.
|
|
1845
|
+
*/
|
|
1846
|
+
apply: ((state: GardState, match: InputRule.MatchArray) => Transaction.Spec | null) | string;
|
|
1847
|
+
/**
|
|
1848
|
+
Because the regular expression given in `expr` must end at the
|
|
1849
|
+
cursor, it is matched against a string that stops at the
|
|
1850
|
+
cursor, and cannot look beyond it. You can provide an
|
|
1851
|
+
additional expression here (which should start with `^`) to
|
|
1852
|
+
enforce a lookahead condition.
|
|
1853
|
+
*/
|
|
1854
|
+
lookahead?: RegExp;
|
|
1855
|
+
/**
|
|
1856
|
+
By default, input rules don't apply inside nodes with the
|
|
1857
|
+
{@link Node.Role.Code `Code` role}. Set this to `true` to
|
|
1858
|
+
allow matches in code.
|
|
1859
|
+
*/
|
|
1860
|
+
inCode?: boolean;
|
|
1861
|
+
}
|
|
1862
|
+
/**
|
|
1863
|
+
An object representing a matched group for an input rule. Holds
|
|
1864
|
+
the start and end positions of the group in the document, along
|
|
1865
|
+
with the matched text content.
|
|
1866
|
+
*/
|
|
1867
|
+
type Match = {
|
|
1868
|
+
from: Pos;
|
|
1869
|
+
to: Pos;
|
|
1870
|
+
text: string;
|
|
1871
|
+
};
|
|
1872
|
+
/**
|
|
1873
|
+
An array of {@link InputRule.Match matches}.
|
|
1874
|
+
*/
|
|
1875
|
+
type MatchArray = readonly (InputRule.Match | null)[] & {
|
|
1876
|
+
0: InputRule.Match;
|
|
1877
|
+
};
|
|
1878
|
+
/**
|
|
1879
|
+
Input rule that converts double dashes to an emdash.
|
|
1880
|
+
*/
|
|
1881
|
+
const emDash: InputRule;
|
|
1882
|
+
/**
|
|
1883
|
+
Rule that converts three dots to an ellipsis character.
|
|
1884
|
+
*/
|
|
1885
|
+
const ellipsis: InputRule;
|
|
1886
|
+
/**
|
|
1887
|
+
“Smart” opening double quotes.
|
|
1888
|
+
*/
|
|
1889
|
+
const openDoubleQuote: InputRule;
|
|
1890
|
+
/**
|
|
1891
|
+
“Smart” closing double quotes.
|
|
1892
|
+
*/
|
|
1893
|
+
const closeDoubleQuote: InputRule;
|
|
1894
|
+
/**
|
|
1895
|
+
‘Smart’ opening single quotes.
|
|
1896
|
+
*/
|
|
1897
|
+
const openSingleQuote: InputRule;
|
|
1898
|
+
/**
|
|
1899
|
+
‘Smart’ closing single quotes.
|
|
1900
|
+
*/
|
|
1901
|
+
const closeSingleQuote: InputRule;
|
|
1902
|
+
/**
|
|
1903
|
+
Smart-quote related input rules.
|
|
1904
|
+
*/
|
|
1905
|
+
const smartQuotes: readonly InputRule[];
|
|
1906
|
+
}
|
|
1907
|
+
|
|
1908
|
+
/**
|
|
1909
|
+
Extension that enables a placeholder—a piece of example content
|
|
1910
|
+
to show when the editor is empty.
|
|
1911
|
+
*/
|
|
1912
|
+
declare function placeholder(content: string | (() => Element)): GardState.Extension;
|
|
1913
|
+
|
|
1914
|
+
/**
|
|
1915
|
+
Draws a cursor at the current drop position when something is
|
|
1916
|
+
being dragged over the editor.
|
|
1917
|
+
*/
|
|
1918
|
+
declare function dropCursor(): GardState.Extension;
|
|
1919
|
+
|
|
1920
|
+
export { Decoration, Dialog, InputRule, KeyBinding, Panel, PointSet, RangeSet, Tooltip, Widget, Wordgard, dropCursor, menuBar, placeholder };
|