wysimark-lite 0.9.0

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.
@@ -0,0 +1,1038 @@
1
+ import react from 'react';
2
+ import * as slate from 'slate';
3
+ import { Element as Element$1, BaseEditor, NodeEntry, BaseRange, Location, Editor, Descendant, Path, BaseText } from 'slate';
4
+ import { Client } from '@portive/client';
5
+ import { SetReturnType, SetOptional, UnionToIntersection, Simplify, RequireExactlyOne } from 'type-fest';
6
+ import * as zustand from 'zustand';
7
+ import { HistoryEditor } from 'slate-history';
8
+ import { ReactEditor, Editable } from 'slate-react';
9
+ import { RenderElementProps, RenderLeafProps, RenderPlaceholderProps, EditableProps } from 'slate-react/dist/components/editable';
10
+
11
+ /**
12
+ * SinkEditor just adds a `sink` object where we drop all of our sink
13
+ * related data on.
14
+ */
15
+ type SinkEditor = {
16
+ /**
17
+ * a master Element is one that has one or more elements that are depedant
18
+ * on it. For example, a `table` Element. For clarity, a `table-row` Element
19
+ * is not considered a master Element. Only the top-most element is.
20
+ *
21
+ * One use for identify a master is for adding a block quote. We want the
22
+ * block quote to always surround the master Element. A block-quote that
23
+ * surrounded a table-row, for example, would not make sense.
24
+ */
25
+ isMaster: (node: Element$1) => boolean;
26
+ /**
27
+ * a slave Element is one that is dependant on another Element. For example,
28
+ * `table-row`, `table-cell` and `table-cotent` elements are all considered
29
+ * slave elements.
30
+ *
31
+ * At the time of writing, I haven't figured out a use case for a slave
32
+ * element actually...
33
+ */
34
+ isSlave: (node: Element$1) => boolean;
35
+ isStandalone: (node: Element$1) => boolean;
36
+ sink: {
37
+ plugins: BasePluginPolicy[];
38
+ };
39
+ };
40
+ type FullSinkEditor = SinkEditor & BaseEditor & ReactEditor & HistoryEditor;
41
+
42
+ /**
43
+ * On the editor, there are several methods that return void that are used to
44
+ * override default editor behaviors.
45
+ *
46
+ * These are referred to as Overrideable core actions in the docs.
47
+ *
48
+ * - deleteBackward
49
+ * - deleteForward
50
+ * - deleteFragment
51
+ * - insertBreak
52
+ * - insertFragment
53
+ * - insertNode
54
+ * - insertText
55
+ * - normalizeNode
56
+ *
57
+ * When there are plugins, Sink tries to find a plugin to handle the event and
58
+ * if it cannot, uses the previously defined handler. For example, the user may
59
+ * have specified `editor.insertBreak` on the `editor` earlier and that will
60
+ * be called after all the plugins have been searched.
61
+ *
62
+ * We search through the plugins from the first to the last plugin.
63
+ *
64
+ * In a plugin, we specify the functions like we don on the editor but the
65
+ * return value informs us how the plugin should proceed after. The return
66
+ * value generally indicates whether the plugin has handled the event with one
67
+ * special case:
68
+ *
69
+ * - `true`: If the return type is `true` then the plugin has indicated it has
70
+ * handled the event and no further processing is required. The handlers in
71
+ * all remaining plugins are skipped.
72
+ *
73
+ * - `false`: If the return type is `false` then the plugin has indicated it has
74
+ * not handled the event and will continue through the rest of the plugins
75
+ * looking for a plugin to handle the event.
76
+ *
77
+ * - `() => void`: If the return tyep is a function, the plugin has indicated
78
+ * it has not handled the event, but that it would like to register another
79
+ * function that should execute after the actual event handler has been
80
+ * executed. In particular, this is used when in certain situations we may
81
+ * want a normalizer to execute after the event handler has triggered. This
82
+ * is used in the `normalize-after-delete-plugin` for example.
83
+ *
84
+ * NOTE:
85
+ *
86
+ * This seems like an unusual specification at first glance and a purist might
87
+ * argue, this could be handled more succinctly with a `next` function passed
88
+ * in as the final argument.
89
+ *
90
+ * Here's why I elected to go this route but it boils down to the fact that
91
+ * `next` functions make the function difficult to reason about.
92
+ *
93
+ * - 99% of the true, we want to indicate whether we handled the function or
94
+ * not and for that use case, true/false is simple to understand and natural.
95
+ * In the case where we need something to happen after, returning a function
96
+ * is unusual, but still easy to reason about. Also, the exclusivity of
97
+ * the function return is nice in that it assumes that the event wasn't
98
+ * handled, and of course, the function return would only ever be used if the
99
+ * function indeed wasn't handled. For if it was handled, there would be no
100
+ * need to have the after function because that could just be in the original
101
+ * function handler.
102
+ *
103
+ * - To use this, you have to build nested contexts that are always hard to
104
+ * reason about because you are passing a set of contexts from inner child
105
+ * to outer parent. This created difficult to comprehend complexity in the
106
+ * old Slate plugins architecture and is probably why it was abandoned.
107
+ *
108
+ * - It's also harder to type properly and to reason about it. The argument
109
+ * list changes in length depending on the function; furthermore, in some
110
+ * cases it is natural to ignore the arguments but we'd have to accept blank
111
+ * arguments that are unused to access the `next` function.
112
+ *
113
+ * - It's hard to debug. The plugin system as it currently is designed to
114
+ * execute linearly, instead of in a nested fashion. This makes it easy to
115
+ * add debug code, and know what happens before and after each step.
116
+ */
117
+ type VoidActionReturn = boolean | (() => void);
118
+
119
+ type RenderEditableProps = {
120
+ attributes: EditableProps;
121
+ Editable: typeof Editable;
122
+ };
123
+ type RenderEditable = (props: RenderEditableProps) => react.ReactElement;
124
+ /**
125
+ * The return type of the BasePluginFn which specifies how the Plugin is
126
+ * supposed to behave.
127
+ */
128
+ type BasePluginPolicy = {
129
+ name: string;
130
+ editor?: {
131
+ isInline?: (element: Element) => boolean | void;
132
+ isVoid?: (element: Element) => boolean | void;
133
+ isMaster?: (element: Element) => boolean | void;
134
+ isSlave?: (element: Element) => boolean | void;
135
+ isStandalone?: (element: Element) => boolean | void;
136
+ deleteBackward?: (unit: "character" | "word" | "line" | "block") => VoidActionReturn;
137
+ deleteForward?: (unit: "character" | "word" | "line" | "block") => VoidActionReturn;
138
+ deleteFragment?: () => VoidActionReturn;
139
+ insertBreak?: () => VoidActionReturn;
140
+ insertFragment?: (fragment: Node[]) => VoidActionReturn;
141
+ insertNode?: (node: Node) => VoidActionReturn;
142
+ insertText?: (text: string) => VoidActionReturn;
143
+ normalizeNode?: (entry: NodeEntry) => VoidActionReturn;
144
+ };
145
+ renderEditable?: RenderEditable;
146
+ editableProps?: {
147
+ decorate?: ((entry: NodeEntry) => BaseRange[]) | undefined;
148
+ renderElement?: (props: RenderElementProps) => react.ReactElement | undefined;
149
+ renderLeaf?: (props: RenderLeafProps) => react.ReactElement | undefined;
150
+ renderPlaceholder?: (props: RenderPlaceholderProps) => react.ReactElement;
151
+ onKeyDown?: EditableVoidToBooleanHandlerType<"onKeyDown">;
152
+ onKeyUp?: EditableVoidToBooleanHandlerType<"onKeyDown">;
153
+ onPaste?: EditableVoidToBooleanHandlerType<"onPaste">;
154
+ onDrop?: EditableVoidToBooleanHandlerType<"onDrop">;
155
+ };
156
+ };
157
+ type EditableVoidToBooleanHandlerType<K extends keyof EditableProps> = SetReturnType<NonNullable<EditableProps[K]>, boolean>;
158
+
159
+ /**
160
+ * IMPORTANT!
161
+ *
162
+ * NEVER!
163
+ *
164
+ * refer to a type that is defined in the `slate` package. This is because
165
+ * any reference to a Slate type will cause a circular reference type error that
166
+ * is very hard to track down.
167
+ *
168
+ * NOTE: This kind of happens in that `Element` will often have a reference to
169
+ * `Descendant` but it looks like this is okay; however, let's not tempt fate
170
+ * by only using it where the definition is absolutely necessary.
171
+ *
172
+ * ALWAYS!
173
+ *
174
+ * Be explicity about return types. If they are inferred through the return
175
+ * type, because we need to provide `Editor` as an argument in certain cases,
176
+ * we don't want to accidentally have `Editor` be provided as a return type
177
+ * or this will create the circular reference.
178
+ */
179
+ type BasePluginSchema = {
180
+ Name: string;
181
+ Options: Record<string, unknown>;
182
+ Editor: Record<string, unknown>;
183
+ Element: {
184
+ type: string;
185
+ };
186
+ Text: Record<string, unknown>;
187
+ };
188
+ /**
189
+ * These are the PluginTypes that are accepted as inputs into `createPlugin`
190
+ * which has the same basic signature as `BasePluginTypes` but some of the
191
+ * types are optional.
192
+ *
193
+ * These `InputPluginTypes` need to have their optional types filled in with
194
+ * defaults before they can be used.
195
+ *
196
+ * See `NormalizeInputPluginTypes`
197
+ */
198
+ type InputPluginSchema = SetOptional<BasePluginSchema, "Options" | "Editor" | "Element" | "Text">;
199
+ /**
200
+ * Takes an `InputPluginSchema` (that has some optional types) and turns them
201
+ * into a regular PluginTypes with any missing types filled in with defaults.
202
+ */
203
+ type NormalizeInputPluginSchema<T extends InputPluginSchema> = {
204
+ Name: T["Name"];
205
+ Options: T["Options"] extends object ? T["Options"] : {};
206
+ Editor: T["Editor"] extends object ? T["Editor"] : {};
207
+ Element: T["Element"] extends object ? T["Element"] : never;
208
+ Text: T["Text"] extends object ? T["Text"] : {};
209
+ };
210
+
211
+ /**
212
+ * Shape of a PluginFn (Plugin Function).
213
+ */
214
+ type BasePluginFn = (editor: FullSinkEditor, options: {}, helpers: {
215
+ createPolicy: (value: unknown) => unknown;
216
+ }) => BasePluginPolicy;
217
+
218
+ /**
219
+ * IMPORTANT!
220
+ *
221
+ * NEVER!
222
+ *
223
+ * refer to a type that is defined in the `slate` package. This is because
224
+ * any reference to a Slate type will cause a circular reference type error that
225
+ * is very hard to track down.
226
+ *
227
+ * NOTE: This kind of happens in that `Element` will often have a reference to
228
+ * `Descendant` but it looks like this is okay; however, let's not tempt fate
229
+ * by only using it where the definition is absolutely necessary.
230
+ *
231
+ * ALWAYS!
232
+ *
233
+ * Be explicity about return types. If they are inferred through the return
234
+ * type, because we need to provide `Editor` as an argument in certain cases,
235
+ * we don't want to accidentally have `Editor` be provided as a return type
236
+ * or this will create the circular reference.
237
+ */
238
+
239
+ /**
240
+ * When a Plugin is created using the `createPlugin` method, it returns a
241
+ * Plugin.
242
+ */
243
+ type BasePlugin = {
244
+ fn: BasePluginFn;
245
+ __types__: BasePluginSchema;
246
+ };
247
+ /**
248
+ * When a Plugin is created using `createPlugin` we must
249
+ */
250
+ type TypedPlugin<T extends InputPluginSchema> = {
251
+ fn: BasePluginFn;
252
+ __types__: NormalizeInputPluginSchema<T>;
253
+ };
254
+
255
+ type ExtractCustomTypes<TA extends Array<BasePlugin>> =
256
+ /**
257
+ * This code takes an array of types and merges them together into a union.
258
+ */
259
+ TA extends Array<{
260
+ __types__: infer U;
261
+ }> ? {
262
+ Editor: SinkEditor & BaseEditor & ReactEditor & HistoryEditor & UnionToIntersection<U extends {
263
+ Editor: infer E;
264
+ } ? E : never>;
265
+ Element: U extends {
266
+ Element: infer E;
267
+ } ? E : never;
268
+ Text: Simplify<UnionToIntersection<U extends {
269
+ Text: infer T;
270
+ } ? T : never>>;
271
+ Options: Simplify<UnionToIntersection<U extends {
272
+ Options: infer T;
273
+ } ? T : never>>;
274
+ } : never;
275
+
276
+ /**
277
+ * Defines a value you'd find in a function's parameters as a replacement for
278
+ * `at`. The benefit of using `BetterAt` is that it allows you to search
279
+ * using an `Element`.
280
+ */
281
+ type BetterAt = Location | Element$1 | null;
282
+
283
+ /**
284
+ * The TargetElement can be specified either as the actual value or as a
285
+ * function that takes a srcElement and returns the targetElement.
286
+ */
287
+ type TargetElement<T extends Element$1 = Element$1> = Omit<T, "children"> | ((srcElement: Element$1) => Omit<T, "children">);
288
+
289
+ type PlaceholderEditor = {
290
+ placeholder: {};
291
+ };
292
+ type PlaceholderPluginCustomTypes = {
293
+ Name: "placeholder";
294
+ Editor: PlaceholderEditor;
295
+ };
296
+
297
+ declare function createImageMethods(editor: Editor): {
298
+ noop: () => void;
299
+ };
300
+
301
+ type ImageSize = {
302
+ width: number;
303
+ height: number;
304
+ };
305
+ type ImageMethods = ReturnType<typeof createImageMethods>;
306
+ type ImagePluginConfig = {
307
+ /**
308
+ * When an image is uploaded, the plugin needs to decide whether the image
309
+ * should be an inline image (like an icon that displays within a line of
310
+ * text) or a block image (like a photo that appears as its own block).
311
+ *
312
+ * This setting is the maximum size of an image for it to be defaulted to an
313
+ * inline image.
314
+ *
315
+ * NOTE:
316
+ *
317
+ * The user can convert an image from one image type to the other manually.
318
+ */
319
+ maxInitialInlineImageSize: ImageSize;
320
+ /**
321
+ * When an image is first uploaded, it may come in at a large size but for
322
+ * some applications, you don't want the image to overwhelm the page,
323
+ * like when the editor is visually a small size.
324
+ *
325
+ * This specifies the maximum initial size when an image is first uploaded
326
+ * to the page. The user can resize to a larger size.
327
+ *
328
+ * If the value is null, the image will be displayed at full size.
329
+ *
330
+ * NOTE:
331
+ *
332
+ * This is the displayed image width. On retina displays, the actualy image
333
+ * file delivered to the browser may be a multiple of the provided value.
334
+ */
335
+ maxInitialImageSize: ImageSize | null;
336
+ /**
337
+ * When an image is displayed at full size, you may still want to limit the
338
+ * size of the image file.
339
+ *
340
+ * NOTE:
341
+ *
342
+ * This is the maximum visual image
343
+ */
344
+ maxImageSize: ImageSize;
345
+ imageBlockPresets: ImageSizePreset[];
346
+ imageInlinePresets: ImageSizePreset[];
347
+ };
348
+ type ImagePluginOptions = {
349
+ image: Partial<ImagePluginConfig>;
350
+ };
351
+ type ImageEditor = {
352
+ image: ImageMethods & ImagePluginConfig;
353
+ };
354
+ type ImageSharedElement = {
355
+ /**
356
+ * The `url` represents either
357
+ *
358
+ * - a `hashUrl` that begins with a `#` during the upload process which
359
+ * represents a unique id reference to a Zustand store where the actual
360
+ * information about the upload is kept.
361
+ * - The actual `url` of the uploaded file. When the file is saved, the
362
+ * `hashUrl` will be converted to the actual `url` of the file.
363
+ */
364
+ url: string;
365
+ title?: string;
366
+ alt?: string;
367
+ bytes?: number;
368
+ /**
369
+ * If the `maxWidth` and `maxHeight` are present, it indicates that the image
370
+ * is resizable.
371
+ *
372
+ * If they are not present, it indicates that the `width` and `height` should
373
+ * be used, but they cannot be resized.
374
+ *
375
+ * If the `width` and `height` are also not present, it indicates we are not
376
+ * aware of the current size of the image, so just display it.
377
+ */
378
+ srcWidth?: number;
379
+ srcHeight?: number;
380
+ width?: number;
381
+ height?: number;
382
+ children: Descendant[];
383
+ };
384
+ /**
385
+ * Default for larger images, over 48px
386
+ *
387
+ * Larger images can be converted to inline images though.
388
+ */
389
+ type ImageBlockElement = {
390
+ type: "image-block";
391
+ } & ImageSharedElement;
392
+ /**
393
+ * Default for smaller images, 48px and less
394
+ *
395
+ * Smaller images can be converted to block images though.
396
+ */
397
+ type ImageInlineElement = {
398
+ type: "image-inline";
399
+ } & ImageSharedElement;
400
+ type ImagePluginCustomTypes = {
401
+ Name: "image";
402
+ Editor: ImageEditor;
403
+ Element: ImageBlockElement | ImageInlineElement;
404
+ Options: ImagePluginOptions;
405
+ };
406
+ /**
407
+ * A preset is defined either as a bound or as a scale:
408
+ *
409
+ * - bounds: The image will be placed within the bounds.
410
+ * - scale: The image will be scaled to the given `scale` value. The max
411
+ * value should be `1`.
412
+ */
413
+ type ImageSizePreset = {
414
+ name: string;
415
+ title: string;
416
+ type: "bounds";
417
+ width: number;
418
+ height: number;
419
+ } | {
420
+ name: string;
421
+ title: string;
422
+ type: "scale";
423
+ scale: number;
424
+ };
425
+
426
+ declare function createAnchorMethods(editor: Editor): {
427
+ insertLink: (args_0: string, args_1?: string | undefined, args_2?: {
428
+ select?: boolean | undefined;
429
+ } | undefined) => void;
430
+ removeLink: (args_0: {
431
+ at?: BetterAt | undefined;
432
+ }) => boolean;
433
+ editLink: (args_0: {
434
+ href: string;
435
+ title?: string | undefined;
436
+ }, args_1: {
437
+ at?: BetterAt | undefined;
438
+ }) => boolean;
439
+ };
440
+
441
+ type AnchorMethods = ReturnType<typeof createAnchorMethods>;
442
+ type AnchorEditor = {
443
+ anchor: AnchorMethods;
444
+ };
445
+ type AnchorElement = {
446
+ type: "anchor";
447
+ href: string;
448
+ target?: string;
449
+ title?: string;
450
+ children: Descendant[];
451
+ };
452
+ type AnchorPluginCustomTypes = {
453
+ Name: "anchor";
454
+ Editor: AnchorEditor;
455
+ Element: AnchorElement;
456
+ };
457
+
458
+ declare function createHeadingMethods(editor: Editor): {
459
+ convertHeading: (level: 1 | 2 | 3 | 4 | 5 | 6, allowToggle: boolean) => void;
460
+ isHeadingActive: (level: 1 | 2 | 3 | 4 | 5 | 6) => boolean;
461
+ };
462
+
463
+ type HeadingEditor = {
464
+ heading: ReturnType<typeof createHeadingMethods>;
465
+ };
466
+ type HeadingElement = {
467
+ type: "heading";
468
+ /**
469
+ * NOTE:
470
+ *
471
+ * Don't extract these into a new type. It's easier to just repeat this and
472
+ * there's less indirection.
473
+ */
474
+ level: 1 | 2 | 3 | 4 | 5 | 6;
475
+ children: Descendant[];
476
+ };
477
+ type HeadingPluginCustomTypes = {
478
+ Name: "heading";
479
+ Editor: HeadingEditor;
480
+ Element: HeadingElement;
481
+ };
482
+
483
+ type BlockQuoteEditor = {
484
+ supportsBlockQuote: true;
485
+ blockQuotePlugin: {
486
+ indent: () => void;
487
+ outdent: () => void;
488
+ isActive: () => boolean;
489
+ };
490
+ };
491
+ type BlockQuoteElement = {
492
+ type: "block-quote";
493
+ children: Descendant[];
494
+ };
495
+ type BlockQuotePluginCustomTypes = {
496
+ Name: "block-quote";
497
+ Editor: BlockQuoteEditor;
498
+ Element: BlockQuoteElement;
499
+ };
500
+
501
+ /**
502
+ * Alignment of Table Columns
503
+ */
504
+ type TableColumnAlign = "left" | "center" | "right";
505
+ /**
506
+ * Table Column values
507
+ */
508
+ type TableColumn = {
509
+ align: TableColumnAlign;
510
+ };
511
+ /**
512
+ * Table Element
513
+ */
514
+ type TableElement = {
515
+ type: "table";
516
+ columns: TableColumn[];
517
+ children: TableRowElement[];
518
+ };
519
+ /**
520
+ * Table Row Element
521
+ */
522
+ type TableRowElement = {
523
+ type: "table-row";
524
+ children: TableCellElement[];
525
+ };
526
+ /**
527
+ * Table Cell Element
528
+ *
529
+ * The children of a `TdElement` is exactly one `ParagraphElement`.
530
+ *
531
+ * This is a good choice for Slate because copying and pasting a range of
532
+ * elements will split the lowest child element by default. If the child of
533
+ * a `TdElement` is a leaf, then we split the `TdElement` which is never what
534
+ * we want.
535
+ *
536
+ * Instead, by having a lower level element, the `ParagraphElement`, we allow
537
+ * that to be split.
538
+ *
539
+ * But of course, insertion means we have many child elements in the `TdElement`
540
+ * but these are easier to fix using normalization. We can keep iterating
541
+ * through normalizations until we end up with a single Paragraph.
542
+ */
543
+ type TableCellElement = {
544
+ type: "table-cell";
545
+ x?: number;
546
+ y?: number;
547
+ children: TableContentElement[];
548
+ };
549
+ type TableContentElement = {
550
+ type: "table-content";
551
+ children: Descendant[];
552
+ };
553
+
554
+ /**
555
+ * The TableInfo object that includes quick access information starting from a
556
+ * cell in a table including information about the row and the table.
557
+ *
558
+ * NOTE:
559
+ *
560
+ * This is flat and not nested because it makes destructuring easier, for
561
+ * example, in the table methods.
562
+ */
563
+ type TableInfo = {
564
+ tableElement: TableElement;
565
+ tablePath: Path;
566
+ tableColumns: TableColumn[];
567
+ rowElement: TableRowElement;
568
+ rowPath: Path;
569
+ rowIndex: number;
570
+ rowCount: number;
571
+ cellElement: TableCellElement;
572
+ cellPath: Path;
573
+ cellIndex: number;
574
+ cellCount: number;
575
+ };
576
+
577
+ declare function createHorizontalRuleMethods(editor: Editor): {
578
+ insertHorizontalRule: () => boolean;
579
+ };
580
+
581
+ type HorizontalRuleMethods = ReturnType<typeof createHorizontalRuleMethods>;
582
+ type HorizontalRuleEditor = {
583
+ horizontalRule: HorizontalRuleMethods;
584
+ };
585
+ type HorizontalRuleElement = {
586
+ type: "horizontal-rule";
587
+ children: [{
588
+ text: "";
589
+ }];
590
+ };
591
+ type HorizontalRulePluginCustomTypes = {
592
+ Name: "horizontal-rule";
593
+ Editor: HorizontalRuleEditor;
594
+ Element: HorizontalRuleElement;
595
+ };
596
+
597
+ declare function createListMethods(editor: Editor): {
598
+ indent: () => boolean;
599
+ outdent: () => boolean;
600
+ convertUnorderedList: (allowToggle: boolean) => void;
601
+ convertOrderedList: (allowToggle: boolean) => void;
602
+ convertTaskList: (allowToggle: boolean) => void;
603
+ insertBreak: () => boolean;
604
+ toggleTaskListItem: (args_0?: {
605
+ at?: BetterAt | undefined;
606
+ } | undefined) => false | undefined;
607
+ getListDepth: () => number;
608
+ canIncreaseDepth: () => boolean;
609
+ canDecreaseDepth: () => boolean;
610
+ increaseDepth: () => void;
611
+ decreaseDepth: () => void;
612
+ };
613
+
614
+ /**
615
+ * List Editor
616
+ */
617
+ type ListEditor = {
618
+ list: ReturnType<typeof createListMethods>;
619
+ };
620
+ /**
621
+ * Ordered List Item Element
622
+ */
623
+ type OrderedListItemElement = {
624
+ type: "ordered-list-item";
625
+ depth: number;
626
+ __firstAtDepth?: boolean;
627
+ children: Descendant[];
628
+ };
629
+ /**
630
+ * Unordered List Item Element
631
+ */
632
+ type UnorderedListItemElement = {
633
+ type: "unordered-list-item";
634
+ depth: number;
635
+ __firstAtDepth?: boolean;
636
+ children: Descendant[];
637
+ };
638
+ /**
639
+ * Checkable Task List Item Element
640
+ */
641
+ type TaskListItemElement = {
642
+ type: "task-list-item";
643
+ depth: number;
644
+ __firstAtDepth?: boolean;
645
+ checked: boolean;
646
+ children: Descendant[];
647
+ };
648
+ /**
649
+ * List Plugins Custom Types
650
+ */
651
+ type ListPluginCustomTypes = {
652
+ Name: "list";
653
+ Editor: ListEditor;
654
+ Element: OrderedListItemElement | UnorderedListItemElement | TaskListItemElement;
655
+ };
656
+
657
+ type CollapsibleParagraphEditor = {
658
+ collapsibleParagraph: {
659
+ convertParagraph: () => void;
660
+ };
661
+ };
662
+ type ParagraphElement = {
663
+ type: "paragraph";
664
+ __collapsible?: true;
665
+ children: Descendant[];
666
+ };
667
+ type CollapsibleParagraphPluginCustomTypes = {
668
+ Name: "collapsible-paragraph";
669
+ Editor: CollapsibleParagraphEditor;
670
+ Element: ParagraphElement;
671
+ };
672
+
673
+ declare function createTableMethods(editor: Editor): {
674
+ getTableInfo: (args_0?: {
675
+ at?: ImageBlockElement | ImageInlineElement | ParagraphElement | OrderedListItemElement | UnorderedListItemElement | TaskListItemElement | HorizontalRuleElement | TableElement | TableRowElement | TableCellElement | TableContentElement | BlockQuoteElement | HeadingElement | AnchorElement | slate.Location | null | undefined;
676
+ } | undefined) => TableInfo | undefined;
677
+ insertTable: (args_0: number, args_1: number, args_2?: {
678
+ at?: slate.Location | null | undefined;
679
+ } | undefined) => boolean;
680
+ insertColumn: (args_0?: {
681
+ offset?: 0 | 1 | undefined;
682
+ at?: BetterAt | undefined;
683
+ } | undefined) => boolean;
684
+ insertRow: (args_0?: {
685
+ at?: BetterAt | undefined;
686
+ offset?: 0 | 1 | undefined;
687
+ } | undefined) => boolean;
688
+ removeTable: () => boolean;
689
+ removeColumn: (args_0?: {
690
+ at?: BetterAt | undefined;
691
+ } | undefined) => boolean | undefined;
692
+ removeRow: (args_0?: {
693
+ at?: BetterAt | undefined;
694
+ } | undefined) => boolean;
695
+ tabForward: () => boolean;
696
+ tabBackward: () => boolean | undefined;
697
+ selectCell: (args_0?: {
698
+ at?: BetterAt | undefined;
699
+ } | undefined) => boolean;
700
+ down: () => boolean;
701
+ up: () => boolean;
702
+ setTableColumnAlign: (options: {
703
+ align: "center" | "left" | "right";
704
+ }) => boolean;
705
+ };
706
+
707
+ type TableEditor = {
708
+ supportsTable: true;
709
+ tablePlugin: ReturnType<typeof createTableMethods>;
710
+ };
711
+ type TablePluginCustomTypes = {
712
+ Name: "table";
713
+ Editor: TableEditor;
714
+ Element: TableElement | TableRowElement | TableCellElement | TableContentElement;
715
+ };
716
+
717
+ declare function createUploadMethods(editor: Editor): {
718
+ upload: (file: File) => boolean;
719
+ setElementTimeTraveling: <T extends ImageBlockElement | ImageInlineElement | ParagraphElement | OrderedListItemElement | UnorderedListItemElement | TaskListItemElement | HorizontalRuleElement | TableElement | TableRowElement | TableCellElement | TableContentElement | BlockQuoteElement | HeadingElement | AnchorElement, K extends keyof T = keyof T>(prev: RequireExactlyOne<T, K>, next: RequireExactlyOne<T, K>) => void;
720
+ };
721
+
722
+ /**
723
+ * Indicates an `Origin` that is uploading and the state of the Upload
724
+ */
725
+ type UploadProgress = {
726
+ /**
727
+ * This is a URL but not the final upload URL. This is a URL that represents
728
+ * a secure value in the form of a string that represents a location on the
729
+ * user's computer.
730
+ */
731
+ url: string;
732
+ status: "progress";
733
+ sentBytes: number;
734
+ totalBytes: number;
735
+ };
736
+ /**
737
+ * Indicates an `Origin` that has completed uploading
738
+ */
739
+ type UploadComplete = {
740
+ status: "success";
741
+ /**
742
+ * This is a URL to the final place of the file
743
+ */
744
+ url: string;
745
+ };
746
+ /**
747
+ * Indicates an `Origin` that has an error during uploading and the Error
748
+ * message
749
+ */
750
+ type UploadError = {
751
+ status: "error";
752
+ url: string;
753
+ message: string;
754
+ };
755
+ type Upload = UploadProgress | UploadComplete | UploadError;
756
+
757
+ /**
758
+ * Creates an origin store using `zustand`.
759
+ *
760
+ * The purpose of this is to keep track of uploads and their progress but only
761
+ * storing the key to the lookup in the Element itself.
762
+ *
763
+ * This is necessary so that the Element value stays the same even as the image
764
+ * progress is updating during the upload.
765
+ *
766
+ * We want this because we don't want the progress updates to be part of the
767
+ * document's edit history. Consider that a user executes an undo and it undoes
768
+ * the progress of the upload.
769
+ *
770
+ * Te return value of `createUploadStore` is a React hook.
771
+ *
772
+ * The hook should be referenced as `useUploadStore`
773
+ */
774
+ declare const createUploadStore: ({ uploads }?: {
775
+ uploads: Record<string, Upload>;
776
+ }) => zustand.UseBoundStore<zustand.StoreApi<UploadStore>>;
777
+
778
+ /**
779
+ * Types related to the `zustand` state-management library which we use to
780
+ * store the state of uploads.
781
+ */
782
+ type GetUpload = (id: string) => Upload;
783
+ type SetUpload = (id: string, upload: Upload) => void;
784
+ type UploadStore = {
785
+ uploads: Record<string, Upload>;
786
+ getUpload: GetUpload;
787
+ setUpload: SetUpload;
788
+ };
789
+
790
+ type UploadMethods = ReturnType<typeof createUploadMethods>;
791
+ type UploadFileEvent = {
792
+ hashUrl: string;
793
+ file: File;
794
+ };
795
+ type UploadImageFileEvent = UploadFileEvent & {
796
+ width: number;
797
+ height: number;
798
+ };
799
+ type UploadFileSuccessEvent = UploadFileEvent & {
800
+ url: string;
801
+ };
802
+ type UploadImageFileSuccessEvent = UploadImageFileEvent & {
803
+ url: string;
804
+ };
805
+ type UploadEditor = {
806
+ upload: UploadMethods & {
807
+ client?: Client;
808
+ onUploadImageFile: (e: UploadImageFileEvent) => boolean;
809
+ onUploadFile: (e: UploadFileEvent) => boolean;
810
+ onUploadImageFileSuccess: (e: UploadImageFileSuccessEvent) => boolean;
811
+ onUploadFileSuccess: (e: UploadFileSuccessEvent) => boolean;
812
+ useUploadStore: ReturnType<typeof createUploadStore>;
813
+ };
814
+ };
815
+ type UploadOptions = {
816
+ upload?: {
817
+ authToken?: string;
818
+ };
819
+ };
820
+ type UploadPluginCustomTypes = {
821
+ Name: "upload";
822
+ Editor: UploadEditor;
823
+ Options: UploadOptions;
824
+ };
825
+
826
+ type ToolbarEditor = {
827
+ toolbar: {
828
+ height?: string | number;
829
+ minHeight?: string | number;
830
+ maxHeight?: string | number;
831
+ showUploadButtons?: boolean;
832
+ };
833
+ };
834
+ type ToolbarOptions = {
835
+ toolbar: {
836
+ height?: string | number;
837
+ minHeight?: string | number;
838
+ maxHeight?: string | number;
839
+ showUploadButtons?: boolean;
840
+ };
841
+ };
842
+ type ToolbarPluginCustomTypes = {
843
+ Name: "toolbar";
844
+ Editor: ToolbarEditor;
845
+ Options: ToolbarOptions;
846
+ };
847
+
848
+ type ThemeEditor = {
849
+ theme: true;
850
+ };
851
+ type ThemePluginCustomTypes = {
852
+ Name: "theme";
853
+ Editor: ThemeEditor;
854
+ };
855
+
856
+ type NormalizeAfterDeleteEditor = {
857
+ normalizeAfterDelete: true;
858
+ };
859
+ type NormalizeAfterDeletePluginCustomTypes = {
860
+ Name: "normalize-after-delete";
861
+ Editor: NormalizeAfterDeleteEditor;
862
+ };
863
+
864
+ type AtomicDeleteEditor = {
865
+ atomicDelete: true;
866
+ };
867
+ type AtomicDeletePluginCustomTypes = {
868
+ Name: "atomic-delete";
869
+ Editor: AtomicDeleteEditor;
870
+ };
871
+
872
+ type InlineCodeEditor = {
873
+ inlineCode: {
874
+ toggleInlineCode: () => void;
875
+ };
876
+ };
877
+ type InlineCodeText = {
878
+ text: string;
879
+ code?: true;
880
+ };
881
+ type InlineCodePluginCustomTypes = {
882
+ Name: "inline-code";
883
+ Editor: InlineCodeEditor;
884
+ Text: InlineCodeText;
885
+ };
886
+
887
+ declare function createMarksMethods(editor: Editor): {
888
+ removeMarks: (args_0?: {
889
+ at?: slate.Location | null | undefined;
890
+ } | undefined) => void;
891
+ toggleMark: (args_0: "bold" | "strike" | "text" | "code" | "italic" | "underline", args_1?: "bold" | "strike" | "text" | "code" | "italic" | "underline" | undefined, args_2?: {
892
+ at?: slate.Location | null | undefined;
893
+ } | undefined) => void;
894
+ toggleBold: () => void;
895
+ toggleItalic: () => void;
896
+ toggleUnderline: () => void;
897
+ toggleStrike: () => void;
898
+ };
899
+
900
+ type MarksEditor = {
901
+ /**
902
+ * IMPORTANT:
903
+ *
904
+ * This cannot be named `marks` because it conflicts with the `editor.marks`
905
+ * built into the BaseEditor.j
906
+ */
907
+ marksPlugin: ReturnType<typeof createMarksMethods>;
908
+ activeMarks?: {
909
+ bold?: boolean;
910
+ italic?: boolean;
911
+ underline?: boolean;
912
+ strike?: boolean;
913
+ };
914
+ };
915
+ type MarksText = {
916
+ text: string;
917
+ bold?: true;
918
+ italic?: true;
919
+ underline?: true;
920
+ strike?: true;
921
+ };
922
+ type MarksPluginCustomTypes = {
923
+ Name: "marks";
924
+ Editor: MarksEditor;
925
+ Text: MarksText;
926
+ };
927
+
928
+ /**
929
+ * A type with generic for `convertElements` (below) to be used with the curry
930
+ * method. TypeScript, unfortunately, cannot automatically curry generics for
931
+ * us so we have to do it manually.
932
+ */
933
+ type CurriedConvertElements = <T extends Element$1 = Element$1>(matchForToggle: (element: Element$1) => boolean, targetElement: TargetElement<T>, allowToggle: boolean) => void;
934
+
935
+ declare function createConvertElementMethods(editor: Editor): {
936
+ convertElementTypes: string[];
937
+ addConvertElementType: (type: "anchor" | "heading" | "block-quote" | "table" | "horizontal-rule" | "paragraph" | "image-block" | "image-inline" | "ordered-list-item" | "unordered-list-item" | "task-list-item" | "table-row" | "table-cell" | "table-content" | ("anchor" | "heading" | "block-quote" | "table" | "horizontal-rule" | "paragraph" | "image-block" | "image-inline" | "ordered-list-item" | "unordered-list-item" | "task-list-item" | "table-row" | "table-cell" | "table-content")[]) => void;
938
+ isConvertibleElement: (element: ImageBlockElement | ImageInlineElement | ParagraphElement | OrderedListItemElement | UnorderedListItemElement | TaskListItemElement | HorizontalRuleElement | TableElement | TableRowElement | TableCellElement | TableContentElement | BlockQuoteElement | HeadingElement | AnchorElement) => boolean;
939
+ convertElements: CurriedConvertElements;
940
+ };
941
+
942
+ type ConvertElementEditor = {
943
+ convertElement: ReturnType<typeof createConvertElementMethods>;
944
+ };
945
+ type ConvertElementPluginCustomTypes = {
946
+ Name: "convert-element";
947
+ Editor: ConvertElementEditor;
948
+ };
949
+
950
+ declare function createPasteMarkdownMethods(editor: Editor): {
951
+ pasteMarkdown: (markdown: string) => void;
952
+ };
953
+
954
+ type PasteMarkdownMethods = ReturnType<typeof createPasteMarkdownMethods>;
955
+ type PasteMarkdownEditor = {
956
+ pasteMarkdown: PasteMarkdownMethods;
957
+ };
958
+ type PasteMarkdownPluginCustomTypes = {
959
+ Name: "paste-markdown";
960
+ Editor: PasteMarkdownEditor;
961
+ };
962
+
963
+ type WysimarkEditor = {
964
+ /**
965
+ * Private state for the wysimark editor.
966
+ */
967
+ wysimark: {
968
+ prevValue?: {
969
+ markdown: string;
970
+ children: Descendant[];
971
+ };
972
+ };
973
+ /**
974
+ * Public methods for the wysimark editor.
975
+ */
976
+ getMarkdown: () => string;
977
+ setMarkdown: (markdown: string) => void;
978
+ };
979
+
980
+ declare const plugins: (TypedPlugin<PasteMarkdownPluginCustomTypes> | TypedPlugin<ConvertElementPluginCustomTypes> | TypedPlugin<AnchorPluginCustomTypes> | TypedPlugin<HeadingPluginCustomTypes> | TypedPlugin<MarksPluginCustomTypes> | TypedPlugin<InlineCodePluginCustomTypes> | TypedPlugin<BlockQuotePluginCustomTypes> | TypedPlugin<TablePluginCustomTypes> | TypedPlugin<HorizontalRulePluginCustomTypes> | TypedPlugin<{
981
+ Name: "trailing-block";
982
+ Editor: {
983
+ allowTrailingBlock: true;
984
+ };
985
+ }> | TypedPlugin<ListPluginCustomTypes> | TypedPlugin<AtomicDeletePluginCustomTypes> | TypedPlugin<NormalizeAfterDeletePluginCustomTypes> | TypedPlugin<CollapsibleParagraphPluginCustomTypes> | TypedPlugin<ThemePluginCustomTypes> | TypedPlugin<ToolbarPluginCustomTypes> | TypedPlugin<UploadPluginCustomTypes> | TypedPlugin<ImagePluginCustomTypes> | TypedPlugin<PlaceholderPluginCustomTypes>)[];
986
+ type PluginTypes = ExtractCustomTypes<typeof plugins>;
987
+ type CustomEditor = PluginTypes["Editor"];
988
+ type CustomElement = PluginTypes["Element"];
989
+ type CustomText = PluginTypes["Text"];
990
+ declare module "slate" {
991
+ interface CustomTypes {
992
+ Editor: BaseEditor & ReactEditor & HistoryEditor & CustomEditor & WysimarkEditor;
993
+ Element: CustomElement;
994
+ Text: BaseText & CustomText;
995
+ }
996
+ }
997
+
998
+ declare function useEditor({ authToken, height, minHeight, maxHeight, }: {
999
+ authToken?: string;
1000
+ height?: string | number;
1001
+ minHeight?: string | number;
1002
+ maxHeight?: string | number;
1003
+ }): Editor & ReactEditor & WysimarkEditor;
1004
+
1005
+ /**
1006
+ * The options passed into the standalone version of Wysimark.
1007
+ */
1008
+ type StandaloneOptions = Parameters<typeof useEditor>[0] & {
1009
+ onChange?: (markdown: string) => void;
1010
+ placeholder?: string;
1011
+ initialMarkdown?: string;
1012
+ className?: string;
1013
+ };
1014
+ /**
1015
+ * The object returned by `createWysimark`
1016
+ */
1017
+ type Wysimark = {
1018
+ unmount: () => void;
1019
+ getMarkdown: () => string;
1020
+ setMarkdown: (markdown: string) => void;
1021
+ };
1022
+ type ReadOnlyOptions = {
1023
+ markdown: string;
1024
+ className?: string;
1025
+ style?: react.CSSProperties;
1026
+ };
1027
+ /**
1028
+ + * Creates a read-only version of Wysimark that doesn't show the toolbar and doesn't allow editing.
1029
+ + */
1030
+ declare function createMarkdownDisplay(containerElement: HTMLElement, options?: ReadOnlyOptions): {
1031
+ unmount(): void;
1032
+ };
1033
+ /**
1034
+ * The primary entry point for the standalone version of Wysimark.
1035
+ */
1036
+ declare function createWysimark(containerElement: HTMLElement, options: StandaloneOptions): Wysimark;
1037
+
1038
+ export { Wysimark, createMarkdownDisplay, createWysimark };