UNPKG

@bratislava/wysimark-editor

Version:

The customized fork of wysimark editor - A modern and clean rich text editor for React that supports 100% of CommonMark and GitHub Flavored Markdown.

1,079 lines (1,024 loc) 35.6 kB
import * as react_jsx_runtime from 'react/jsx-runtime'; import * as slate from 'slate'; import { Element as Element$2, BaseEditor, NodeEntry, BaseRange, Location, Editor, Descendant, Text as Text$1, Path, BaseText } from 'slate'; import { Client } from '@portive/client'; import { SetReturnType, SetOptional, UnionToIntersection, Simplify, RequireExactlyOne } from 'type-fest'; import * as zustand from 'zustand'; import { HistoryEditor } from 'slate-history'; import { ReactEditor, Editable as Editable$1 } from 'slate-react'; import react from 'react'; import { RenderElementProps, RenderLeafProps, RenderPlaceholderProps, EditableProps as EditableProps$1 } from 'slate-react/dist/components/editable'; /** * SinkEditor just adds a `sink` object where we drop all of our sink * related data on. */ type SinkEditor = { /** * a master Element is one that has one or more elements that are depedant * on it. For example, a `table` Element. For clarity, a `table-row` Element * is not considered a master Element. Only the top-most element is. * * One use for identify a master is for adding a block quote. We want the * block quote to always surround the master Element. A block-quote that * surrounded a table-row, for example, would not make sense. */ isMaster: (node: Element$2) => boolean; /** * a slave Element is one that is dependant on another Element. For example, * `table-row`, `table-cell` and `table-cotent` elements are all considered * slave elements. * * At the time of writing, I haven't figured out a use case for a slave * element actually... */ isSlave: (node: Element$2) => boolean; isStandalone: (node: Element$2) => boolean; sink: { plugins: BasePluginPolicy[]; }; }; type FullSinkEditor = SinkEditor & BaseEditor & ReactEditor & HistoryEditor; /** * On the editor, there are several methods that return void that are used to * override default editor behaviors. * * These are referred to as Overrideable core actions in the docs. * * - deleteBackward * - deleteForward * - deleteFragment * - insertBreak * - insertFragment * - insertNode * - insertText * - normalizeNode * * When there are plugins, Sink tries to find a plugin to handle the event and * if it cannot, uses the previously defined handler. For example, the user may * have specified `editor.insertBreak` on the `editor` earlier and that will * be called after all the plugins have been searched. * * We search through the plugins from the first to the last plugin. * * In a plugin, we specify the functions like we don on the editor but the * return value informs us how the plugin should proceed after. The return * value generally indicates whether the plugin has handled the event with one * special case: * * - `true`: If the return type is `true` then the plugin has indicated it has * handled the event and no further processing is required. The handlers in * all remaining plugins are skipped. * * - `false`: If the return type is `false` then the plugin has indicated it has * not handled the event and will continue through the rest of the plugins * looking for a plugin to handle the event. * * - `() => void`: If the return tyep is a function, the plugin has indicated * it has not handled the event, but that it would like to register another * function that should execute after the actual event handler has been * executed. In particular, this is used when in certain situations we may * want a normalizer to execute after the event handler has triggered. This * is used in the `normalize-after-delete-plugin` for example. * * NOTE: * * This seems like an unusual specification at first glance and a purist might * argue, this could be handled more succinctly with a `next` function passed * in as the final argument. * * Here's why I elected to go this route but it boils down to the fact that * `next` functions make the function difficult to reason about. * * - 99% of the true, we want to indicate whether we handled the function or * not and for that use case, true/false is simple to understand and natural. * In the case where we need something to happen after, returning a function * is unusual, but still easy to reason about. Also, the exclusivity of * the function return is nice in that it assumes that the event wasn't * handled, and of course, the function return would only ever be used if the * function indeed wasn't handled. For if it was handled, there would be no * need to have the after function because that could just be in the original * function handler. * * - To use this, you have to build nested contexts that are always hard to * reason about because you are passing a set of contexts from inner child * to outer parent. This created difficult to comprehend complexity in the * old Slate plugins architecture and is probably why it was abandoned. * * - It's also harder to type properly and to reason about it. The argument * list changes in length depending on the function; furthermore, in some * cases it is natural to ignore the arguments but we'd have to accept blank * arguments that are unused to access the `next` function. * * - It's hard to debug. The plugin system as it currently is designed to * execute linearly, instead of in a nested fashion. This makes it easy to * add debug code, and know what happens before and after each step. */ type VoidActionReturn = boolean | (() => void); type RenderEditableProps = { attributes: EditableProps$1; Editable: typeof Editable$1; }; type RenderEditable = (props: RenderEditableProps) => react.ReactElement; /** * The return type of the BasePluginFn which specifies how the Plugin is * supposed to behave. */ type BasePluginPolicy = { name: string; editor?: { isInline?: (element: Element) => boolean | void; isVoid?: (element: Element) => boolean | void; isMaster?: (element: Element) => boolean | void; isSlave?: (element: Element) => boolean | void; isStandalone?: (element: Element) => boolean | void; deleteBackward?: (unit: "character" | "word" | "line" | "block") => VoidActionReturn; deleteForward?: (unit: "character" | "word" | "line" | "block") => VoidActionReturn; deleteFragment?: () => VoidActionReturn; insertBreak?: () => VoidActionReturn; insertFragment?: (fragment: Node[]) => VoidActionReturn; insertNode?: (node: Node) => VoidActionReturn; insertText?: (text: string) => VoidActionReturn; normalizeNode?: (entry: NodeEntry) => VoidActionReturn; }; renderEditable?: RenderEditable; editableProps?: { decorate?: ((entry: NodeEntry) => BaseRange[]) | undefined; renderElement?: (props: RenderElementProps) => react.ReactElement | undefined; renderLeaf?: (props: RenderLeafProps) => react.ReactElement | undefined; renderPlaceholder?: (props: RenderPlaceholderProps) => JSX.Element; onKeyDown?: EditableVoidToBooleanHandlerType<"onKeyDown">; onKeyUp?: EditableVoidToBooleanHandlerType<"onKeyDown">; onPaste?: EditableVoidToBooleanHandlerType<"onPaste">; onDrop?: EditableVoidToBooleanHandlerType<"onDrop">; }; }; type EditableVoidToBooleanHandlerType<K extends keyof EditableProps$1> = SetReturnType<NonNullable<EditableProps$1[K]>, boolean>; /** * IMPORTANT! * * NEVER! * * refer to a type that is defined in the `slate` package. This is because * any reference to a Slate type will cause a circular reference type error that * is very hard to track down. * * NOTE: This kind of happens in that `Element` will often have a reference to * `Descendant` but it looks like this is okay; however, let's not tempt fate * by only using it where the definition is absolutely necessary. * * ALWAYS! * * Be explicity about return types. If they are inferred through the return * type, because we need to provide `Editor` as an argument in certain cases, * we don't want to accidentally have `Editor` be provided as a return type * or this will create the circular reference. */ type BasePluginSchema = { Name: string; Options: Record<string, unknown>; Editor: Record<string, unknown>; Element: { type: string; }; Text: Record<string, unknown>; }; /** * These are the PluginTypes that are accepted as inputs into `createPlugin` * which has the same basic signature as `BasePluginTypes` but some of the * types are optional. * * These `InputPluginTypes` need to have their optional types filled in with * defaults before they can be used. * * See `NormalizeInputPluginTypes` */ type InputPluginSchema = SetOptional<BasePluginSchema, "Options" | "Editor" | "Element" | "Text">; /** * Takes an `InputPluginSchema` (that has some optional types) and turns them * into a regular PluginTypes with any missing types filled in with defaults. */ type NormalizeInputPluginSchema<T extends InputPluginSchema> = { Name: T["Name"]; Options: T["Options"] extends object ? T["Options"] : {}; Editor: T["Editor"] extends object ? T["Editor"] : {}; Element: T["Element"] extends object ? T["Element"] : never; Text: T["Text"] extends object ? T["Text"] : {}; }; /** * Shape of a PluginFn (Plugin Function). */ type BasePluginFn = (editor: FullSinkEditor, options: {}, helpers: { createPolicy: (value: unknown) => unknown; }) => BasePluginPolicy; /** * IMPORTANT! * * NEVER! * * refer to a type that is defined in the `slate` package. This is because * any reference to a Slate type will cause a circular reference type error that * is very hard to track down. * * NOTE: This kind of happens in that `Element` will often have a reference to * `Descendant` but it looks like this is okay; however, let's not tempt fate * by only using it where the definition is absolutely necessary. * * ALWAYS! * * Be explicity about return types. If they are inferred through the return * type, because we need to provide `Editor` as an argument in certain cases, * we don't want to accidentally have `Editor` be provided as a return type * or this will create the circular reference. */ /** * When a Plugin is created using the `createPlugin` method, it returns a * Plugin. */ type BasePlugin = { fn: BasePluginFn; __types__: BasePluginSchema; }; /** * When a Plugin is created using `createPlugin` we must */ type TypedPlugin<T extends InputPluginSchema> = { fn: BasePluginFn; __types__: NormalizeInputPluginSchema<T>; }; type ExtractCustomTypes<TA extends Array<BasePlugin>> = /** * This code takes an array of types and merges them together into a union. */ TA extends Array<{ __types__: infer U; }> ? { Editor: SinkEditor & BaseEditor & ReactEditor & HistoryEditor & UnionToIntersection<U extends { Editor: infer E; } ? E : never>; Element: U extends { Element: infer E; } ? E : never; Text: Simplify<UnionToIntersection<U extends { Text: infer T; } ? T : never>>; Options: Simplify<UnionToIntersection<U extends { Options: infer T; } ? T : never>>; } : never; /** * Defines a value you'd find in a function's parameters as a replacement for * `at`. The benefit of using `BetterAt` is that it allows you to search * using an `Element`. */ type BetterAt = Location | Element$2 | null; /** * The TargetElement can be specified either as the actual value or as a * function that takes a srcElement and returns the targetElement. */ type TargetElement<T extends Element$2 = Element$2> = Omit<T, "children"> | ((srcElement: Element$2) => Omit<T, "children">); type PlaceholderEditor = { placeholder: {}; }; type PlaceholderPluginCustomTypes = { Name: "placeholder"; Editor: PlaceholderEditor; }; declare function createImageMethods(editor: Editor): { noop: () => void; }; type ImageSize = { width: number; height: number; }; type ImageMethods = ReturnType<typeof createImageMethods>; type ImagePluginConfig = { /** * When an image is uploaded, the plugin needs to decide whether the image * should be an inline image (like an icon that displays within a line of * text) or a block image (like a photo that appears as its own block). * * This setting is the maximum size of an image for it to be defaulted to an * inline image. * * NOTE: * * The user can convert an image from one image type to the other manually. */ maxInitialInlineImageSize: ImageSize; /** * When an image is first uploaded, it may come in at a large size but for * some applications, you don't want the image to overwhelm the page, * like when the editor is visually a small size. * * This specifies the maximum initial size when an image is first uploaded * to the page. The user can resize to a larger size. * * If the value is null, the image will be displayed at full size. * * NOTE: * * This is the displayed image width. On retina displays, the actualy image * file delivered to the browser may be a multiple of the provided value. */ maxInitialImageSize: ImageSize | null; /** * When an image is displayed at full size, you may still want to limit the * size of the image file. * * NOTE: * * This is the maximum visual image */ maxImageSize: ImageSize; imageBlockPresets: ImageSizePreset[]; imageInlinePresets: ImageSizePreset[]; }; type ImagePluginOptions = { image: Partial<ImagePluginConfig>; }; type ImageEditor = { image: ImageMethods & ImagePluginConfig; }; type ImageSharedElement = { /** * The `url` represents either * * - a `hashUrl` that begins with a `#` during the upload process which * represents a unique id reference to a Zustand store where the actual * information about the upload is kept. * - The actual `url` of the uploaded file. When the file is saved, the * `hashUrl` will be converted to the actual `url` of the file. */ url: string; title?: string; alt?: string; bytes?: number; /** * If the `maxWidth` and `maxHeight` are present, it indicates that the image * is resizable. * * If they are not present, it indicates that the `width` and `height` should * be used, but they cannot be resized. * * If the `width` and `height` are also not present, it indicates we are not * aware of the current size of the image, so just display it. */ srcWidth?: number; srcHeight?: number; width?: number; height?: number; children: Descendant[]; }; /** * Default for larger images, over 48px * * Larger images can be converted to inline images though. */ type ImageBlockElement = { type: "image-block"; } & ImageSharedElement; /** * Default for smaller images, 48px and less * * Smaller images can be converted to block images though. */ type ImageInlineElement = { type: "image-inline"; } & ImageSharedElement; type ImagePluginCustomTypes = { Name: "image"; Editor: ImageEditor; Element: ImageBlockElement | ImageInlineElement; Options: ImagePluginOptions; }; /** * A preset is defined either as a bound or as a scale: * * - bounds: The image will be placed within the bounds. * - scale: The image will be scaled to the given `scale` value. The max * value should be `1`. */ type ImageSizePreset = { name: string; title: string; type: "bounds"; width: number; height: number; } | { name: string; title: string; type: "scale"; scale: number; }; declare function createAnchorMethods(editor: Editor): { insertLink: (args_0: string, args_1?: string | undefined, args_2?: { select?: boolean | undefined; } | undefined) => void; removeLink: (args_0: { at?: BetterAt | undefined; }) => boolean; editLink: (args_0: { href: string; title?: string | undefined; }, args_1: { at?: BetterAt | undefined; }) => boolean; }; type AnchorMethods = ReturnType<typeof createAnchorMethods>; type AnchorEditor = { anchor: AnchorMethods; }; type AnchorElement = { type: "anchor"; href: string; target?: string; title?: string; children: Descendant[]; }; type AnchorPluginCustomTypes = { Name: "anchor"; Editor: AnchorEditor; Element: AnchorElement; }; declare function createHeadingMethods(editor: Editor): { convertHeading: (level: 1 | 3 | 2 | 4 | 5 | 6, allowToggle: boolean) => void; }; type HeadingEditor = { heading: ReturnType<typeof createHeadingMethods>; }; type HeadingElement = { type: "heading"; /** * NOTE: * * Don't extract these into a new type. It's easier to just repeat this and * there's less indirection. */ level: 1 | 2 | 3 | 4 | 5 | 6; children: Descendant[]; }; type HeadingPluginCustomTypes = { Name: "heading"; Editor: HeadingEditor; Element: HeadingElement; }; type BlockQuoteEditor = { supportsBlockQuote: true; blockQuotePlugin: { indent: () => void; outdent: () => void; }; }; type BlockQuoteElement = { type: "block-quote"; children: Descendant[]; }; type BlockQuotePluginCustomTypes = { Name: "block-quote"; Editor: BlockQuoteEditor; Element: BlockQuoteElement; }; declare function createCodeBlockMethods(editor: Editor): { createCodeBlock: (args_0: { language: BuiltInLanguage; }) => void; setCodeBlockLanguage: (language: BuiltInLanguage, options?: { at?: BetterAt | undefined; } | undefined) => boolean; }; type CodeBlockMethods = ReturnType<typeof createCodeBlockMethods>; type BuiltInLanguage = "text" | "html" | "svg" | "markup" | "css" | "javascript" | "js" | "java" | "c" | "clike"; type CodeBlockEditor = { codeBlock: CodeBlockMethods; }; /** * The code block element is the root element of a code block. */ type CodeBlockElement = { type: "code-block"; /** * The language of the code block. Can accept any string because Markdown can * accept any string; however, the built-in Prism languages are defined in: * `BuiltInLanguage` */ language: string; children: CodeBlockLineElement[]; }; type CodeBlockLineElement = { type: "code-block-line"; children: Text$1[]; }; type CodeBlockPluginCustomTypes = { Name: "code-block"; Editor: CodeBlockEditor; Element: CodeBlockElement | CodeBlockLineElement; Text: { text: string; prismToken?: string; }; }; /** * Alignment of Table Columns */ type TableColumnAlign = "left" | "center" | "right"; /** * Table Column values */ type TableColumn = { align: TableColumnAlign; }; /** * Table Element */ type TableElement = { type: "table"; columns: TableColumn[]; children: TableRowElement[]; }; /** * Table Row Element */ type TableRowElement = { type: "table-row"; children: TableCellElement[]; }; /** * Table Cell Element * * The children of a `TdElement` is exactly one `ParagraphElement`. * * This is a good choice for Slate because copying and pasting a range of * elements will split the lowest child element by default. If the child of * a `TdElement` is a leaf, then we split the `TdElement` which is never what * we want. * * Instead, by having a lower level element, the `ParagraphElement`, we allow * that to be split. * * But of course, insertion means we have many child elements in the `TdElement` * but these are easier to fix using normalization. We can keep iterating * through normalizations until we end up with a single Paragraph. */ type TableCellElement = { type: "table-cell"; x?: number; y?: number; children: TableContentElement[]; }; type TableContentElement = { type: "table-content"; children: Descendant[]; }; /** * The TableInfo object that includes quick access information starting from a * cell in a table including information about the row and the table. * * NOTE: * * This is flat and not nested because it makes destructuring easier, for * example, in the table methods. */ type TableInfo = { tableElement: TableElement; tablePath: Path; tableColumns: TableColumn[]; rowElement: TableRowElement; rowPath: Path; rowIndex: number; rowCount: number; cellElement: TableCellElement; cellPath: Path; cellIndex: number; cellCount: number; }; declare function createHorizontalRuleMethods(editor: Editor): { insertHorizontalRule: () => boolean; }; type HorizontalRuleMethods = ReturnType<typeof createHorizontalRuleMethods>; type HorizontalRuleEditor = { horizontalRule: HorizontalRuleMethods; }; type HorizontalRuleElement = { type: "horizontal-rule"; children: [{ text: ""; }]; }; type HorizontalRulePluginCustomTypes = { Name: "horizontal-rule"; Editor: HorizontalRuleEditor; Element: HorizontalRuleElement; }; declare function createListMethods(editor: Editor): { indent: () => boolean; outdent: () => boolean; convertUnorderedList: (allowToggle: boolean) => void; convertOrderedList: (allowToggle: boolean) => void; convertTaskList: (allowToggle: boolean) => void; insertBreak: () => boolean; toggleTaskListItem: (args_0?: { at?: BetterAt | undefined; } | undefined) => false | undefined; }; /** * List Editor */ type ListEditor = { list: ReturnType<typeof createListMethods>; }; /** * Ordered List Item Element */ type OrderedListItemElement = { type: "ordered-list-item"; depth: number; __firstAtDepth?: boolean; children: Descendant[]; }; /** * Unordered List Item Element */ type UnorderedListItemElement = { type: "unordered-list-item"; depth: number; __firstAtDepth?: boolean; children: Descendant[]; }; /** * Checkable Task List Item Element */ type TaskListItemElement = { type: "task-list-item"; depth: number; __firstAtDepth?: boolean; checked: boolean; children: Descendant[]; }; /** * List Plugins Custom Types */ type ListPluginCustomTypes = { Name: "list"; Editor: ListEditor; Element: OrderedListItemElement | UnorderedListItemElement | TaskListItemElement; }; type CollapsibleParagraphEditor = { collapsibleParagraph: { convertParagraph: () => void; }; }; type ParagraphElement = { type: "paragraph"; __collapsible?: true; children: Descendant[]; }; type CollapsibleParagraphPluginCustomTypes = { Name: "collapsible-paragraph"; Editor: CollapsibleParagraphEditor; Element: ParagraphElement; }; declare function createTableMethods(editor: Editor): { getTableInfo: (args_0?: { at?: ImageBlockElement | ImageInlineElement | ParagraphElement | OrderedListItemElement | UnorderedListItemElement | TaskListItemElement | HorizontalRuleElement | TableElement | TableRowElement | TableCellElement | TableContentElement | CodeBlockElement | CodeBlockLineElement | BlockQuoteElement | HeadingElement | AnchorElement | slate.Location | null | undefined; } | undefined) => TableInfo | undefined; insertTable: (args_0: number, args_1: number, args_2?: { at?: slate.Location | null | undefined; } | undefined) => boolean; insertColumn: (args_0?: { offset?: 0 | 1 | undefined; at?: BetterAt | undefined; } | undefined) => boolean; insertRow: (args_0?: { at?: BetterAt | undefined; offset?: 0 | 1 | undefined; } | undefined) => boolean; removeTable: () => boolean; removeColumn: (args_0?: { at?: BetterAt | undefined; } | undefined) => boolean | undefined; removeRow: (args_0?: { at?: BetterAt | undefined; } | undefined) => boolean; tabForward: () => boolean; tabBackward: () => boolean | undefined; selectCell: (args_0?: { at?: BetterAt | undefined; } | undefined) => boolean; down: () => boolean; up: () => boolean; setTableColumnAlign: (options: { align: "center" | "left" | "right"; }) => boolean; }; type TableEditor = { supportsTable: true; tablePlugin: ReturnType<typeof createTableMethods>; }; type TablePluginCustomTypes = { Name: "table"; Editor: TableEditor; Element: TableElement | TableRowElement | TableCellElement | TableContentElement; }; declare function createUploadMethods(editor: Editor): { upload: (file: File) => boolean; setElementTimeTraveling: <T extends ImageBlockElement | ImageInlineElement | ParagraphElement | OrderedListItemElement | UnorderedListItemElement | TaskListItemElement | HorizontalRuleElement | TableElement | TableRowElement | TableCellElement | TableContentElement | CodeBlockElement | CodeBlockLineElement | BlockQuoteElement | HeadingElement | AnchorElement, K extends keyof T = keyof T>(prev: RequireExactlyOne<T, K>, next: RequireExactlyOne<T, K>) => void; }; /** * Indicates an `Origin` that is uploading and the state of the Upload */ type UploadProgress = { /** * This is a URL but not the final upload URL. This is a URL that represents * a secure value in the form of a string that represents a location on the * user's computer. */ url: string; status: "progress"; sentBytes: number; totalBytes: number; }; /** * Indicates an `Origin` that has completed uploading */ type UploadComplete = { status: "success"; /** * This is a URL to the final place of the file */ url: string; }; /** * Indicates an `Origin` that has an error during uploading and the Error * message */ type UploadError = { status: "error"; url: string; message: string; }; type Upload = UploadProgress | UploadComplete | UploadError; /** * Creates an origin store using `zustand`. * * The purpose of this is to keep track of uploads and their progress but only * storing the key to the lookup in the Element itself. * * This is necessary so that the Element value stays the same even as the image * progress is updating during the upload. * * We want this because we don't want the progress updates to be part of the * document's edit history. Consider that a user executes an undo and it undoes * the progress of the upload. * * Te return value of `createUploadStore` is a React hook. * * The hook should be referenced as `useUploadStore` */ declare const createUploadStore: ({ uploads }?: { uploads: Record<string, Upload>; }) => zustand.UseBoundStore<zustand.StoreApi<UploadStore>>; /** * Types related to the `zustand` state-management library which we use to * store the state of uploads. */ type GetUpload = (id: string) => Upload; type SetUpload = (id: string, upload: Upload) => void; type UploadStore = { uploads: Record<string, Upload>; getUpload: GetUpload; setUpload: SetUpload; }; type UploadMethods = ReturnType<typeof createUploadMethods>; type UploadFileEvent = { hashUrl: string; file: File; }; type UploadImageFileEvent = UploadFileEvent & { width: number; height: number; }; type UploadFileSuccessEvent = UploadFileEvent & { url: string; }; type UploadImageFileSuccessEvent = UploadImageFileEvent & { url: string; }; type UploadEditor = { upload: UploadMethods & { client?: Client; onUploadIconClick: () => void; onUploadImageFile: (e: UploadImageFileEvent) => boolean; onUploadFile: (e: UploadFileEvent) => boolean; onUploadImageFileSuccess: (e: UploadImageFileSuccessEvent) => boolean; onUploadFileSuccess: (e: UploadFileSuccessEvent) => boolean; useUploadStore: ReturnType<typeof createUploadStore>; }; }; type UploadOptions = { upload?: { authToken?: string; onUploadButtonClick?: () => void; }; }; type UploadPluginCustomTypes = { Name: "upload"; Editor: UploadEditor; Options: UploadOptions; }; type AttachmentEditor = { attachment: {}; }; type AttachmentPluginCustomTypes = { Name: "attachment"; Editor: AttachmentEditor & UploadEditor; }; type ToolbarEditor = { toolbar: { height?: number; minHeight?: number; maxHeight?: number; showUploadButtons?: boolean; showCustomUploadButton?: boolean; }; }; type ToolbarOptions = { toolbar: { height?: number; minHeight?: number; maxHeight?: number; showUploadButtons?: boolean; showCustomUploadButton?: boolean; }; }; type ToolbarPluginCustomTypes = { Name: "toolbar"; Editor: ToolbarEditor; Options: ToolbarOptions; }; type ThemeEditor = { theme: true; }; type ThemePluginCustomTypes = { Name: "theme"; Editor: ThemeEditor; }; type NormalizeAfterDeleteEditor = { normalizeAfterDelete: true; }; type NormalizeAfterDeletePluginCustomTypes = { Name: "normalize-after-delete"; Editor: NormalizeAfterDeleteEditor; }; type AtomicDeleteEditor = { atomicDelete: true; }; type AtomicDeletePluginCustomTypes = { Name: "atomic-delete"; Editor: AtomicDeleteEditor; }; type InlineCodeEditor = { inlineCode: { toggleInlineCode: () => void; }; }; type InlineCodeText = { text: string; code?: true; }; type InlineCodePluginCustomTypes = { Name: "inline-code"; Editor: InlineCodeEditor; Text: InlineCodeText; }; declare function createMarksMethods(editor: Editor): { removeMarks: (args_0?: { at?: slate.Location | null | undefined; } | undefined) => void; toggleMark: (args_0: "text" | "prismToken" | "code" | "bold" | "italic" | "underline" | "sup" | "sub" | "strike", args_1?: "text" | "prismToken" | "code" | "bold" | "italic" | "underline" | "sup" | "sub" | "strike" | undefined, args_2?: { at?: slate.Location | null | undefined; } | undefined) => void; toggleBold: () => void; toggleItalic: () => void; toggleUnderline: () => void; toggleSup: () => void; toggleSub: () => void; toggleStrike: () => void; }; type MarksEditor = { /** * IMPORTANT: * * This cannot be named `marks` because it conflicts with the `editor.marks` * built into the BaseEditor.j */ marksPlugin: ReturnType<typeof createMarksMethods>; }; type MarksText = { text: string; bold?: true; italic?: true; underline?: true; sup?: true; sub?: true; strike?: true; }; type MarksPluginCustomTypes = { Name: "marks"; Editor: MarksEditor; Text: MarksText; }; /** * A type with generic for `convertElements` (below) to be used with the curry * method. TypeScript, unfortunately, cannot automatically curry generics for * us so we have to do it manually. */ type CurriedConvertElements = <T extends Element$2 = Element$2>(matchForToggle: (element: Element$2) => boolean, targetElement: TargetElement<T>, allowToggle: boolean) => void; declare function createConvertElementMethods(editor: Editor): { convertElementTypes: string[]; addConvertElementType: (type: "anchor" | "heading" | "block-quote" | "table" | "horizontal-rule" | "code-block" | "paragraph" | "image-block" | "image-inline" | "ordered-list-item" | "unordered-list-item" | "task-list-item" | "table-row" | "table-cell" | "table-content" | "code-block-line" | ("anchor" | "heading" | "block-quote" | "table" | "horizontal-rule" | "code-block" | "paragraph" | "image-block" | "image-inline" | "ordered-list-item" | "unordered-list-item" | "task-list-item" | "table-row" | "table-cell" | "table-content" | "code-block-line")[]) => void; isConvertibleElement: (element: ImageBlockElement | ImageInlineElement | ParagraphElement | OrderedListItemElement | UnorderedListItemElement | TaskListItemElement | HorizontalRuleElement | TableElement | TableRowElement | TableCellElement | TableContentElement | CodeBlockElement | CodeBlockLineElement | BlockQuoteElement | HeadingElement | AnchorElement) => boolean; convertElements: CurriedConvertElements; }; type ConvertElementEditor = { convertElement: ReturnType<typeof createConvertElementMethods>; }; type ConvertElementPluginCustomTypes = { Name: "convert-element"; Editor: ConvertElementEditor; }; declare function createPasteMarkdownMethods(editor: Editor): { pasteMarkdown: (markdown: string) => void; }; type PasteMarkdownMethods = ReturnType<typeof createPasteMarkdownMethods>; type PasteMarkdownEditor = { pasteMarkdown: PasteMarkdownMethods; }; type PasteMarkdownPluginCustomTypes = { Name: "paste-markdown"; Editor: PasteMarkdownEditor; }; declare function createFullscreenMethods(): { toggleFullscreen: () => void; isFullscreen: boolean; }; type FullscreenMethods = ReturnType<typeof createFullscreenMethods>; type FullscreenEditor = { fullscreen: FullscreenMethods; }; type FullscreenPluginCustomTypes = { Name: "fullscreen"; Editor: FullscreenEditor; }; type WysimarkEditor = { /** * Private state for the wysimark editor. */ wysimark: { prevValue?: { markdown: string; children: Descendant[]; }; }; /** * Public methods for the wysimark editor. */ getMarkdown: () => string; setMarkdown: (markdown: string) => void; }; declare const plugins: (TypedPlugin<FullscreenPluginCustomTypes> | TypedPlugin<PasteMarkdownPluginCustomTypes> | TypedPlugin<ConvertElementPluginCustomTypes> | TypedPlugin<AnchorPluginCustomTypes> | TypedPlugin<HeadingPluginCustomTypes> | TypedPlugin<MarksPluginCustomTypes> | TypedPlugin<InlineCodePluginCustomTypes> | TypedPlugin<BlockQuotePluginCustomTypes> | TypedPlugin<CodeBlockPluginCustomTypes> | TypedPlugin<TablePluginCustomTypes> | TypedPlugin<HorizontalRulePluginCustomTypes> | TypedPlugin<{ Name: "trailing-block"; Editor: { allowTrailingBlock: true; }; }> | TypedPlugin<ListPluginCustomTypes> | TypedPlugin<AtomicDeletePluginCustomTypes> | TypedPlugin<NormalizeAfterDeletePluginCustomTypes> | TypedPlugin<CollapsibleParagraphPluginCustomTypes> | TypedPlugin<ThemePluginCustomTypes> | TypedPlugin<ToolbarPluginCustomTypes> | TypedPlugin<UploadPluginCustomTypes> | TypedPlugin<AttachmentPluginCustomTypes> | TypedPlugin<ImagePluginCustomTypes> | TypedPlugin<PlaceholderPluginCustomTypes>)[]; type PluginTypes = ExtractCustomTypes<typeof plugins>; type CustomEditor = PluginTypes["Editor"]; type CustomElement = PluginTypes["Element"]; type CustomText = PluginTypes["Text"]; type Element$1 = CustomElement; type Text = CustomText; declare module "slate" { interface CustomTypes { Editor: BaseEditor & ReactEditor & HistoryEditor & CustomEditor & WysimarkEditor; Element: CustomElement; Text: BaseText & CustomText; } } declare function useEditor({ authToken, height, minHeight, maxHeight, onUploadButtonClick, }: { authToken?: string; height?: number; minHeight?: number; maxHeight?: number; onUploadButtonClick?: () => void; }): Editor & ReactEditor & WysimarkEditor; type EditableProps = { editor: Editor; value: string; onChange: (markdown: string) => void; throttleInMs?: number; placeholder?: string; className?: string; style?: React.CSSProperties; }; declare function Editable({ editor, value, onChange, throttleInMs, placeholder, className, style, }: EditableProps): react_jsx_runtime.JSX.Element; export { Editable, EditableProps, Element$1 as Element, Text, useEditor };