mirror of
https://github.com/wassname/DefinitelyTyped.git
synced 2026-09-10 11:40:16 +08:00
Add definitions for React DnD
Adding React DnD type definitions for React DnD v1.1.4, which is the latest version. Paired with @vsiao on parts of this
This commit is contained in:
@@ -0,0 +1,260 @@
|
||||
///<reference path="react-dnd.d.ts" />
|
||||
"use strict";
|
||||
|
||||
// Test adapted from the ReactDnD chess game tutorial:
|
||||
// http://gaearon.github.io/react-dnd/docs-tutorial.html
|
||||
|
||||
import React = require("react");
|
||||
import ReactDnd = require("react-dnd");
|
||||
|
||||
var r = React.DOM;
|
||||
|
||||
import DragSource = ReactDnd.DragSource;
|
||||
import DropTarget = ReactDnd.DropTarget;
|
||||
import DragDropContext = ReactDnd.DragDropContext;
|
||||
import HTML5Backend = require('react-dnd/modules/backends/HTML5');
|
||||
|
||||
// Game Component
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
module Game {
|
||||
var knightPosition = [0, 0];
|
||||
var observer: any = null;
|
||||
|
||||
function emitChange() {
|
||||
observer(knightPosition);
|
||||
}
|
||||
|
||||
export function observe(o: any) {
|
||||
if (observer) {
|
||||
throw new Error("Multiple observers not implemented.");
|
||||
}
|
||||
|
||||
observer = o;
|
||||
emitChange();
|
||||
}
|
||||
|
||||
export function moveKnight(toX: number, toY: number) {
|
||||
knightPosition = [toX, toY];
|
||||
emitChange();
|
||||
}
|
||||
|
||||
export function canMoveKnight(toX: number, toY: number) {
|
||||
const x = knightPosition[0];
|
||||
const y = knightPosition[1];
|
||||
const dx = toX - x;
|
||||
const dy = toY - y;
|
||||
|
||||
return (Math.abs(dx) === 2 && Math.abs(dy) === 1) ||
|
||||
(Math.abs(dx) === 1 && Math.abs(dy) === 2);
|
||||
}
|
||||
}
|
||||
|
||||
var ItemTypes = {
|
||||
KNIGHT: "knight"
|
||||
};
|
||||
|
||||
// Knight Component
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
module Knight {
|
||||
interface KnightP extends React.Props<Knight> {
|
||||
connectDragSource: ReactDnd.ConnectDragSource;
|
||||
connectDragPreview: ReactDnd.ConnectDragPreview;
|
||||
isDragging: boolean;
|
||||
}
|
||||
|
||||
var knightSource: ReactDnd.DragSourceSpec<KnightP> = {
|
||||
beginDrag: (props) => {
|
||||
return {};
|
||||
}
|
||||
};
|
||||
|
||||
function knightCollect(connect: ReactDnd.DragSourceConnector, monitor: ReactDnd.DragSourceMonitor) {
|
||||
return {
|
||||
connectDragSource: connect.dragSource(),
|
||||
connectDragPreview: connect.dragPreview(),
|
||||
isDragging: monitor.isDragging()
|
||||
};
|
||||
}
|
||||
|
||||
export class Knight extends React.Component<KnightP, {}> {
|
||||
static create = React.createFactory(Knight);
|
||||
|
||||
componentDidMount() {
|
||||
var img = HTML5Backend.getEmptyImage();
|
||||
img.onload = () => this.props.connectDragPreview(img);
|
||||
}
|
||||
|
||||
render() {
|
||||
return this.props.connectDragSource(
|
||||
r.div({
|
||||
style: {
|
||||
opacity: this.props.isDragging ? 0.5 : 1,
|
||||
fontSize: 25,
|
||||
fontWeight: 'bold',
|
||||
cursor: 'move'
|
||||
}
|
||||
}, "♘")
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export var DndKnight = DragSource(ItemTypes.KNIGHT, knightSource, knightCollect)(Knight);
|
||||
export var create = React.createFactory(DndKnight);
|
||||
}
|
||||
|
||||
// Square Component
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
module Square {
|
||||
interface SquareP extends React.Props<Square> {
|
||||
black: boolean;
|
||||
}
|
||||
|
||||
export class Square extends React.Component<SquareP, {}> {
|
||||
render() {
|
||||
var fill = this.props.black ? 'black' : 'white';
|
||||
return r.div({
|
||||
style: {
|
||||
backgroundColor: fill
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
export var create = React.createFactory(Square);
|
||||
}
|
||||
|
||||
// BoardSquare Component
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
module BoardSquare {
|
||||
interface BoardSquareP extends React.Props<BoardSquare> {
|
||||
x: number;
|
||||
y: number;
|
||||
connectDropTarget?: ReactDnd.ConnectDropTarget;
|
||||
isOver?: boolean;
|
||||
canDrop?: boolean;
|
||||
}
|
||||
|
||||
var boardSquareTarget: ReactDnd.DropTargetSpec<BoardSquareP> = {
|
||||
canDrop: (props) => Game.canMoveKnight(props.x, props.y),
|
||||
drop: (props) => Game.moveKnight(props.x, props.y)
|
||||
};
|
||||
|
||||
function boardSquareCollect(connect: ReactDnd.DropTargetConnector, monitor: ReactDnd.DropTargetMonitor) {
|
||||
return {
|
||||
connectDropTarget: connect.dropTarget(),
|
||||
isOver: monitor.isOver(),
|
||||
canDrop: monitor.canDrop()
|
||||
};
|
||||
}
|
||||
|
||||
export class BoardSquare extends React.Component<BoardSquareP, {}> {
|
||||
private _renderOverlay = (color: string) => {
|
||||
return r.div({
|
||||
style: {
|
||||
position: 'absolute',
|
||||
top: 0,
|
||||
left: 0,
|
||||
height: '100%',
|
||||
width: '100%',
|
||||
zIndex: 1,
|
||||
opacity: 0.5,
|
||||
backgroundColor: color
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
render() {
|
||||
var black = (this.props.x + this.props.y) % 2 === 1;
|
||||
var isOver = this.props.isOver;
|
||||
var canDrop = this.props.canDrop;
|
||||
|
||||
return this.props.connectDropTarget(
|
||||
r.div({
|
||||
style: {
|
||||
position: 'relative',
|
||||
width: '100%',
|
||||
height: '100%'
|
||||
},
|
||||
children: [
|
||||
Square.create({
|
||||
black: black
|
||||
}),
|
||||
isOver && !canDrop ? this._renderOverlay('red') : null,
|
||||
!isOver && canDrop ? this._renderOverlay('yellow') : null,
|
||||
isOver && canDrop ? this._renderOverlay('green') : null
|
||||
]
|
||||
})
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export var DndBoardSquare = DropTarget(ItemTypes.KNIGHT, boardSquareTarget, boardSquareCollect)(BoardSquare);
|
||||
export var create = React.createFactory(DndBoardSquare);
|
||||
}
|
||||
|
||||
// Board Component
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
module Board {
|
||||
interface BoardP extends React.Props<Board> {
|
||||
knightPosition: number[];
|
||||
}
|
||||
|
||||
export class Board extends React.Component<BoardP, {}> {
|
||||
private _renderPiece = (x: number, y: number) => {
|
||||
var knightX = this.props.knightPosition[0];
|
||||
var knightY = this.props.knightPosition[1];
|
||||
return x === knightX && y === knightY ?
|
||||
Knight.create() :
|
||||
null;
|
||||
};
|
||||
|
||||
private _renderSquare = (i: number) => {
|
||||
var x = i % 8;
|
||||
var y = Math.floor(i / 8);
|
||||
|
||||
return r.div({
|
||||
key: i,
|
||||
style: {
|
||||
width: '12.5%',
|
||||
height: '12.5%'
|
||||
}
|
||||
}, BoardSquare.create({
|
||||
x: x,
|
||||
y: y
|
||||
}, this._renderPiece(x, y)));
|
||||
};
|
||||
|
||||
render() {
|
||||
var squares: React.DOMElement<React.HTMLAttributes>[] = [];
|
||||
for (let i = 0; i < 64; i++) {
|
||||
squares.push(this._renderSquare(i));
|
||||
}
|
||||
|
||||
return r.div({
|
||||
style: {
|
||||
width: '100%',
|
||||
height: '100%',
|
||||
display: 'flex',
|
||||
flexWrap: 'wrap'
|
||||
},
|
||||
children: squares
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
var DndBoard = DragDropContext(HTML5Backend)(Board);
|
||||
export var create = React.createFactory(DndBoard);
|
||||
}
|
||||
|
||||
|
||||
// Render the Board Component
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
Board.create({
|
||||
knightPosition: [0, 0]
|
||||
});
|
||||
Vendored
+172
@@ -0,0 +1,172 @@
|
||||
// Type definitions for React DnD v1.1.4
|
||||
// Project: https://github.com/gaearon/react-dnd
|
||||
// Definitions by: Asana <https://asana.com>
|
||||
// Definitions: https://github.com/borisyankov/DefinitelyTyped
|
||||
|
||||
///<reference path='../react/react.d.ts' />
|
||||
|
||||
declare module __ReactDnd {
|
||||
import React = __React;
|
||||
|
||||
// Decorated React Components
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
class ContextComponent<P, S> extends React.Component<P, S> {
|
||||
getDecoratedComponentInstance(): React.Component<P, S>;
|
||||
// Note: getManager is not yet documented on the React DnD docs.
|
||||
getManager(): any;
|
||||
}
|
||||
|
||||
class DndComponent<P, S> extends React.Component<P, S> {
|
||||
getDecoratedComponentInstance(): React.Component<P, S>;
|
||||
getHandlerId(): Identifier;
|
||||
}
|
||||
|
||||
interface ContextComponentClass<P> extends React.ComponentClass<P> {
|
||||
new(props?: P, context?: any): ContextComponent<P, any>;
|
||||
DecoratedComponent: React.ComponentClass<P>;
|
||||
}
|
||||
|
||||
interface DndComponentClass<P> extends React.ComponentClass<P> {
|
||||
new(props?: P, context?: any): DndComponent<P, any>;
|
||||
DecoratedComponent: React.ComponentClass<P>;
|
||||
}
|
||||
|
||||
// Top-level API
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
export function DragSource<P>(
|
||||
type: Identifier | ((props: P) => Identifier),
|
||||
spec: DragSourceSpec<P>,
|
||||
collect: (connect: DragSourceConnector, monitor: DragSourceMonitor) => Object,
|
||||
options?: DndOptions<P>
|
||||
): (componentClass: React.ComponentClass<P>) => DndComponentClass<P>;
|
||||
|
||||
export function DropTarget<P>(
|
||||
types: Identifier | Identifier[] | ((props: P) => Identifier | Identifier[]),
|
||||
spec: DropTargetSpec<P>,
|
||||
collect: (connect: DropTargetConnector, monitor: DropTargetMonitor) => Object,
|
||||
options?: DndOptions<P>
|
||||
): (componentClass: React.ComponentClass<P>) => DndComponentClass<P>;
|
||||
|
||||
export function DragDropContext<P>(
|
||||
backend: Backend
|
||||
): (componentClass: React.ComponentClass<P>) => ContextComponentClass<P>;
|
||||
|
||||
// TODO: Add exported function for DragLayer.
|
||||
// The React DnD docs say that this is an advanced feature that is only
|
||||
// necessary when performing custom rendering or when using a custom
|
||||
// backend.
|
||||
|
||||
// Shared
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
// The React DnD docs say that this can also be the ES6 Symbol.
|
||||
type Identifier = string;
|
||||
|
||||
interface ClientOffset {
|
||||
x: number;
|
||||
y: number;
|
||||
}
|
||||
|
||||
interface DndOptions<P> {
|
||||
arePropsEqual?(props: P, otherProps: P): boolean;
|
||||
}
|
||||
|
||||
// DragSource
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
interface DragSourceSpec<P> {
|
||||
beginDrag(props: P, monitor?: DragSourceMonitor, component?: React.Component<P, any>): Object;
|
||||
endDrag?(props: P, monitor?: DragSourceMonitor, component?: React.Component<P, any>): void;
|
||||
canDrag?(props: P, monitor?: DragSourceMonitor): boolean;
|
||||
isDragging?(props: P, monitor?: DragSourceMonitor): boolean;
|
||||
}
|
||||
|
||||
class DragSourceMonitor {
|
||||
canDrag(): boolean;
|
||||
isDragging(): boolean;
|
||||
getItemType(): Identifier;
|
||||
getItem(): Object;
|
||||
getDropResult(): Object;
|
||||
didDrop(): boolean;
|
||||
getInitialClientOffset(): ClientOffset;
|
||||
getInitialSourceClientOffset(): ClientOffset;
|
||||
getClientOffset(): ClientOffset;
|
||||
getDifferenceFromInitialOffset(): ClientOffset;
|
||||
getSourceClientOffset(): ClientOffset;
|
||||
}
|
||||
|
||||
class DragSourceConnector {
|
||||
dragSource(): ConnectDragSource;
|
||||
dragPreview(): ConnectDragPreview;
|
||||
}
|
||||
|
||||
interface DragElementWrapper<O> {
|
||||
<P>(elementOrNode: React.ReactElement<P>, options?: O): React.ReactElement<P>;
|
||||
}
|
||||
|
||||
interface DragSourceOptions {
|
||||
dropEffect?: string;
|
||||
}
|
||||
|
||||
interface DragPreviewOptions {
|
||||
captureDraggingState?: boolean;
|
||||
anchorX?: number;
|
||||
anchorY?: number;
|
||||
}
|
||||
|
||||
type ConnectDragSource = DragElementWrapper<DragSourceOptions>;
|
||||
type ConnectDragPreview = DragElementWrapper<DragPreviewOptions>;
|
||||
|
||||
/// DropTarget
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
interface DropTargetSpec<P> {
|
||||
drop?(props: P, monitor?: DropTargetMonitor, component?: React.Component<P, any>): Object|void;
|
||||
hover?(props: P, monitor?: DropTargetMonitor, component?: React.Component<P, any>): void;
|
||||
canDrop?(props: P, monitor?: DropTargetMonitor): boolean;
|
||||
}
|
||||
|
||||
class DropTargetMonitor {
|
||||
canDrop(): boolean;
|
||||
isOver(options?: { shallow: boolean }): boolean;
|
||||
getItemType(): Identifier;
|
||||
getItem(): Object;
|
||||
getDropResult(): Object;
|
||||
didDrop(): boolean;
|
||||
getInitialClientOffset(): ClientOffset;
|
||||
getInitialSourceClientOffset(): ClientOffset;
|
||||
getClientOffset(): ClientOffset;
|
||||
getDifferenceFromInitialOffset(): ClientOffset;
|
||||
getSourceClientOffset(): ClientOffset;
|
||||
}
|
||||
|
||||
class DropTargetConnector {
|
||||
dropTarget(): ConnectDropTarget;
|
||||
}
|
||||
|
||||
type ConnectDropTarget = <P>(elementOrNode: React.ReactElement<P>) => React.ReactElement<P>;
|
||||
|
||||
/// Backend
|
||||
/// ---------------------------------------------------------------------
|
||||
|
||||
// TODO: Fill in the Backend interface.
|
||||
// The React DnD docs do not cover this, and this is only needed for
|
||||
// creating custom backends (i.e. not using the built-in HTML5Backend).
|
||||
interface Backend {}
|
||||
}
|
||||
|
||||
declare module "react-dnd" {
|
||||
export = __ReactDnd;
|
||||
}
|
||||
|
||||
declare module "react-dnd/modules/backends/HTML5" {
|
||||
enum _NativeTypes { FILE, URL, TEXT }
|
||||
class HTML5Backend implements __ReactDnd.Backend {
|
||||
static getEmptyImage(): any; // Image
|
||||
static NativeTypes: _NativeTypes;
|
||||
}
|
||||
|
||||
export = HTML5Backend;
|
||||
}
|
||||
Reference in New Issue
Block a user