UNPKG

19.6 kBTypeScriptView Raw
1// Type definitions for react-beautiful-dnd 13.1
2// Project: https://github.com/atlassian/react-beautiful-dnd
3// Definitions by: varHarrie <https://github.com/varHarrie>
4// Bradley Ayers <https://github.com/bradleyayers>
5// Austin Turner <https://github.com/paustint>
6// Mark Nelissen <https://github.com/marknelissen>
7// Enrico Boccadifuoco <https://github.com/enricoboccadifuoco>
8// Taeheon Kim <https://github.com/lonyele>
9// Kanitkorn Sujautra <https://github.com/lukyth>
10// Arun George <https://github.com/aruniverse>
11// Nick Garlis <https://github.com/nickgarlis>
12// Brian Powers <https://github.com/brianspowers>
13// Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped
14// TypeScript Version: 2.8
15// Refer to https://github.com/atlassian/react-beautiful-dnd/blob/master/src/types.js
16
17import * as React from 'react';
18
19export type Omit<T, K extends keyof T> = Pick<T, Exclude<keyof T, K>>;
20
21export interface Position {
22 x: number;
23 y: number;
24}
25
26export interface BoxModel {
27 // content + padding + border + margin
28 marginBox: Rect;
29 // content + padding + border
30 borderBox: Rect;
31 // content + padding
32 paddingBox: Rect;
33 // content
34 contentBox: Rect;
35 // for your own consumption
36 border: Spacing;
37 padding: Spacing;
38 margin: Spacing;
39}
40
41// This is an extension of DOMRect and ClientRect
42export interface Rect {
43 // ClientRect
44 top: number;
45 right: number;
46 bottom: number;
47 left: number;
48 width: number;
49 height: number;
50 // DOMRect
51 x: number;
52 y: number;
53 // Rect
54 center: Position;
55}
56
57export interface Spacing {
58 top: number;
59 right: number;
60 bottom: number;
61 left: number;
62}
63
64/**
65 * IDs
66 */
67
68export type Id = string;
69export type DraggableId = Id;
70export type DroppableId = Id;
71export type TypeId = Id;
72export type ContextId = Id;
73export type ElementId = Id;
74
75export type DroppableMode = 'standard' | 'virtual';
76
77export interface DroppableDescriptor {
78 id: DroppableId;
79 type: TypeId;
80 mode: DroppableMode;
81}
82
83export interface DraggableDescriptor {
84 id: DraggableId;
85 index: number;
86 // Inherited from Droppable
87 droppableId: DroppableId;
88 // This is technically redundant but it avoids
89 // needing to look up a parent droppable just to get its type
90 type: TypeId;
91}
92
93export interface DraggableOptions {
94 canDragInteractiveElements: boolean;
95 shouldRespectForcePress: boolean;
96 isEnabled: boolean;
97}
98
99export type Direction = 'horizontal' | 'vertical';
100
101export interface VerticalAxis {
102 direction: 'vertical';
103 line: 'y';
104 start: 'top';
105 end: 'bottom';
106 size: 'height';
107 crossAxisLine: 'x';
108 crossAxisStart: 'left';
109 crossAxisEnd: 'right';
110 crossAxisSize: 'width';
111}
112
113export interface HorizontalAxis {
114 direction: 'horizontal';
115 line: 'x';
116 start: 'left';
117 end: 'right';
118 size: 'width';
119 crossAxisLine: 'y';
120 crossAxisStart: 'top';
121 crossAxisEnd: 'bottom';
122 crossAxisSize: 'height';
123}
124
125export type Axis = VerticalAxis | HorizontalAxis;
126
127export interface ScrollSize {
128 scrollHeight: number;
129 scrollWidth: number;
130}
131
132export interface ScrollDifference {
133 value: Position;
134 // The actual displacement as a result of a scroll is in the opposite
135 // direction to the scroll itself. When scrolling down items are displaced
136 // upwards. This value is the negated version of the 'value'
137 displacement: Position;
138}
139
140export interface ScrollDetails {
141 initial: Position;
142 current: Position;
143 // the maximum allowable scroll for the frame
144 max: Position;
145 diff: ScrollDifference;
146}
147
148export interface Placeholder {
149 client: BoxModel;
150 tagName: string;
151 display: string;
152}
153
154export interface DraggableDimension {
155 descriptor: DraggableDescriptor;
156 // the placeholder for the draggable
157 placeholder: Placeholder;
158 // relative to the viewport when the drag started
159 client: BoxModel;
160 // relative to the whole page
161 page: BoxModel;
162 // how much displacement the draggable causes
163 // this is the size of the marginBox
164 displaceBy: Position;
165}
166
167export interface Scrollable {
168 // This is the window through which the droppable is observed
169 // It does not change during a drag
170 pageMarginBox: Rect;
171 // Used for comparision with dynamic recollecting
172 frameClient: BoxModel;
173 scrollSize: ScrollSize;
174 // Whether or not we should clip the subject by the frame
175 // Is controlled by the ignoreContainerClipping prop
176 shouldClipSubject: boolean;
177 scroll: ScrollDetails;
178}
179
180export interface PlaceholderInSubject {
181 // might not actually be increased by
182 // placeholder if there is no required space
183 increasedBy?: Position | undefined;
184 placeholderSize: Position;
185 // max scroll before placeholder added
186 // will be null if there was no frame
187 oldFrameMaxScroll?: Position | undefined;
188}
189
190export interface DroppableSubject {
191 // raw, unchanging
192 page: BoxModel;
193 withPlaceholder?: PlaceholderInSubject | undefined;
194 // The hitbox for a droppable
195 // - page margin box
196 // - with scroll changes
197 // - with any additional droppable placeholder
198 // - clipped by frame
199 // The subject will be null if the hit area is completely empty
200 active?: Rect | undefined;
201}
202
203export interface DroppableDimension {
204 descriptor: DroppableDescriptor;
205 axis: Axis;
206 isEnabled: boolean;
207 isCombineEnabled: boolean;
208 // relative to the current viewport
209 client: BoxModel;
210 // relative to the whole page
211 isFixedOnPage: boolean;
212 // relative to the page
213 page: BoxModel;
214 // The container of the droppable
215 frame?: Scrollable | undefined;
216 // what is visible through the frame
217 subject: DroppableSubject;
218}
219
220export interface DraggableLocation {
221 droppableId: DroppableId;
222 index: number;
223}
224
225export interface DraggableIdMap {
226 [id: string]: true;
227}
228
229export interface DroppableIdMap {
230 [id: string]: true;
231}
232
233export interface DraggableDimensionMap {
234 [key: string]: DraggableDimension;
235}
236export interface DroppableDimensionMap {
237 [key: string]: DroppableDimension;
238}
239
240export interface Displacement {
241 draggableId: DraggableId;
242 shouldAnimate: boolean;
243}
244
245export interface DisplacementMap {
246 [key: string]: Displacement;
247}
248
249export interface DisplacedBy {
250 value: number;
251 point: Position;
252}
253
254// details of the item that is being combined with
255export interface Combine {
256 draggableId: DraggableId;
257 droppableId: DroppableId;
258}
259
260export interface DisplacementGroups {
261 all: DraggableId[];
262 visible: DisplacementMap;
263 invisible: DraggableIdMap;
264}
265
266export interface ReorderImpact {
267 type: 'REORDER';
268 destination: DraggableLocation;
269}
270
271export interface CombineImpact {
272 type: 'COMBINE';
273 combine: Combine;
274}
275
276export type ImpactLocation = ReorderImpact | CombineImpact;
277
278export interface Displaced {
279 forwards: DisplacementGroups;
280 backwards: DisplacementGroups;
281}
282
283export interface DragImpact {
284 displaced: DisplacementGroups;
285 displacedBy: DisplacedBy;
286 at?: ImpactLocation | undefined;
287}
288
289export interface ClientPositions {
290 // where the user initially selected
291 // This point is not used to calculate the impact of a dragging item
292 // It is used to calculate the offset from the initial selection point
293 selection: Position;
294 // the current center of the item
295 borderBoxCenter: Position;
296 // how far the item has moved from its original position
297 offset: Position;
298}
299
300export interface PagePositions {
301 selection: Position;
302 borderBoxCenter: Position;
303 // how much the page position has changed from the initial
304 offset: Position;
305}
306
307// There are two seperate modes that a drag can be in
308// FLUID: everything is done in response to highly granular input (eg mouse)
309// SNAP: items move in response to commands (eg keyboard);
310export type MovementMode = 'FLUID' | 'SNAP';
311
312export interface DragPositions {
313 client: ClientPositions;
314 page: PagePositions;
315}
316
317export interface DraggableRubric {
318 draggableId: DraggableId;
319 mode: MovementMode;
320 source: DraggableLocation;
321}
322
323export interface DragStart extends BeforeCapture {
324 type: TypeId;
325 source: DraggableLocation;
326}
327
328// Published in onBeforeCapture
329// We cannot give more information as things might change in the
330// onBeforeCapture responder!
331export interface BeforeCapture {
332 draggableId: DraggableId;
333 mode: MovementMode;
334}
335
336// published when a drag starts
337export interface DragStart extends DraggableRubric {
338 mode: MovementMode;
339}
340
341export interface DragUpdate extends DragStart {
342 // may not have any destination (drag to nowhere)
343 destination?: DraggableLocation | undefined;
344 // populated when a draggable is dragging over another in combine mode
345 combine?: Combine | undefined;
346}
347
348export type DropReason = 'DROP' | 'CANCEL';
349
350export interface DropResult extends DragUpdate {
351 reason: DropReason;
352}
353
354export interface ScrollOptions {
355 shouldPublishImmediately: boolean;
356}
357
358// using the draggable id rather than the descriptor as the descriptor
359// may change as a result of the initial flush. This means that the lift
360// descriptor may not be the same as the actual descriptor. To avoid
361// confusion the request is just an id which is looked up
362// in the dimension-marshal post-flush
363// Not including droppableId as it might change in a drop flush
364export interface LiftRequest {
365 draggableId: DraggableId;
366 scrollOptions: ScrollOptions;
367}
368
369export interface Critical {
370 draggable: DraggableDescriptor;
371 droppable: DroppableDescriptor;
372}
373
374export interface Viewport {
375 // live updates with the latest values
376 frame: Rect;
377 scroll: ScrollDetails;
378}
379
380export interface LiftEffect {
381 inVirtualList: boolean;
382 effected: DraggableIdMap;
383 displacedBy: DisplacedBy;
384}
385
386export interface DimensionMap {
387 draggables: DraggableDimensionMap;
388 droppables: DroppableDimensionMap;
389}
390
391export interface DroppablePublish {
392 droppableId: DroppableId;
393 scroll: Position;
394}
395export interface Published {
396 additions: DraggableDimension[];
397 removals: DraggableId[];
398 modified: DroppablePublish[];
399}
400
401export interface CompletedDrag {
402 critical: Critical;
403 result: DropResult;
404 impact: DragImpact;
405 afterCritical: LiftEffect;
406}
407
408export interface IdleState {
409 phase: 'IDLE';
410 completed?: CompletedDrag | undefined;
411 shouldFlush: boolean;
412}
413
414export interface DraggingState {
415 phase: 'DRAGGING';
416 isDragging: true;
417 critical: Critical;
418 movementMode: MovementMode;
419 dimensions: DimensionMap;
420 initial: DragPositions;
421 current: DragPositions;
422 impact: DragImpact;
423 viewport: Viewport;
424 afterCritical: LiftEffect;
425 onLiftImpact: DragImpact;
426 // when there is a fixed list we want to opt out of this behaviour
427 isWindowScrollAllowed: boolean;
428 // if we need to jump the scroll (keyboard dragging)
429 scrollJumpRequest?: Position | undefined;
430 // whether or not draggable movements should be animated
431 forceShouldAnimate?: boolean | undefined;
432}
433
434// While dragging we can enter into a bulk collection phase
435// During this phase no drag updates are permitted.
436// If a drop occurs during this phase, it must wait until it is
437// completed before continuing with the drop
438// TODO: rename to BulkCollectingState
439export interface CollectingState extends Omit<DraggingState, 'phase'> {
440 phase: 'COLLECTING';
441}
442
443// If a drop action occurs during a bulk collection we need to
444// wait for the collection to finish before performing the drop.
445// This is to ensure that everything has the correct index after
446// a drop
447export interface DropPendingState extends Omit<DraggingState, 'phase'> {
448 phase: 'DROP_PENDING';
449 isWaiting: boolean;
450 reason: DropReason;
451}
452
453// An optional phase for animating the drop / cancel if it is needed
454export interface DropAnimatingState {
455 phase: 'DROP_ANIMATING';
456 completed: CompletedDrag;
457 newHomeClientOffset: Position;
458 dropDuration: number;
459 // We still need to render placeholders and fix the dimensions of the dragging item
460 dimensions: DimensionMap;
461}
462
463export type State = IdleState | DraggingState | CollectingState | DropPendingState | DropAnimatingState;
464
465export type StateWhenUpdatesAllowed = DraggingState | CollectingState;
466
467export type Announce = (message: string) => void;
468
469export type InOutAnimationMode = 'none' | 'open' | 'close';
470
471export interface ResponderProvided {
472 announce: Announce;
473}
474
475export type OnBeforeCaptureResponder = (before: BeforeCapture) => void;
476
477export type OnBeforeDragStartResponder = (start: DragStart) => void;
478
479export type OnDragStartResponder = (start: DragStart, provided: ResponderProvided) => void;
480
481export type OnDragUpdateResponder = (update: DragUpdate, provided: ResponderProvided) => void;
482
483export type OnDragEndResponder = (result: DropResult, provided: ResponderProvided) => void;
484
485export interface Responders {
486 onBeforeCapture?: OnBeforeCaptureResponder | undefined;
487 onBeforeDragStart?: OnBeforeDragStartResponder | undefined;
488 onDragStart?: OnDragStartResponder | undefined;
489 onDragUpdate?: OnDragUpdateResponder | undefined;
490 // always required
491 onDragEnd: OnDragEndResponder;
492}
493
494export interface StopDragOptions {
495 shouldBlockNextClick: boolean;
496}
497
498export interface DragActions {
499 drop: (args?: StopDragOptions) => void;
500 cancel: (args?: StopDragOptions) => void;
501 isActive: () => boolean;
502 shouldRespectForcePress: () => boolean;
503}
504
505export interface FluidDragActions extends DragActions {
506 move: (clientSelection: Position) => void;
507}
508
509export interface SnapDragActions extends DragActions {
510 moveUp: () => void;
511 moveDown: () => void;
512 moveRight: () => void;
513 moveLeft: () => void;
514}
515
516export interface PreDragActions {
517 // discover if the lock is still active
518 isActive: () => boolean;
519 // whether it has been indicated if force press should be respected
520 shouldRespectForcePress: () => boolean;
521 // lift the current item
522 fluidLift: (clientSelection: Position) => FluidDragActions;
523 snapLift: () => SnapDragActions;
524 // cancel the pre drag without starting a drag. Releases the lock
525 abort: () => void;
526}
527
528export interface TryGetLockOptions {
529 sourceEvent?: Event | undefined;
530}
531
532export type TryGetLock = (
533 draggableId: DraggableId,
534 forceStop?: () => void,
535 options?: TryGetLockOptions,
536) => PreDragActions | null;
537
538export interface SensorAPI {
539 tryGetLock: TryGetLock;
540 canGetLock: (id: DraggableId) => boolean;
541 isLockClaimed: () => boolean;
542 tryReleaseLock: () => void;
543 findClosestDraggableId: (event: Event) => DraggableId | null;
544 findOptionsForDraggable: (id: DraggableId) => DraggableOptions | null;
545}
546
547export type Sensor = (api: SensorAPI) => void;
548
549/**
550 * DragDropContext
551 */
552
553export interface DragDropContextProps {
554 onBeforeCapture?(before: BeforeCapture): void;
555 onBeforeDragStart?(initial: DragStart): void;
556 onDragStart?(initial: DragStart, provided: ResponderProvided): void;
557 onDragUpdate?(initial: DragUpdate, provided: ResponderProvided): void;
558 onDragEnd(result: DropResult, provided: ResponderProvided): void;
559 children: React.ReactNode | null;
560 dragHandleUsageInstructions?: string | undefined;
561 nonce?: string | undefined;
562 enableDefaultSensors?: boolean | undefined;
563 sensors?: Sensor[] | undefined;
564}
565
566export class DragDropContext extends React.Component<DragDropContextProps> { }
567
568/**
569 * Droppable
570 */
571
572export interface DroppableProvidedProps {
573 // used for shared global styles
574 'data-rbd-droppable-context-id': string;
575 // Used to lookup. Currently not used for drag and drop lifecycle
576 'data-rbd-droppable-id': DroppableId;
577}
578
579export interface DroppableProvided {
580 innerRef: (element: HTMLElement | null) => any;
581 placeholder?: React.ReactElement<HTMLElement> | null | undefined;
582 droppableProps: DroppableProvidedProps;
583}
584
585export interface DroppableStateSnapshot {
586 isDraggingOver: boolean;
587 draggingOverWith?: DraggableId | undefined;
588 draggingFromThisWith?: DraggableId | undefined;
589 isUsingPlaceholder: boolean;
590}
591
592export interface DroppableProps {
593 droppableId: DroppableId;
594 type?: TypeId | undefined;
595 mode?: DroppableMode | undefined;
596 isDropDisabled?: boolean | undefined;
597 isCombineEnabled?: boolean | undefined;
598 direction?: Direction | undefined;
599 ignoreContainerClipping?: boolean | undefined;
600 renderClone?: DraggableChildrenFn | undefined;
601 getContainerForClone?: (() => React.ReactElement<HTMLElement>) | undefined;
602 children(provided: DroppableProvided, snapshot: DroppableStateSnapshot): React.ReactElement<HTMLElement>;
603}
604
605export class Droppable extends React.Component<DroppableProps> { }
606
607/**
608 * Draggable
609 */
610
611export interface DropAnimation {
612 duration: number;
613 curve: string;
614 moveTo: Position;
615 opacity?: number | undefined;
616 scale?: number | undefined;
617}
618
619export interface NotDraggingStyle {
620 transform?: string | undefined;
621 transition?: 'none' | undefined;
622}
623
624export interface DraggingStyle {
625 position: 'fixed';
626 top: number;
627 left: number;
628 boxSizing: 'border-box';
629 width: number;
630 height: number;
631 transition: 'none';
632 transform?: string | undefined;
633 zIndex: number;
634 opacity?: number | undefined;
635 pointerEvents: 'none';
636}
637
638export interface DraggableProvidedDraggableProps {
639 // inline style
640 style?: DraggingStyle | NotDraggingStyle | undefined;
641 // used for shared global styles
642 'data-rbd-draggable-context-id': string;
643 'data-rbd-draggable-id': string;
644 onTransitionEnd?: React.TransitionEventHandler<any> | undefined;
645}
646
647export interface DraggableProvidedDragHandleProps {
648 'data-rbd-drag-handle-draggable-id': DraggableId;
649 'data-rbd-drag-handle-context-id': ContextId;
650 'aria-describedby': ElementId;
651
652 role: string;
653 tabIndex: number;
654 draggable: boolean;
655 onDragStart: React.DragEventHandler<any>;
656}
657
658export interface DraggableProvided {
659 // will be removed after move to react 16
660 innerRef: (element?: HTMLElement | null) => any;
661 draggableProps: DraggableProvidedDraggableProps;
662 dragHandleProps?: DraggableProvidedDragHandleProps | undefined;
663}
664
665export interface DraggableStateSnapshot {
666 isDragging: boolean;
667 isDropAnimating: boolean;
668 dropAnimation?: DropAnimation | undefined;
669 draggingOver?: DroppableId | undefined;
670 // the id of a draggable that you are combining with
671 combineWith?: DraggableId | undefined;
672 // a combine target is being dragged over by
673 combineTargetFor?: DraggableId | undefined;
674 // What type of movement is being done: 'FLUID' or 'SNAP'
675 mode?: MovementMode | undefined;
676}
677
678export type DraggableChildrenFn = (
679 provided: DraggableProvided,
680 snapshot: DraggableStateSnapshot,
681 rubric: DraggableRubric,
682) => React.ReactElement<HTMLElement>;
683
684export interface DraggableProps {
685 draggableId: DraggableId;
686 index: number;
687 children: DraggableChildrenFn;
688 isDragDisabled?: boolean | undefined;
689 disableInteractiveElementBlocking?: boolean | undefined;
690 shouldRespectForcePress?: boolean | undefined;
691}
692
693export class Draggable extends React.Component<DraggableProps> { }
694
695export function resetServerContext(): void;
696
697export const useMouseSensor: Sensor;
698export const useTouchSensor: Sensor;
699export const useKeyboardSensor: Sensor;