1 | "use strict";
|
2 | var __extends = (this && this.__extends) || (function () {
|
3 | var extendStatics = function (d, b) {
|
4 | extendStatics = Object.setPrototypeOf ||
|
5 | ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
|
6 | function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
|
7 | return extendStatics(d, b);
|
8 | };
|
9 | return function (d, b) {
|
10 | extendStatics(d, b);
|
11 | function __() { this.constructor = d; }
|
12 | d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
|
13 | };
|
14 | })();
|
15 | var __assign = (this && this.__assign) || function () {
|
16 | __assign = Object.assign || function(t) {
|
17 | for (var s, i = 1, n = arguments.length; i < n; i++) {
|
18 | s = arguments[i];
|
19 | for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
|
20 | t[p] = s[p];
|
21 | }
|
22 | return t;
|
23 | };
|
24 | return __assign.apply(this, arguments);
|
25 | };
|
26 | var __importStar = (this && this.__importStar) || function (mod) {
|
27 | if (mod && mod.__esModule) return mod;
|
28 | var result = {};
|
29 | if (mod != null) for (var k in mod) if (Object.hasOwnProperty.call(mod, k)) result[k] = mod[k];
|
30 | result["default"] = mod;
|
31 | return result;
|
32 | };
|
33 | Object.defineProperty(exports, "__esModule", { value: true });
|
34 | var React = __importStar(require("react"));
|
35 | var ReactDOM = __importStar(require("react-dom"));
|
36 | var utils_1 = require("./utils");
|
37 | var List = (function (_super) {
|
38 | __extends(List, _super);
|
39 | function List() {
|
40 | var _this = _super !== null && _super.apply(this, arguments) || this;
|
41 | _this.listRef = React.createRef();
|
42 | _this.ghostRef = React.createRef();
|
43 | _this.topOffsets = [];
|
44 | _this.itemTranslateOffsets = [];
|
45 | _this.initialYOffset = 0;
|
46 | _this.lastScroll = 0;
|
47 | _this.needle = -1;
|
48 | _this.afterIndex = -2;
|
49 | _this.state = {
|
50 | itemDragged: -1,
|
51 | selectedItem: -1,
|
52 | initialX: 0,
|
53 | initialY: 0,
|
54 | targetX: 0,
|
55 | targetY: 0,
|
56 | targetHeight: 0,
|
57 | targetWidth: 0,
|
58 | liveText: ''
|
59 | };
|
60 | _this.getChildren = function () {
|
61 | if (_this.listRef && _this.listRef.current) {
|
62 | return Array.from(_this.listRef.current.children);
|
63 | }
|
64 | console.warn('No items found in the List container. Did you forget to pass & spread the `props` param in renderList?');
|
65 | return [];
|
66 | };
|
67 | _this.calculateOffsets = function () {
|
68 | _this.topOffsets = _this.getChildren().map(function (item) {
|
69 | return item.getBoundingClientRect().top;
|
70 | });
|
71 | _this.itemTranslateOffsets = _this.getChildren().map(function (item) {
|
72 | return utils_1.getTranslateOffset(item);
|
73 | });
|
74 | };
|
75 | _this.getTargetIndex = function (e) {
|
76 | return _this.getChildren().findIndex(function (child) { return child === e.target || child.contains(e.currentTarget); });
|
77 | };
|
78 | _this.onMouseDown = function (e) {
|
79 | if (e.button !== 0)
|
80 | return;
|
81 | document.addEventListener('mousemove', _this.onMouseMove, { passive: true });
|
82 | document.addEventListener('mouseup', _this.onEnd, { passive: true });
|
83 | var index = _this.getTargetIndex(e);
|
84 | if (index === -1)
|
85 | return;
|
86 | _this.onStart(_this.getChildren()[index], e.clientX, e.clientY, index);
|
87 | };
|
88 | _this.onTouchStart = function (e) {
|
89 | document.addEventListener('touchmove', _this.onTouchMove, { passive: true });
|
90 | document.addEventListener('touchend', _this.onEnd, { passive: true });
|
91 | document.addEventListener('touchcancel', _this.onEnd, { passive: true });
|
92 | var index = _this.getTargetIndex(e);
|
93 | if (index === -1)
|
94 | return;
|
95 | _this.onStart(_this.getChildren()[index], e.touches[0].clientX, e.touches[0].clientY, index);
|
96 | };
|
97 | _this.getYOffset = function () {
|
98 | var listScroll = _this.listRef.current
|
99 | ? _this.listRef.current.scrollTop
|
100 | : 0;
|
101 | return window.pageYOffset + listScroll;
|
102 | };
|
103 | _this.onStart = function (target, clientX, clientY, index) {
|
104 | if (_this.state.selectedItem > -1) {
|
105 | _this.setState({ selectedItem: -1 });
|
106 | _this.needle = -1;
|
107 | }
|
108 | var targetRect = target.getBoundingClientRect();
|
109 | var targetStyles = window.getComputedStyle(target);
|
110 | _this.calculateOffsets();
|
111 | _this.initialYOffset = _this.getYOffset();
|
112 | _this.setState({
|
113 | itemDragged: index,
|
114 | targetX: targetRect.x - parseInt(targetStyles['margin-left'], 10),
|
115 | targetY: targetRect.y - parseInt(targetStyles['margin-top'], 10),
|
116 | targetHeight: targetRect.height,
|
117 | targetWidth: targetRect.width,
|
118 | initialX: clientX,
|
119 | initialY: clientY
|
120 | });
|
121 | };
|
122 | _this.onMouseMove = function (e) { return _this.onMove(e.clientX, e.clientY); };
|
123 | _this.onTouchMove = function (e) {
|
124 | return _this.onMove(e.touches[0].clientX, e.touches[0].clientY);
|
125 | };
|
126 | _this.onWheel = function (e) {
|
127 | if (_this.state.itemDragged < 0)
|
128 | return;
|
129 | _this.lastScroll = _this.listRef.current.scrollTop += e.deltaY;
|
130 | _this.moveOtherItems();
|
131 | };
|
132 | _this.onMove = function (clientX, clientY) {
|
133 | if (_this.state.itemDragged === -1)
|
134 | return null;
|
135 | utils_1.transformItem(_this.ghostRef.current, clientY - _this.state.initialY, _this.props.lockVertically ? 0 : clientX - _this.state.initialX);
|
136 | _this.moveOtherItems();
|
137 | };
|
138 | _this.moveOtherItems = function () {
|
139 | var targetRect = _this.ghostRef.current.getBoundingClientRect();
|
140 | var itemVerticalCenter = targetRect.top + targetRect.height / 2;
|
141 | var offset = utils_1.getTranslateOffset(_this.getChildren()[_this.state.itemDragged]);
|
142 | var currentYOffset = _this.getYOffset();
|
143 |
|
144 | if (_this.initialYOffset !== currentYOffset) {
|
145 | _this.topOffsets = _this.topOffsets.map(function (offset) { return offset - (currentYOffset - _this.initialYOffset); });
|
146 | _this.initialYOffset = currentYOffset;
|
147 | }
|
148 | _this.afterIndex = utils_1.binarySearch(_this.topOffsets, itemVerticalCenter);
|
149 | _this.animateItems(_this.afterIndex === -1 ? 0 : _this.afterIndex, _this.state.itemDragged, offset);
|
150 | };
|
151 | _this.animateItems = function (needle, movedItem, offset, animateMovedItem) {
|
152 | if (animateMovedItem === void 0) { animateMovedItem = false; }
|
153 | _this.getChildren().forEach(function (item, i) {
|
154 | utils_1.setItemTransition(item, _this.props.transitionDuration);
|
155 | if (movedItem === i && animateMovedItem) {
|
156 | if (movedItem === needle) {
|
157 | return utils_1.transformItem(item, null);
|
158 | }
|
159 | utils_1.transformItem(item, movedItem < needle
|
160 | ? _this.itemTranslateOffsets
|
161 | .slice(movedItem + 1, needle + 1)
|
162 | .reduce(function (a, b) { return a + b; }, 0)
|
163 | : _this.itemTranslateOffsets
|
164 | .slice(needle, movedItem)
|
165 | .reduce(function (a, b) { return a + b; }, 0) * -1);
|
166 | }
|
167 | else if (movedItem < needle && i > movedItem && i <= needle) {
|
168 | utils_1.transformItem(item, -offset);
|
169 | }
|
170 | else if (i < movedItem && movedItem > needle && i >= needle) {
|
171 | utils_1.transformItem(item, offset);
|
172 | }
|
173 | else {
|
174 | utils_1.transformItem(item, null);
|
175 | }
|
176 | });
|
177 | };
|
178 | _this.onEnd = function () {
|
179 | document.removeEventListener('mousemove', _this.onMouseMove);
|
180 | document.removeEventListener('touchmove', _this.onTouchMove);
|
181 | document.removeEventListener('mouseup', _this.onEnd);
|
182 | document.removeEventListener('touchup', _this.onEnd);
|
183 | document.removeEventListener('touchcancel', _this.onEnd);
|
184 | if (_this.afterIndex > -1 && _this.state.itemDragged !== _this.afterIndex) {
|
185 | _this.props.onChange({
|
186 | oldIndex: _this.state.itemDragged,
|
187 | newIndex: _this.afterIndex
|
188 | });
|
189 | }
|
190 | _this.getChildren().forEach(function (item) {
|
191 | utils_1.setItemTransition(item, 0);
|
192 | utils_1.transformItem(item, null);
|
193 | });
|
194 | _this.setState({ itemDragged: -1 });
|
195 | _this.afterIndex = -2;
|
196 |
|
197 | if (_this.lastScroll > 0) {
|
198 | _this.listRef.current.scrollTop = _this.lastScroll;
|
199 | _this.lastScroll = 0;
|
200 | }
|
201 | };
|
202 | _this.onKeyDown = function (e) {
|
203 | var selectedItem = _this.state.selectedItem;
|
204 | var index = _this.getTargetIndex(e);
|
205 | if (index === -1)
|
206 | return;
|
207 | if (e.key === ' ') {
|
208 | e.preventDefault();
|
209 | if (selectedItem === index) {
|
210 | if (selectedItem !== _this.needle) {
|
211 | _this.getChildren().forEach(function (item) {
|
212 | utils_1.setItemTransition(item, 0);
|
213 | utils_1.transformItem(item, null);
|
214 | });
|
215 | _this.props.onChange({
|
216 | oldIndex: selectedItem,
|
217 | newIndex: _this.needle
|
218 | });
|
219 | _this.getChildren()[_this.needle].focus();
|
220 | }
|
221 | _this.setState({
|
222 | selectedItem: -1,
|
223 | liveText: _this.props.voiceover.dropped(selectedItem + 1, _this.needle + 1)
|
224 | });
|
225 | _this.needle = -1;
|
226 | }
|
227 | else {
|
228 | _this.setState({
|
229 | selectedItem: index,
|
230 | liveText: _this.props.voiceover.lifted(index + 1)
|
231 | });
|
232 | _this.needle = index;
|
233 | }
|
234 | }
|
235 | if ((e.key === 'ArrowDown' || e.key === 'j') &&
|
236 | selectedItem > -1 &&
|
237 | _this.needle < _this.props.values.length - 1) {
|
238 | e.preventDefault();
|
239 | var offset = utils_1.getTranslateOffset(_this.getChildren()[selectedItem]);
|
240 | _this.needle++;
|
241 | _this.animateItems(_this.needle, selectedItem, offset, true);
|
242 | _this.setState({
|
243 | liveText: _this.props.voiceover.moved(_this.needle + 1, false)
|
244 | });
|
245 | }
|
246 | if ((e.key === 'ArrowUp' || e.key === 'k') &&
|
247 | selectedItem > -1 &&
|
248 | _this.needle > 0) {
|
249 | e.preventDefault();
|
250 | var offset = utils_1.getTranslateOffset(_this.getChildren()[selectedItem]);
|
251 | _this.needle--;
|
252 | _this.animateItems(_this.needle, selectedItem, offset, true);
|
253 | _this.setState({
|
254 | liveText: _this.props.voiceover.moved(_this.needle + 1, true)
|
255 | });
|
256 | }
|
257 | if (e.key === 'Escape' && selectedItem > -1) {
|
258 | _this.getChildren().forEach(function (item) {
|
259 | utils_1.setItemTransition(item, 0);
|
260 | utils_1.transformItem(item, null);
|
261 | });
|
262 | _this.setState({
|
263 | selectedItem: -1,
|
264 | liveText: _this.props.voiceover.canceled(selectedItem + 1)
|
265 | });
|
266 | _this.needle = -1;
|
267 | }
|
268 | if ((e.key === 'Tab' || e.key === 'Enter') && selectedItem > -1) {
|
269 | e.preventDefault();
|
270 | }
|
271 | };
|
272 | return _this;
|
273 | }
|
274 | List.prototype.componentDidMount = function () {
|
275 | this.calculateOffsets();
|
276 | };
|
277 | List.prototype.render = function () {
|
278 | var _this = this;
|
279 | var baseStyle = {
|
280 | userDrag: 'none',
|
281 | userSelect: 'none',
|
282 | boxSizing: 'border-box',
|
283 | position: 'relative'
|
284 | };
|
285 | var ghostStyle = __assign({}, baseStyle, { top: this.state.targetY, left: this.state.targetX, width: this.state.targetWidth, height: this.state.targetHeight, display: 'block', position: 'fixed', marginTop: 0 });
|
286 | return (React.createElement(React.Fragment, null,
|
287 | this.props.renderList({
|
288 | children: this.props.values.map(function (value, index) {
|
289 | var isDragged = index === _this.state.itemDragged;
|
290 | var isSelected = index === _this.state.selectedItem;
|
291 | var props = {
|
292 | key: index,
|
293 | tabIndex: 0,
|
294 | 'aria-roledescription': _this.props.voiceover.item(index + 1),
|
295 | onKeyDown: _this.onKeyDown,
|
296 | onMouseDown: _this.onMouseDown,
|
297 | onTouchStart: _this.onTouchStart,
|
298 | style: __assign({}, baseStyle, { visibility: isDragged ? 'hidden' : undefined, zIndex: isSelected ? 5000 : 0 })
|
299 | };
|
300 | return _this.props.renderItem({
|
301 | value: value,
|
302 | props: props,
|
303 | index: index,
|
304 | isDragged: isDragged,
|
305 | isSelected: isSelected
|
306 | });
|
307 | }),
|
308 | isDragged: this.state.itemDragged > -1,
|
309 | props: {
|
310 | ref: this.listRef
|
311 | }
|
312 | }),
|
313 | this.state.itemDragged > -1 &&
|
314 | ReactDOM.createPortal(this.props.renderItem({
|
315 | value: this.props.values[this.state.itemDragged],
|
316 | props: {
|
317 | ref: this.ghostRef,
|
318 | style: ghostStyle,
|
319 | onWheel: this.onWheel
|
320 | },
|
321 | isDragged: true,
|
322 | isSelected: false
|
323 | }), document.body),
|
324 | React.createElement("div", { "aria-live": "assertive", role: "log", "aria-atomic": "true", style: {
|
325 | position: 'absolute',
|
326 | width: '1px',
|
327 | height: '1px',
|
328 | margin: '-1px',
|
329 | border: '0px',
|
330 | padding: '0px',
|
331 | overflow: 'hidden',
|
332 | clip: 'react(0px, 0px, 0px, 0px)',
|
333 | clipPath: 'inset(100%)'
|
334 | } }, this.state.liveText)));
|
335 | };
|
336 | List.defaultProps = {
|
337 | transitionDuration: 300,
|
338 | lockVertically: false,
|
339 | voiceover: {
|
340 | item: function (position) {
|
341 | return "You are currently at a draggable item at position " + position + ". Press space bar to lift.";
|
342 | },
|
343 | lifted: function (position) {
|
344 | return "You have lifted item at position " + position + ". Press j to move down, k to move up, space bar to drop and escape to cancel.";
|
345 | },
|
346 | moved: function (position, up) {
|
347 | return "You have moved the lifted item " + (up ? 'up' : 'down') + " to position " + position + ". Press j to move down, k to move up, space bar to drop and escape to cancel.";
|
348 | },
|
349 | dropped: function (from, to) {
|
350 | return "You have dropped the item. It has moved from position " + from + " to " + to + ".";
|
351 | },
|
352 | canceled: function (position) {
|
353 | return "You have cancelled the movement. The item has returned to its starting position of " + position + ".";
|
354 | }
|
355 | }
|
356 | };
|
357 | return List;
|
358 | }(React.Component));
|
359 | exports.default = List;
|