Added new definition file for Draft-js v0.7.0.

Added tests.
Renamed old files by adding "-v0.2.2" suffix.
This commit is contained in:
d.rogozhny@gmail.com
2016-07-07 17:17:46 +03:00
parent 7ce2630b07
commit ee2b56f2b5
4 changed files with 1548 additions and 425 deletions

277
draft-js/draft-js-0.2.2.d.ts vendored Normal file
View File

@@ -0,0 +1,277 @@
// Type definitions for draft-js 0.2.2
// Project: https://github.com/facebook/draft-js
// Definitions by: Pavel Evsegneev <https://github.com/Ahineya>
// Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped
declare module "draft-js" {
namespace Draft {
interface IEditor {
new(): Editor
}
interface EditorState {
getCurrentContent(): ContentState,
getSelection(): SelectionState,
getCurrentInlineStyle(): any,
getBlockTree(): any,
createEmpty(decorator?: any): EditorState,
createWithContent(contentState: ContentState, decorator?: any): EditorState,
create(config: any): EditorState,
push(editorState: EditorState, contentState: ContentState, actionType: string): EditorState,
undo(editorState: EditorState): EditorState,
redo(editorState: EditorState): EditorState,
acceptSelection(editorState: EditorState, selectionState: SelectionState): EditorState,
forceSelection(editorState: EditorState, selectionState: SelectionState): EditorState,
moveFocusToEnd(editorState: EditorState): EditorState
}
interface CompositeDecorator {
getDecorations(): Array<any>,
getComponentForKey(): any,
getPropsForKey(): any
}
interface Entity {
create(type: string, mutability: string, data?: Object): EntityInstance,
add(instance: EntityInstance): string,
get(key: string): EntityInstance,
mergeData(key: string, toMerge: any): EntityInstance,
replaceData(key: string, newData: any): EntityInstance
}
interface EntityInstance {
getData(): any,
getKey(): string,
getMutability(): string
}
interface BlockMapBuilder {
createFromArray(blocks: Array<ContentBlock>): BlockMap
}
interface CharacterMetadata {
create(config?: any): CharacterMetadata,
applyStyle(record: CharacterMetadata,
style: string): CharacterMetadata,
removeStyle(record: CharacterMetadata,
style: string): CharacterMetadata,
applyEntity(record: CharacterMetadata,
entityKey?: string): CharacterMetadata,
getStyle(): any,
hasStyle(style: string): boolean,
getEntity(): string
}
interface IContentBlock {
new(draftContentBlock: any): ContentBlock;
}
interface ContentBlock {
key: string,
type: string,
text: string,
characterList: any,
depth: number,
getKey(): string,
getType(): string,
getText(): string,
getCharacterList(): any,
getLength(): number,
getDepth(): number,
getInlineStyleAt(offset: number): any,
getEntityAt(offset: number): string,
findStyleRanges(filterFn: Function, callback: Function): void,
findEntityRanges(filterFn: Function, callback: Function): void
}
interface ContentState {
createFromText(text: string): ContentState,
createFromBlockArray(blocks: Array<ContentBlock>): ContentState,
getBlockMap(): BlockMap,
getSelectionBefore(): SelectionState,
getSelectionAfter(): SelectionState,
getBlockForKey(key: string): ContentBlock,
getKeyBefore(key: string): string,
getKeyAfter(key: string): string,
getBlockBefore(key: string): ContentBlock,
getBlockAfter(key: string): ContentBlock,
getBlocksAsArray(): Array<ContentBlock>,
getPlainText(): string,
hasText(): boolean,
set(key: string, value: any): ContentState,
toJS(): any
}
interface ISelectionState {
new(draftSelectionState: any): SelectionState;
createEmpty(blockKey: string): SelectionState;
}
interface SelectionState {
getStartKey(): string,
getStartOffset(): number,
getEndKey(): string,
getEndOffset(): number,
getAnchorKey(): string,
getAnchorOffset(): number,
getFocusKey(): string,
getFocusOffset(): number,
getIsBackward(): boolean,
getHasFocus(): boolean,
isCollapsed(): boolean,
hasEdgeWithin(blockKey: string, start: number, end: number): boolean,
serialize(): string,
get(key: string): any,
set(key: string, value: any): SelectionState
}
interface BlockMap {
get(key: string): ContentBlock,
set(key: string, value: any): BlockMap,
delete(key: string): BlockMap,
find(cb: any): ContentBlock
}
interface Modifier {
replaceText(contentState: ContentState,
rangeToReplace: SelectionState,
text: string,
inlineStyle?: any,
entityKey?: string): ContentState,
insertText(contentState: ContentState,
targetRange: SelectionState,
text: string,
inlineStyle?: any,
entityKey?: string): ContentState,
moveText(contentState: ContentState,
removalRange: SelectionState,
targetRange: SelectionState): ContentState,
replaceWithFragment(contentState: ContentState,
targetRange: SelectionState,
fragment: BlockMap): ContentState,
removeRange(contentState: ContentState,
rangeToRemove: SelectionState,
removalDirection: string): ContentState,
splitBlock(contentState: ContentState,
selectionState: SelectionState): ContentState,
applyInlineStyle(contentState: ContentState,
selectionState: SelectionState,
inlineStyle: string): ContentState,
removeInlineStyle(contentState: ContentState,
selectionState: SelectionState,
inlineStyle: string): ContentState,
setBlockType(contentState: ContentState,
selectionState: SelectionState,
blockType: string): ContentState,
applyEntity(contentState: ContentState,
selectionState: SelectionState,
entityKey: string): ContentState
}
interface RichUtils {
currentBlockContainsLink(editorState: EditorState): boolean,
getCurrentBlockType(editor: EditorState): string,
handleKeyCommand(editorState: EditorState, command: string): any,
insertSoftNewline(editorState: EditorState): EditorState,
onBackspace(editorState: EditorState): EditorState,
onDelete(editorState: EditorState): EditorState,
onTab(event: Event, editorState: EditorState, maxDepth: number): EditorState,
toggleBlockType(editorState: EditorState, blockType: string): EditorState,
toggleCode(editorState: EditorState): EditorState,
toggleLink(editorState: EditorState, targetSelection: SelectionState, entityKey: string): EditorState,
tryToRemoveBlockStyle(editorState: EditorState): EditorState
}
interface EditorProps {
editorState: EditorState,
onChange(editorState: EditorState): void,
placeholder?: string,
textAlignment?: any,
blockRendererFn?: (ContentBlock: ContentBlock) => any,
blockStyleFn?: (ContentBlock: ContentBlock) => string,
customStyleMap?: any,
readOnly?: boolean,
spellCheck?: boolean,
stripPastedStyles?: boolean,
handleReturn?: (e: any) => boolean,
handleKeyCommand?: (command: string) => boolean,
handleBeforeInput?: (chars: string) => boolean,
handlePastedFiles?: (files: Array<Blob>) => boolean,
handleDroppedFiles?: (selection: SelectionState, files: Array<Blob>) => boolean,
handleDrop?: (selection: SelectionState, dataTransfer: any, isInternal: any) => boolean,
onEscape?: (e: any) => void,
onTab?: (e: any) => void,
onUpArrow?: (e: any) => void,
onDownArrow?: (e: any) => void,
suppressContentEditableWarning?: any,
onBlur?: (e: any) => void,
onFocus?: (e: any) => void
}
interface Editor {
props: EditorProps
state: any,
refs: any,
context: any,
setState(): any,
render(): any,
forceUpdate(): any
}
var Editor: IEditor;
var EditorState: EditorState;
var CompositeDecorator: CompositeDecorator;
var Entity: Entity;
var EntityInstance: EntityInstance;
var BlockMapBuilder: BlockMapBuilder;
var CharacterMetadata: CharacterMetadata;
var ContentBlock: IContentBlock;
var ContentState: ContentState;
var SelectionState: ISelectionState;
var Modifier: Modifier;
var RichUtils: RichUtils;
function convertFromRaw(rawState: any): Array<ContentBlock>;
function convertToRaw(contentState: ContentState): any;
function genKey(): string
}
export = Draft;
}

View File

@@ -0,0 +1,183 @@
/// <reference path="draft-js-0.2.2.d.ts" />
/// <reference path="../react/react-global.d.ts" />
/// <reference path="../react/react-dom.d.ts"/>
import * as React from "react";
import {
Editor,
EditorState,
Entity,
CharacterMetadata,
ContentBlock,
Modifier,
SelectionState,
genKey
} from "draft-js";
export class Tag extends React.Component<any, any> {
constructor(props: any) {
super(props);
}
remove = (): void => {
this.props.blockProps.removeBlock(this.props.block.getKey());
}
render () {
const {block} = this.props;
if (block.getEntityAt(0)) {
const data = Entity.get(block.getEntityAt(0)).getData();
return (
<div className="tag" contentEditable={false} >
{data.content.name}
<span className="remove" onClick={this.remove}>
<i className="material-icons">clear</i>
</span>
</div>
);
}
}
}
export class Hint extends React.Component<any, any> {
constructor(props: any) {
super(props);
}
render () {
const {block} = this.props;
if (block.getEntityAt(0)) {
const data = Entity.get(block.getEntityAt(0)).getData();
return (
<div className="hint" contentEditable={false} >
<span className="autocomplete">{this.props.blockProps.autocomplete}</span>
{data.content.text}
</div>
);
}
}
}
export function removeBlock(editorState: EditorState, blockKey: string) {
const content = editorState.getCurrentContent();
const targetRange = new SelectionState({
anchorKey: blockKey,
anchorOffset: 0,
focusKey: blockKey,
focusOffset: 1
});
const withoutTag = Modifier.removeRange(content, targetRange, "backward");
const resetBlock = Modifier.setBlockType(
withoutTag,
withoutTag.getSelectionAfter(),
"unstyled"
);
const newState = EditorState.push(editorState, resetBlock, "remove-range");
return EditorState.forceSelection(newState, resetBlock.getSelectionAfter());
}
export function applyEntity(editorState: EditorState, blockKey: string, entityKey: string) {
const content = editorState.getCurrentContent();
const targetRange = new SelectionState({
anchorKey: blockKey,
anchorOffset: 0,
focusKey: blockKey,
focusOffset: 1
});
const withNewEntity = Modifier.applyEntity(
content,
targetRange,
entityKey
)
const newState = EditorState.push(editorState, withNewEntity, "change-entity");
return EditorState.forceSelection(newState, withNewEntity.getSelectionAfter());
}
export function addTagBlock(content: any, editorState: EditorState): any {
const contentState = editorState.getCurrentContent();
const entityKey = Entity.create(
"TOKEN",
"IMMUTABLE",
{content}
);
const charData = CharacterMetadata.create({entity: entityKey});
const tag = new ContentBlock({
key: genKey(),
type: "tag",
text: "",
characterList: [],
});
const withTag = contentState.set("blockMap", contentState.getBlockMap().set(tag.key, tag));
const withRemovedPreviousBlock = withTag.set("blockMap", withTag.getBlockMap().delete(contentState.getSelectionBefore().getAnchorKey()))
const withTagBlock = EditorState.push(editorState, withRemovedPreviousBlock, "insert-fragment");
return withTagBlock;
}
export function addHintBlock(content: any, editorState: EditorState): any {
const contentState = editorState.getCurrentContent();
const selectionState = editorState.getSelection();
const entityKey = Entity.create(
"TOKEN",
"IMMUTABLE",
{content}
);
const charData = CharacterMetadata.create({entity: entityKey});
const hint = new ContentBlock({
key: genKey(),
type: "hint",
text: "",
characterList: [],
});
const empty = new ContentBlock({
key: genKey(),
type: "unstyled",
text: "",
characterList: [],
});
const withEmpty = contentState.set("blockMap", contentState.getBlockMap().set(empty.key, empty));
const withHint = withEmpty.set("blockMap", withEmpty.getBlockMap().set(hint.key, hint));
return {
editorState: EditorState.forceSelection(EditorState.push(editorState, withHint, "insert-fragment"), selectionState),
blockKey: hint.key
}
}
export class SearchField extends React.Component<any, any> {
public onChange: any;
constructor(props: any) {
super(props);
this.onChange = (editorState: EditorState) => {
this.setState({editorState})
};
}
render() {
const {editorState} = this.state;
return (
<Editor suppressContentEditableWarning
editorState={editorState}
onChange={this.onChange}
/>
)
}
}

View File

@@ -1,183 +1,184 @@
/// <reference path="draft-js.d.ts" />
/// <reference path="../react/react-global.d.ts" />
/// <reference path="../react/react-dom.d.ts"/>
///<reference path="draft-js.d.ts" />
///<reference path="../react/react.d.ts" />
///<reference path="../react/react-dom.d.ts"/>
// Using Rich text editor example as a test: https://github.com/facebook/draft-js/tree/master/examples/rich
import * as React from "react";
import * as ReactDOM from "react-dom";
import {Map} from "immutable";
import {
Editor,
EditorState,
Entity,
CharacterMetadata,
ContentBlock,
Modifier,
SelectionState,
genKey
} from "draft-js";
import {Editor, EditorState, RichUtils, DefaultDraftBlockRenderMap, ContentBlock} from 'draft-js';
export class Tag extends React.Component<any, any> {
constructor(props: any) {
super(props);
class RichEditorExample extends React.Component<{}, { editorState: EditorState }> {
constructor() {
super();
this.state = { editorState: EditorState.createEmpty() };
}
onChange: (editorState: EditorState) => void = (editorState: EditorState) => this.setState({ editorState });
handleKeyCommand: (command: string) => boolean = (command: string) => {
const {editorState} = this.state;
const newState = RichUtils.handleKeyCommand(editorState, command);
if (newState) {
this.onChange(newState);
return true;
}
remove = (): void => {
this.props.blockProps.removeBlock(this.props.block.getKey());
return false;
}
toggleBlockType: (blockType: string) => void = (blockType: string) => {
this.onChange(RichUtils.toggleBlockType(this.state.editorState, blockType));
}
toggleInlineStyle: (inlineStyle: string) => void = (inlineStyle: string) => {
this.onChange(RichUtils.toggleInlineStyle(this.state.editorState, inlineStyle));
}
render(): React.ReactElement<{}> {
// If the user changes block type before entering any text, we can
// either style the placeholder or hide it. Let's just hide it now.
let className = 'RichEditor-editor';
var contentState = this.state.editorState.getCurrentContent();
if (!contentState.hasText()) {
if (contentState.getBlockMap().first().getType() !== 'unstyled') {
className += ' RichEditor-hidePlaceholder';
}
}
render () {
const {block} = this.props;
if (block.getEntityAt(0)) {
const data = Entity.get(block.getEntityAt(0)).getData();
return (
<div className="tag" contentEditable={false} >
{data.content.name}
<span className="remove" onClick={this.remove}>
<i className="material-icons">clear</i>
</span>
</div>
);
}
}
}
export class Hint extends React.Component<any, any> {
constructor(props: any) {
super(props);
}
render () {
const {block} = this.props;
if (block.getEntityAt(0)) {
const data = Entity.get(block.getEntityAt(0)).getData();
return (
<div className="hint" contentEditable={false} >
<span className="autocomplete">{this.props.blockProps.autocomplete}</span>
{data.content.text}
</div>
);
}
}
}
export function removeBlock(editorState: EditorState, blockKey: string) {
const content = editorState.getCurrentContent();
const targetRange = new SelectionState({
anchorKey: blockKey,
anchorOffset: 0,
focusKey: blockKey,
focusOffset: 1
});
const withoutTag = Modifier.removeRange(content, targetRange, "backward");
const resetBlock = Modifier.setBlockType(
withoutTag,
withoutTag.getSelectionAfter(),
"unstyled"
return (
<div className="RichEditor-root">
<BlockStyleControls
editorState={this.state.editorState}
onToggle={this.toggleBlockType}
/>
<InlineStyleControls
editorState={this.state.editorState}
onToggle={this.toggleInlineStyle}
/>
<div className={className}>
<Editor
blockStyleFn={getBlockStyle}
customStyleMap={styleMap}
editorState={this.state.editorState}
handleKeyCommand={this.handleKeyCommand}
onChange={this.onChange}
placeholder="Tell a story..."
ref="editor"
spellCheck={true}
/>
</div>
</div>
);
const newState = EditorState.push(editorState, resetBlock, "remove-range");
return EditorState.forceSelection(newState, resetBlock.getSelectionAfter());
}
}
export function applyEntity(editorState: EditorState, blockKey: string, entityKey: string) {
const content = editorState.getCurrentContent();
// Custom overrides for "code" style.
const styleMap = {
CODE: {
backgroundColor: 'rgba(0, 0, 0, 0.05)',
fontFamily: '"Inconsolata", "Menlo", "Consolas", monospace',
fontSize: 16,
padding: 2,
},
};
const targetRange = new SelectionState({
anchorKey: blockKey,
anchorOffset: 0,
focusKey: blockKey,
focusOffset: 1
});
const withNewEntity = Modifier.applyEntity(
content,
targetRange,
entityKey
)
const newState = EditorState.push(editorState, withNewEntity, "change-entity");
return EditorState.forceSelection(newState, withNewEntity.getSelectionAfter());
function getBlockStyle(block: ContentBlock) {
switch (block.getType()) {
case 'blockquote': return 'RichEditor-blockquote';
default: return null;
}
}
export function addTagBlock(content: any, editorState: EditorState): any {
const contentState = editorState.getCurrentContent();
class StyleButton extends React.Component<{key: string, active: boolean, label: string, onToggle: (blockType: string) => void, style: string}, {}> {
constructor() {
super();
}
const entityKey = Entity.create(
"TOKEN",
"IMMUTABLE",
{content}
onToggle: (event: Event) => void = (event: Event) => {
event.preventDefault();
this.props.onToggle(this.props.style);
};
render(): React.ReactElement<{}> {
let className = 'RichEditor-styleButton';
if (this.props.active) {
className += ' RichEditor-activeButton';
}
return (
<span className={className} onMouseDown={this.onToggle}>
{this.props.label}
</span>
);
const charData = CharacterMetadata.create({entity: entityKey});
const tag = new ContentBlock({
key: genKey(),
type: "tag",
text: "",
characterList: [],
});
const withTag = contentState.set("blockMap", contentState.getBlockMap().set(tag.key, tag));
const withRemovedPreviousBlock = withTag.set("blockMap", withTag.getBlockMap().delete(contentState.getSelectionBefore().getAnchorKey()))
const withTagBlock = EditorState.push(editorState, withRemovedPreviousBlock, "insert-fragment");
return withTagBlock;
}
}
export function addHintBlock(content: any, editorState: EditorState): any {
const contentState = editorState.getCurrentContent();
const selectionState = editorState.getSelection();
const BLOCK_TYPES = [
{ label: 'H1', style: 'header-one' },
{ label: 'H2', style: 'header-two' },
{ label: 'H3', style: 'header-three' },
{ label: 'H4', style: 'header-four' },
{ label: 'H5', style: 'header-five' },
{ label: 'H6', style: 'header-six' },
{ label: 'Blockquote', style: 'blockquote' },
{ label: 'UL', style: 'unordered-list-item' },
{ label: 'OL', style: 'ordered-list-item' },
{ label: 'Code Block', style: 'code-block' },
];
const entityKey = Entity.create(
"TOKEN",
"IMMUTABLE",
{content}
);
const BlockStyleControls = (props: {editorState: EditorState, onToggle: (blockType: string) => void}) => {
const {editorState} = props;
const selection = editorState.getSelection();
const blockType = editorState
.getCurrentContent()
.getBlockForKey(selection.getStartKey())
.getType();
const charData = CharacterMetadata.create({entity: entityKey});
const hint = new ContentBlock({
key: genKey(),
type: "hint",
text: "",
characterList: [],
});
const empty = new ContentBlock({
key: genKey(),
type: "unstyled",
text: "",
characterList: [],
});
return (
<div className="RichEditor-controls">
{BLOCK_TYPES.map((type) =>
<StyleButton
key={type.label}
active={type.style === blockType}
label={type.label}
onToggle={props.onToggle}
style={type.style}
/>
) }
</div>
);
};
const withEmpty = contentState.set("blockMap", contentState.getBlockMap().set(empty.key, empty));
const withHint = withEmpty.set("blockMap", withEmpty.getBlockMap().set(hint.key, hint));
return {
editorState: EditorState.forceSelection(EditorState.push(editorState, withHint, "insert-fragment"), selectionState),
blockKey: hint.key
}
var INLINE_STYLES = [
{ label: 'Bold', style: 'BOLD' },
{ label: 'Italic', style: 'ITALIC' },
{ label: 'Underline', style: 'UNDERLINE' },
{ label: 'Monospace', style: 'CODE' },
];
}
const InlineStyleControls = (props: {editorState: EditorState, onToggle: (blockType: string) => void}) => {
var currentStyle = props.editorState.getCurrentInlineStyle();
return (
<div className="RichEditor-controls">
{INLINE_STYLES.map(type =>
<StyleButton
key={type.label}
active={currentStyle.has(type.style) }
label={type.label}
onToggle={props.onToggle}
style={type.style}
/>
) }
</div>
);
};
export class SearchField extends React.Component<any, any> {
public onChange: any;
constructor(props: any) {
super(props);
this.onChange = (editorState: EditorState) => {
this.setState({editorState})
};
}
render() {
const {editorState} = this.state;
return (
<Editor suppressContentEditableWarning
editorState={editorState}
onChange={this.onChange}
/>
)
}
}
ReactDOM.render(
<RichEditorExample />,
document.getElementById('target')
);

1192
draft-js/draft-js.d.ts vendored

File diff suppressed because it is too large Load Diff