UNPKG

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