UNPKG

4.51 kBJavaScriptView Raw
1import { invariant } from '@react-dnd/invariant';
2import { addSource, addTarget, removeSource, removeTarget, } from '../actions/registry';
3import { getNextUniqueId } from '../utils/getNextUniqueId';
4import { HandlerRole, } from '../interfaces';
5import { validateSourceContract, validateTargetContract, validateType, } from '../contracts';
6import { asap } from '@react-dnd/asap';
7function getNextHandlerId(role) {
8 const id = getNextUniqueId().toString();
9 switch (role) {
10 case HandlerRole.SOURCE:
11 return `S${id}`;
12 case HandlerRole.TARGET:
13 return `T${id}`;
14 default:
15 throw new Error(`Unknown Handler Role: ${role}`);
16 }
17}
18function parseRoleFromHandlerId(handlerId) {
19 switch (handlerId[0]) {
20 case 'S':
21 return HandlerRole.SOURCE;
22 case 'T':
23 return HandlerRole.TARGET;
24 default:
25 invariant(false, `Cannot parse handler ID: ${handlerId}`);
26 }
27}
28function mapContainsValue(map, searchValue) {
29 const entries = map.entries();
30 let isDone = false;
31 do {
32 const { done, value: [, value], } = entries.next();
33 if (value === searchValue) {
34 return true;
35 }
36 isDone = !!done;
37 } while (!isDone);
38 return false;
39}
40export class HandlerRegistryImpl {
41 types = new Map();
42 dragSources = new Map();
43 dropTargets = new Map();
44 pinnedSourceId = null;
45 pinnedSource = null;
46 store;
47 constructor(store) {
48 this.store = store;
49 }
50 addSource(type, source) {
51 validateType(type);
52 validateSourceContract(source);
53 const sourceId = this.addHandler(HandlerRole.SOURCE, type, source);
54 this.store.dispatch(addSource(sourceId));
55 return sourceId;
56 }
57 addTarget(type, target) {
58 validateType(type, true);
59 validateTargetContract(target);
60 const targetId = this.addHandler(HandlerRole.TARGET, type, target);
61 this.store.dispatch(addTarget(targetId));
62 return targetId;
63 }
64 containsHandler(handler) {
65 return (mapContainsValue(this.dragSources, handler) ||
66 mapContainsValue(this.dropTargets, handler));
67 }
68 getSource(sourceId, includePinned = false) {
69 invariant(this.isSourceId(sourceId), 'Expected a valid source ID.');
70 const isPinned = includePinned && sourceId === this.pinnedSourceId;
71 const source = isPinned ? this.pinnedSource : this.dragSources.get(sourceId);
72 return source;
73 }
74 getTarget(targetId) {
75 invariant(this.isTargetId(targetId), 'Expected a valid target ID.');
76 return this.dropTargets.get(targetId);
77 }
78 getSourceType(sourceId) {
79 invariant(this.isSourceId(sourceId), 'Expected a valid source ID.');
80 return this.types.get(sourceId);
81 }
82 getTargetType(targetId) {
83 invariant(this.isTargetId(targetId), 'Expected a valid target ID.');
84 return this.types.get(targetId);
85 }
86 isSourceId(handlerId) {
87 const role = parseRoleFromHandlerId(handlerId);
88 return role === HandlerRole.SOURCE;
89 }
90 isTargetId(handlerId) {
91 const role = parseRoleFromHandlerId(handlerId);
92 return role === HandlerRole.TARGET;
93 }
94 removeSource(sourceId) {
95 invariant(this.getSource(sourceId), 'Expected an existing source.');
96 this.store.dispatch(removeSource(sourceId));
97 asap(() => {
98 this.dragSources.delete(sourceId);
99 this.types.delete(sourceId);
100 });
101 }
102 removeTarget(targetId) {
103 invariant(this.getTarget(targetId), 'Expected an existing target.');
104 this.store.dispatch(removeTarget(targetId));
105 this.dropTargets.delete(targetId);
106 this.types.delete(targetId);
107 }
108 pinSource(sourceId) {
109 const source = this.getSource(sourceId);
110 invariant(source, 'Expected an existing source.');
111 this.pinnedSourceId = sourceId;
112 this.pinnedSource = source;
113 }
114 unpinSource() {
115 invariant(this.pinnedSource, 'No source is pinned at the time.');
116 this.pinnedSourceId = null;
117 this.pinnedSource = null;
118 }
119 addHandler(role, type, handler) {
120 const id = getNextHandlerId(role);
121 this.types.set(id, type);
122 if (role === HandlerRole.SOURCE) {
123 this.dragSources.set(id, handler);
124 }
125 else if (role === HandlerRole.TARGET) {
126 this.dropTargets.set(id, handler);
127 }
128 return id;
129 }
130}