-
-
Save andykent/202e819c35bd720e73302849c76fab33 to your computer and use it in GitHub Desktop.
declare module 'slate-react' { | |
import * as Slate from 'slate' | |
import * as Immutable from 'immutable' | |
import { ReactNode } from 'react' | |
type RenderMarkProps = { | |
mark: { type: string }, | |
children: ReactNode | |
} | |
type RenderNodeProps = { | |
node: Slate.Block, | |
children: ReactNode, | |
attributes: any, | |
isSelected: boolean, | |
editor: Editor | |
} | |
interface Plugin { | |
onBeforeInput?: (event: Event, change: Slate.Change, editor: Editor) => any | void | |
onBlur?: (event: Event, change: Slate.Change, editor: Editor) => any | void | |
onFocus?: (event: Event, change: Slate.Change, editor: Editor) => any | void | |
onCopy?: (event: Event, change: Slate.Change, editor: Editor) => any | void | |
onCut?: (event: Event, change: Slate.Change, editor: Editor) => any | void | |
onDrop?: (event: Event, change: Slate.Change, editor: Editor) => any | void | |
onKeyDown?: (event: Event, change: Slate.Change, editor: Editor) => any | void | |
onKeyUp?: (event: Event, change: Slate.Change, editor: Editor) => any | void | |
onPaste?: (event: Event, change: Slate.Change, editor: Editor) => any | void | |
onSelect?: (event: Event, change: Slate.Change, editor: Editor) => any | void | |
onChange?: (change: Slate.Change) => any | void | |
renderEditor?: (props: { [key: string]: any }, editor: Editor) => any | void | |
schema?: Slate.Schema | |
decorateNode?: (node: Slate.Node) => Slate.Range[] | void | |
renderMark?: (props: RenderMarkProps) => any | |
renderNode?: (props: RenderNodeProps) => any | |
renderPlaceholder?: (props: { [key: string]: any }) => any | |
renderPortal?: (props: { [key: string]: any }) => any | |
validateNode?: (node: Node) => any | |
} | |
type BasicEditorProps = { | |
value: Slate.Value | |
autoCorrect?: boolean, | |
autoFocus?: boolean, | |
className?: string, | |
onChange?: (change: Slate.Change) => void, | |
placeholder?: any, | |
plugins?: Plugin[], | |
readOnly?: boolean, | |
role?: string, | |
schema?: Slate.Schema, | |
spellCheck?: boolean, | |
style?: { [key: string]: string }, | |
tabIndex?: number | |
} | |
type EditorProps = BasicEditorProps & Plugin | |
type EditorState = { | |
schema: Slate.Schema | |
value: Slate.Value | |
stack: Slate.Stack // [TODO] define stack | |
} | |
export class Editor extends React.Component<EditorProps, EditorState> { | |
schema: Slate.Schema | |
value: Slate.Value | |
stack: Slate.Stack | |
// Instance Methods | |
blur(): void | |
change(fn: (change: Slate.Change) => any | void): void | |
change(...args: any[]): void | |
focus(): void | |
} | |
type SlateType = 'fragment' | 'html' | 'node' | 'rich' | 'text' | |
export function findDOMNode(node: Slate.Node): Element | |
export function findDOMRange(range: Slate.Range): Range | |
export function findNode(element: Element, value: Slate.Value): Slate.Node | |
export function findRange(selection: Selection, value: Slate.Value): Slate.Range | |
export function getEventRange(event: Event, value: Slate.Value): Slate.Range | |
export function getEventTransfer(event: Event): { type: SlateType, node: Slate.Node } | |
export function setEventTransfer(event: Event, type: SlateType, data: any): void | |
} |
declare module 'slate' { | |
import * as Immutable from 'immutable' | |
export interface Data { | |
[key: string]: any | |
} | |
interface Rules { | |
[key: string]: Rule | |
} | |
interface KindsAndTypes { | |
kinds?: string[] | |
types?: string[] | |
} | |
type InvalidReason = 'child_kind_invalid' | 'child_required' | | |
'child_type_invalid' | 'child_unknown' | 'first_child_kind_invalid' | | |
'first_child_type_invalid' | 'last_child_kind_invalid' | 'last_child_type_invalid' | | |
'node_data_invalid' | 'node_is_void_invalid' | 'node_mark_invalid' | | |
'node_text_invalid' | 'parent_kind_invalid' | 'parent_type_invalid' | |
interface Rule { | |
data?: { | |
[key: string]: (v: any) => boolean | |
} | |
first?: KindsAndTypes | |
isVoid?: boolean | |
last?: KindsAndTypes | |
nodes?: { | |
kinds?: string[] | |
types?: string[] | |
min?: number | |
max?: number | |
}[] | |
normalize?: (change: Change, reason: InvalidReason, context: { [key: string]: any }) => void | |
parent?: KindsAndTypes | |
text?: RegExp | |
} | |
interface SchemaProperties { | |
document?: Rules | |
blocks?: Rules | |
inlines?: Rules | |
} | |
export class Schema extends Immutable.Record({}) { | |
document: Rules | |
blocks: Rules | |
inlines: Rules | |
static create(properties: SchemaProperties | Schema): Schema | |
static fromJSON(object: SchemaProperties): Schema | |
static isSchema(maybeSchema: any): boolean | |
toJSON(): SchemaProperties | |
} | |
interface ValueProperties { | |
document?: Document | |
selection?: Range | |
history?: History | |
schema?: Schema | |
data?: Data | |
decorations?: Immutable.List<Range> | null | |
} | |
interface ValueJSON { | |
document?: DocumentJSON | |
selection?: Range | |
history?: History | |
schema?: Schema | |
data?: Data | |
decorations?: Immutable.List<Range> | null | |
kind?: 'value' | |
} | |
export class Value extends Immutable.Record({}) { | |
document: Document | |
selection: Range | |
history: History | |
schema: Schema | |
data: Data | |
kind: 'value' | |
decorations: Immutable.List<Range> | null | |
readonly anchorText: Text | |
readonly focusText: Text | |
readonly startText: Text | |
readonly endText: Text | |
readonly anchorBlock: Block | |
readonly focusBlock: Block | |
readonly startBlock: Block | |
readonly endBlock: Block | |
readonly marks: Immutable.Set<Mark> | |
readonly activeMarks: Immutable.Set<Mark> | |
readonly blocks: Immutable.List<Block> | |
readonly fragement: Document | |
readonly inlines: Immutable.List<Inline> | |
readonly text: Immutable.List<Text> | |
readonly characters: Immutable.List<Character> | |
readonly hasUndos: boolean | |
readonly hasRedos: boolean | |
readonly anchorKey: string | |
readonly focusKey: string | |
readonly startKey: string | |
readonly endKey: string | |
readonly anchorOffset: number | |
readonly focusOffset: number | |
readonly startOffset: number | |
readonly endOffset: number | |
readonly isBackward: boolean | |
readonly isBlurred: boolean | |
readonly isCollapsed: boolean | |
readonly isExpanded: boolean | |
readonly isFocused: boolean | |
readonly isForward: boolean | |
static create(properties: ValueProperties | Value): Value | |
static fromJSON(properties: ValueJSON): Value | |
static isValue(maybeValue: any): boolean | |
change(): Change | |
toJSON(): ValueJSON | |
} | |
interface DocumentProperties { | |
nodes?: Immutable.List<Node> | Node[] | |
key?: string | |
data?: Immutable.Map<string, any> | { [key: string]: any } | |
} | |
interface DocumentJSON { | |
nodes?: NodeJSON[] | |
key?: string | |
data?: { [key: string]: any } | |
kind: 'document' | |
} | |
export class Document extends BaseNode { | |
kind: 'document' | |
static create(properties: DocumentProperties | Document | Immutable.List<Node> | Node[]): Document | |
static fromJSON(properties: DocumentProperties | Document): Document | |
static isDocument(maybeDocument: any): boolean | |
toJSON(): DocumentJSON | |
} | |
interface BlockProperties { | |
type: string | |
key?: string | |
nodes?: Immutable.List<Node> | |
isVoid?: boolean | |
data?: Immutable.Map<string, any> | { [key: string]: any } | |
} | |
interface BlockJSON { | |
type: string | |
key?: string | |
nodes?: Node[] | |
isVoid?: boolean | |
data?: { [key: string]: any } | |
kind: 'block' | |
} | |
export class Block extends BaseNode { | |
isVoid: boolean | |
kind: 'block' | |
static create(properties: BlockProperties | Block | string): Block | |
static createList(array: (BlockProperties | Block | string)[]): Immutable.List<Block> | |
static fromJSON(properties: BlockProperties | Block): Block | |
static isBlock(maybeBlock: any): boolean | |
toJSON(): BlockJSON | |
} | |
interface InlineProperties { | |
type: string | |
key?: string | |
nodes?: Immutable.List<Node> | |
isVoid?: boolean | |
data?: Immutable.Map<string, any> | { [key: string]: any } | |
} | |
interface InlineJSON { | |
type: string | |
key?: string | |
nodes?: Node[] | |
isVoid?: boolean | |
data?: { [key: string]: any } | |
kind: 'inline' | |
} | |
export class Inline extends BaseNode { | |
isVoid: boolean | |
kind: 'inline' | |
static create(properties: InlineProperties | Inline | string): Inline | |
static createList(array: (InlineProperties | Inline | string)[]): Immutable.List<Inline> | |
static fromJSON(properties: InlineProperties | Inline): Inline | |
static isInline(maybeInline: any): boolean | |
toJSON(): InlineJSON | |
} | |
interface TextProperties { | |
key?: string | |
characters: Immutable.List<Character> | |
} | |
interface TextJSON { | |
key?: string | |
characters: Character[] | |
kind: 'text' | |
} | |
export class Text extends Immutable.Record({}) { | |
kind: 'text' | |
characters: Immutable.List<Character> | |
static create(properties: TextProperties | Text | string): Text | |
static fromJSON(properties: TextProperties | Text): Text | |
static isText(maybeText: any): boolean | |
toJSON(): TextJSON | |
} | |
type Node = Document | Block | Inline | Text | |
type NodeJSON = DocumentJSON | BlockJSON | InlineJSON | TextJSON | |
class BaseNode extends Immutable.Record({}) { | |
data: Immutable.Map<string, any> | |
type: string | |
key: string | |
kind: 'document' | 'block' | 'inline' | 'text' | |
nodes: Immutable.List<Node> | |
readonly text: string | |
filterDescendants(iterator: (node: Node) => boolean): Immutable.List<Node> | |
findDescendants(iterator: (node: Node) => boolean): Node | null | |
getBlocksAtRange(range: Range): Immutable.List<Block> | |
getBlocks(): Immutable.List<Block> | |
getCharactersAtRange(range: Range): Immutable.List<Character> | |
getChild(key: string | Node): Node | null | |
getClosestBlock(key: string | Node): Block | null | |
getClosestInline(key: string | Node): Inline | null | |
getClosest(key: string | Node, match: (node: Node) => boolean): Node | null | |
getDepth(key: string | Node): number | |
getDescendant(key: string | Node): Node | null | |
getFirstText(): Text | null | |
getFragmentAtRange(range: Range): Document | |
getFurthest(key: string, iterator: (node: Node) => boolean): Node | null | |
getFurthestAncestor(key: string): Node | null | |
getFurthestBlock(key: string): Block | null | |
getFurthestInline(key: string): Inline | null | |
getFurthestOnlyChildAncestor(key: string): Node | null | |
getInlinesAtRange(range: Range): Immutable.List<Inline> | |
getLastText(): Text | null | |
getMarksAtRange(range: Range): Immutable.Set<Mark> | |
getNextBlock(key: string | Node): Block | null | |
getNextSibling(key: string | Node): Node | null | |
getNextText(key: string | Node): Text | null | |
getParent(key: string | Node): Node | void | |
getPreviousBlock(key: string | Node): Block | void | |
getPreviousSibling(key: string | Node): Node | void | |
getPreviousText(key: string | Node): Text | void | |
getTextAtOffset(offset: Number): Text | void | |
getTextsAtRange(range: Range): Immutable.List<Text> | |
hasChild(key: string | Node): boolean | |
} | |
interface CharacterProperties { | |
marks?: Immutable.Set<Mark> | Mark[] | |
text: string | |
} | |
export class Character extends Immutable.Record({}) { | |
kind: 'character' | |
marks: Immutable.Set<Mark> | |
text: string | |
static create(properties: CharacterProperties | Character | string): Character | |
static createList(array: (CharacterProperties | Character | string)[]): Immutable.List<Character> | |
static fromJSON(properties: CharacterProperties | Character): Character | |
static isCharacter(maybeCharacter: any): boolean | |
toJSON(): CharacterProperties | |
} | |
interface MarkProperties { | |
type: string | |
data?: Immutable.Map<string, any> | { [key: string]: any } | |
} | |
export class Mark extends Immutable.Record({}) { | |
kind: 'mark' | |
type: string | |
data: Immutable.Map<string, any> | |
static create(properties: MarkProperties | Mark | string): Mark | |
static createSet(array: (MarkProperties | Mark | string)[]): Immutable.Set<Mark> | |
static fromJSON(properties: MarkProperties | Mark): Mark | |
static isMark(maybeMark: any): boolean | |
toJSON(): MarkProperties | |
} | |
export class Change extends Immutable.Record({}) { | |
kind: 'change' | |
value: Value | |
operations: Immutable.List<Operation> | |
call(customChange: (change: Change, ...args: any[]) => Change): Change | |
applyOperations(operations: Operation[]): Change | |
applyOperation(operation: Operation): Change | |
// Current Value Changes | |
deleteBackward(n: number): Change | |
deleteForward(n: number): Change | |
delete(): Change | |
insertBlock(block: Block | BlockProperties | string): Change | |
insertFragment(fragment: Document): Change | |
insertInline(inline: Inline | InlineProperties): Change | |
insertText(text: string): Change | |
addMark(mark: Mark | MarkProperties | string): Change | |
setBlock(properties: BlockProperties | string): Change | |
setInline(properties: InlineProperties | string): Change | |
splitBlock(depth: number): Change | |
splitInline(depth: number): Change | |
removeMark(mark: Mark | MarkProperties | string): Change | |
toggleMark(mark: Mark | MarkProperties | string): Change | |
unwrapBlock(properties: BlockProperties | string): Change | |
unwrapInline(properties: InlineProperties | string): Change | |
wrapBlock(properties: BlockProperties | string): Change | |
wrapInline(properties: InlineProperties | string): Change | |
wrapText(prefix: string, suffix?: string): Change | |
// Selection Changes | |
blur(): Change | |
collapseToAnchor(): Change | |
collapseToFocus(): Change | |
collapseToSart(): Change | |
collapseToEnd(): Change | |
collapseToSartOf(node: Node): Change | |
collapseToEndOf(node: Node): Change | |
collapseToSartOfNextBlock(): Change | |
collapseToEndOfNextBlock(): Change | |
collapseToSartOfPreviousBlock(): Change | |
collapseToEndOfPreviousBlock(): Change | |
collapseToSartOfNextText(): Change | |
collapseToEndOfNextText(): Change | |
collapseToSartOfPreviousText(): Change | |
collapseToEndOfPreviousText(): Change | |
extend(n: number): Change | |
extendToStartOf(node: Node): Change | |
extendToEndOf(node: Node): Change | |
flip(): Change | |
focus(): Change | |
move(n: number): Change | |
moveStart(n: number): Change | |
moveEnd(n: number): Change | |
moveOffsetsTo(anchorOffset: number, focusOffset: number): Change | |
moveToRangeOf(node: Node): Change | |
select(properties: Range | RangeProperties): Change | |
selectAll(): Change | |
deselect(): Change | |
// Document Changes | |
deleteBackwardAtRange(range: Range, n: number): Change | |
deleteForwardAtRange(range: Range, n: number): Change | |
deleteAtRange(range: Range): Change | |
insertBlockAtRange(range: Range, block: Block | BlockProperties | string): Change | |
insertFragmentAtRange(range: Range, fragment: Document): Change | |
insertInlineAtRange(range: Range, inline: Inline | InlineProperties): Change | |
insertTextAtRange(range: Range, text: string): Change | |
addMarkAtRange(range: Range, mark: Mark | MarkProperties | string): Change | |
setBlockAtRange(range: Range, properties: BlockProperties | string): Change | |
setInlineAtRange(range: Range, properties: InlineProperties | string): Change | |
splitBlockAtRange(range: Range, depth: number): Change | |
splitInlineAtRange(range: Range, depth: number): Change | |
removeMarkAtRange(range: Range, mark: Mark | MarkProperties | string): Change | |
toggleMarkAtRange(range: Range, mark: Mark | MarkProperties | string): Change | |
unwrapBlockAtRange(range: Range, properties: BlockProperties | string): Change | |
unwrapInlineAtRange(range: Range, properties: InlineProperties | string): Change | |
wrapBlockAtRange(range: Range, properties: BlockProperties | string): Change | |
wrapInlineAtRange(range: Range, properties: InlineProperties | string): Change | |
wrapTextAtRange(range: Range, prefix: string, suffix?: string): Change | |
// Node Changes | |
addMarkByKey(key: string, offset: number, length: number, mark: Mark): Change | |
insertNodeByKey(key: string, index: number, node: Node): Change | |
insertFragmentByKey(key: string, index: number, fragment: Document): Change | |
insertTextByKey(key: string, offset: number, text: string, marks?: (Immutable.Set<Mark> | Mark[])): Change | |
moveNodeByKey(key: string, newKey: string, newIndex: number): Change | |
removeMarkByKey(key: string, offset: number, length: number, mark: Mark): Change | |
removeNodeByKey(key: string): Change | |
replaceNodeByKey(key: string, node: Node): Change | |
removeTextByKey(key: string, offset: number, length: number): Change | |
setMarkByKey(key: string, offset: number, length: number, mark: Mark, properties: MarkProperties): Change | |
setNodeByKey(key: string, properties: BlockProperties | InlineProperties | string): Change | |
splitNodeByKey(key: string, offset: number): Change | |
unwrapInlineByKey(key: string, properties: InlineProperties | string): Change | |
unwrapBlockByKey(key: string, properties: BlockProperties | string): Change | |
unwrapNodeByKey(key: string): Change | |
wrapInlineByKey(key: string, properties: InlineProperties | string): Change | |
wrapBlockByKey(key: string, properties: BlockProperties | string): Change | |
// History Changes | |
redo(): Change | |
undo(): Change | |
} | |
interface RangeProperties { | |
anchorKey?: string | null | |
anchorOffset?: number | |
focusKey?: string | null | |
focusOffset?: number | |
isFocused?: boolean | |
isBackward?: boolean | null | |
marks?: Immutable.Set<Mark> | null | |
} | |
export class Range extends Immutable.Record({}) { | |
kind: 'range' | |
anchorKey: string | null | |
anchorOffset: number | |
focusKey: string | null | |
focusOffset: number | |
isFocused: boolean | |
isBackward: boolean | null | |
marks: Immutable.Set<Mark> | null | |
readonly isBlurred: boolean | |
readonly isCollapsed: boolean | |
readonly isExpanded: boolean | |
readonly isForward: boolean | |
readonly startKey: string | |
readonly startOffset: number | |
readonly endKey: string | |
readonly endOffset: number | |
static create(properties: RangeProperties | Range): Range | |
static fromJSON(properties: RangeProperties): Range | |
static isRange(maybeRange: any): boolean | |
toJSON(): RangeProperties | |
hasAnchorAtStartOf(node: Node): boolean | |
hasFocusAtStartOf(node: Node): boolean | |
hasStartAtStartOf(node: Node): boolean | |
hasEndAtStartOf(node: Node): boolean | |
hasEdgeAtStartOf(node: Node): boolean | |
hasAnchorAtEndOf(node: Node): boolean | |
hasFocusAtEndOf(node: Node): boolean | |
hasStartAtEndOf(node: Node): boolean | |
hasEndAtEndOf(node: Node): boolean | |
hasEdgeAtEndOf(node: Node): boolean | |
hasAnchorBetween(node: Node, start: number, end: number): boolean | |
hasFocusBetween(node: Node, start: number, end: number): boolean | |
hasStartBetween(node: Node, start: number, end: number): boolean | |
hasEndBetween(node: Node, start: number, end: number): boolean | |
hasEdgeBetween(node: Node, start: number, end: number): boolean | |
hasAnchorAtIn(node: Node): boolean | |
hasFocusIn(node: Node): boolean | |
hasStartIn(node: Node): boolean | |
hasEndIn(node: Node): boolean | |
hasEdgeIn(node: Node): boolean | |
isAtStartOf(node: Node): boolean | |
isAtEndOf(node: Node): boolean | |
} | |
type Operation = InsertTextOperation | RemoveTextOperation | AddMarkOperation | | |
RemoveMarkOperation | SetMarkOperation | InsertNodeOperation | MergeNodeOperation | | |
MoveNodeOperation | RemoveNodeOperation | SetNodeOperation | SplitNodeOperation | | |
SetSelectionOperation | SetValueOperation | |
type InsertTextOperation = { | |
type: 'insert_text' | |
path: number[] | |
offset: number | |
text: string | |
marks: Mark[] | |
} | |
type RemoveTextOperation = { | |
type: 'remove_text' | |
path: number[] | |
offset: number | |
text: string | |
} | |
type AddMarkOperation = { | |
type: 'add_mark' | |
path: number[] | |
offset: number | |
length: number | |
mark: Mark | |
} | |
type RemoveMarkOperation = { | |
type: 'remove_mark' | |
path: number[] | |
offset: number | |
length: number | |
mark: Mark | |
} | |
type SetMarkOperation = { | |
type: 'set_mark' | |
path: number[] | |
offset: number | |
length: number | |
mark: Mark | |
properties: MarkProperties | |
} | |
type InsertNodeOperation = { | |
type: 'insert_node' | |
path: number[] | |
node: Node | |
} | |
type MergeNodeOperation = { | |
type: 'merge_node' | |
path: number[] | |
position: number | |
} | |
type MoveNodeOperation = { | |
type: 'move_node' | |
path: number[] | |
newPath: number[] | |
} | |
type RemoveNodeOperation = { | |
type: 'remove_node' | |
path: number[] | |
node: Node | |
} | |
type SetNodeOperation = { | |
type: 'set_node' | |
path: number[] | |
properties: BlockProperties | InlineProperties | TextProperties | |
} | |
type SplitNodeOperation = { | |
type: 'split_node' | |
path: number[] | |
position: number | |
target: number | |
} | |
type SetSelectionOperation = { | |
type: 'set_selection' | |
properties: RangeProperties | |
selection: Range | |
} | |
type SetValueOperation = { | |
type: 'set_value' | |
properties: ValueProperties | |
value: Value | |
} | |
export const Operations: { | |
apply: (value: Value, operation: Operation) => Value | |
invert: (operation: Operation) => Operation | |
} | |
export class Stack extends Immutable.Record({}) { | |
plugins: any[] | |
} | |
export function resetKeyGenerator(): void | |
} |
Thanks for the feedback @petester42, good spot.
I've made the suggested change as well as some other tweaks and fixes just now.
I'd be very happy to see them on @types I don't have the time submit them myself right now but if anyone else wanted to use these as a starting point to put together a PR I'd be very happy about that. If not hopefully I'll find some time to contribute them to the project soon.
Heads up, you have a typo in the collapseToSart*
rules, @andykent.
But, you just saved me hours and hours of work, and probably dozens of future bugs. Beers on me if you're ever in San Francisco. And either way, if you tell me a charity of your choice, I'll make a donation there too. (I'll default to Great Ormond Street if I don't hear back in a little while.)
Update 7th April 2018:
I fixed a couple of typos, updated the is* methods to be type guards, and added a couple of missing methods around getting text: https://gist.github.com/majelbstoat/e3f3a886f9f79ac6b5286b353b77f291
For the Rule interface I believe the nodes property should be an array like the following:
Have you thought about create a @types repo for these? They are really good.