UNPKG

10.3 kBJavaScriptView Raw
1import { __rest } from "tslib";
2import * as React from 'react';
3import { css } from '@patternfly/react-styles';
4import styles from '@patternfly/react-styles/css/components/DataList/data-list';
5import stylesGrid from '@patternfly/react-styles/css/components/DataList/data-list-grid';
6const gridBreakpointClasses = {
7 none: stylesGrid.modifiers.gridNone,
8 always: 'pf-m-grid',
9 sm: stylesGrid.modifiers.gridSm,
10 md: stylesGrid.modifiers.gridMd,
11 lg: stylesGrid.modifiers.gridLg,
12 xl: stylesGrid.modifiers.gridXl,
13 '2xl': stylesGrid.modifiers.grid_2xl
14};
15export var DataListWrapModifier;
16(function (DataListWrapModifier) {
17 DataListWrapModifier["nowrap"] = "nowrap";
18 DataListWrapModifier["truncate"] = "truncate";
19 DataListWrapModifier["breakWord"] = "breakWord";
20})(DataListWrapModifier || (DataListWrapModifier = {}));
21export const DataListContext = React.createContext({
22 isSelectable: false
23});
24const moveItem = (arr, i1, toIndex) => {
25 const fromIndex = arr.indexOf(i1);
26 if (fromIndex === toIndex) {
27 return arr;
28 }
29 const temp = arr.splice(fromIndex, 1);
30 arr.splice(toIndex, 0, temp[0]);
31 return arr;
32};
33export class DataList extends React.Component {
34 constructor(props) {
35 super(props);
36 this.dragFinished = false;
37 this.html5DragDrop = false;
38 this.arrayCopy = React.Children.toArray(this.props.children);
39 this.ref = React.createRef();
40 this.state = {
41 tempItemOrder: [],
42 draggedItemId: null,
43 draggingToItemIndex: null,
44 dragging: false
45 };
46 this.getIndex = (id) => Array.from(this.ref.current.children).findIndex(item => item.id === id);
47 this.move = (itemOrder) => {
48 const ulNode = this.ref.current;
49 const nodes = Array.from(ulNode.children);
50 if (nodes.map(node => node.id).every((id, i) => id === itemOrder[i])) {
51 return;
52 }
53 while (ulNode.firstChild) {
54 ulNode.removeChild(ulNode.lastChild);
55 }
56 itemOrder.forEach(id => {
57 ulNode.appendChild(nodes.find(n => n.id === id));
58 });
59 };
60 this.dragStart0 = (el) => {
61 const { onDragStart } = this.props;
62 const draggedItemId = el.id;
63 el.classList.add(styles.modifiers.ghostRow);
64 el.setAttribute('aria-pressed', 'true');
65 this.setState({
66 draggedItemId,
67 dragging: true
68 });
69 onDragStart && onDragStart(draggedItemId);
70 };
71 this.dragStart = (evt) => {
72 evt.dataTransfer.effectAllowed = 'move';
73 evt.dataTransfer.setData('text/plain', evt.currentTarget.id);
74 this.dragStart0(evt.currentTarget);
75 };
76 this.onDragCancel = () => {
77 this.move(this.props.itemOrder);
78 Array.from(this.ref.current.children).forEach(el => {
79 el.classList.remove(styles.modifiers.ghostRow);
80 el.classList.remove(styles.modifiers.dragOver);
81 el.setAttribute('aria-pressed', 'false');
82 });
83 this.setState({
84 draggedItemId: null,
85 draggingToItemIndex: null,
86 dragging: false
87 });
88 if (this.props.onDragCancel) {
89 this.props.onDragCancel();
90 }
91 };
92 this.dragLeave = (evt) => {
93 // This event false fires when we call `this.move()`, so double check we're out of zone
94 if (!this.isValidDrop(evt)) {
95 this.move(this.props.itemOrder);
96 this.setState({
97 draggingToItemIndex: null
98 });
99 }
100 };
101 this.dragEnd0 = (el) => {
102 el.classList.remove(styles.modifiers.ghostRow);
103 el.classList.remove(styles.modifiers.dragOver);
104 el.setAttribute('aria-pressed', 'false');
105 this.setState({
106 draggedItemId: null,
107 draggingToItemIndex: null,
108 dragging: false
109 });
110 };
111 this.dragEnd = (evt) => {
112 this.dragEnd0(evt.target);
113 };
114 this.isValidDrop = (evt) => {
115 const ulRect = this.ref.current.getBoundingClientRect();
116 return (evt.clientX > ulRect.x &&
117 evt.clientX < ulRect.x + ulRect.width &&
118 evt.clientY > ulRect.y &&
119 evt.clientY < ulRect.y + ulRect.height);
120 };
121 this.drop = (evt) => {
122 if (this.isValidDrop(evt)) {
123 this.props.onDragFinish(this.state.tempItemOrder);
124 }
125 else {
126 this.onDragCancel();
127 }
128 };
129 this.dragOver0 = (id) => {
130 const draggingToItemIndex = Array.from(this.ref.current.children).findIndex(item => item.id === id);
131 if (draggingToItemIndex !== this.state.draggingToItemIndex) {
132 const tempItemOrder = moveItem([...this.props.itemOrder], this.state.draggedItemId, draggingToItemIndex);
133 this.move(tempItemOrder);
134 this.setState({
135 draggingToItemIndex,
136 tempItemOrder
137 });
138 }
139 };
140 this.dragOver = (evt) => {
141 evt.preventDefault();
142 const curListItem = evt.target.closest('li');
143 if (!curListItem || !this.ref.current.contains(curListItem) || curListItem.id === this.state.draggedItemId) {
144 // We're going nowhere, don't bother calling `dragOver0`
145 return null;
146 }
147 else {
148 this.dragOver0(curListItem.id);
149 }
150 };
151 this.handleDragButtonKeys = (evt) => {
152 const { dragging } = this.state;
153 if (![' ', 'Escape', 'Enter', 'ArrowUp', 'ArrowDown'].includes(evt.key) || !this.html5DragDrop) {
154 if (dragging) {
155 evt.preventDefault();
156 }
157 return;
158 }
159 evt.preventDefault();
160 const dragItem = evt.target.closest('li');
161 if (evt.key === ' ' || (evt.key === 'Enter' && !dragging)) {
162 this.dragStart0(dragItem);
163 }
164 else if (dragging) {
165 if (evt.key === 'Escape' || evt.key === 'Enter') {
166 this.setState({
167 dragging: false
168 });
169 this.dragFinished = true;
170 if (evt.key === 'Enter') {
171 this.dragEnd0(dragItem);
172 this.props.onDragFinish(this.state.tempItemOrder);
173 }
174 else {
175 this.onDragCancel();
176 }
177 }
178 else if (evt.key === 'ArrowUp') {
179 const nextSelection = dragItem.previousSibling;
180 if (nextSelection) {
181 this.dragOver0(nextSelection.id);
182 dragItem.querySelector(`.${styles.dataListItemDraggableButton}`).focus();
183 }
184 }
185 else if (evt.key === 'ArrowDown') {
186 const nextSelection = dragItem.nextSibling;
187 if (nextSelection) {
188 this.dragOver0(nextSelection.id);
189 dragItem.querySelector(`.${styles.dataListItemDraggableButton}`).focus();
190 }
191 }
192 }
193 };
194 this.html5DragDrop = Boolean(props.onDragFinish || props.onDragStart || props.onDragMove || props.onDragCancel);
195 if (this.html5DragDrop) {
196 // eslint-disable-next-line no-console
197 console.warn("DataList's onDrag API is deprecated. Use DragDrop instead.");
198 }
199 }
200 componentDidUpdate(oldProps) {
201 if (this.dragFinished) {
202 this.dragFinished = false;
203 this.setState({
204 tempItemOrder: [...this.props.itemOrder],
205 draggedItemId: null,
206 dragging: false
207 });
208 }
209 if (oldProps.itemOrder !== this.props.itemOrder) {
210 this.move(this.props.itemOrder);
211 }
212 }
213 render() {
214 const _a = this.props, { className, children, onSelectDataListItem, selectedDataListItemId, isCompact, wrapModifier,
215 /* eslint-disable @typescript-eslint/no-unused-vars */
216 onDragStart, onDragMove, onDragCancel, onDragFinish, gridBreakpoint, itemOrder } = _a,
217 /* eslint-enable @typescript-eslint/no-unused-vars */
218 props = __rest(_a, ["className", "children", "onSelectDataListItem", "selectedDataListItemId", "isCompact", "wrapModifier", "onDragStart", "onDragMove", "onDragCancel", "onDragFinish", "gridBreakpoint", "itemOrder"]);
219 const { dragging } = this.state;
220 const isSelectable = onSelectDataListItem !== undefined;
221 const updateSelectedDataListItem = (id) => {
222 onSelectDataListItem(id);
223 };
224 const dragProps = this.html5DragDrop && {
225 onDragOver: this.dragOver,
226 onDrop: this.dragOver,
227 onDragLeave: this.dragLeave
228 };
229 return (React.createElement(DataListContext.Provider, { value: {
230 isSelectable,
231 selectedDataListItemId,
232 updateSelectedDataListItem,
233 isDraggable: this.html5DragDrop,
234 dragStart: this.dragStart,
235 dragEnd: this.dragEnd,
236 drop: this.drop,
237 dragKeyHandler: this.handleDragButtonKeys
238 } },
239 React.createElement("ul", Object.assign({ className: css(styles.dataList, isCompact && styles.modifiers.compact, gridBreakpointClasses[gridBreakpoint], wrapModifier && styles.modifiers[wrapModifier], dragging && styles.modifiers.dragOver, className), style: props.style }, props, dragProps, { ref: this.ref }), children)));
240 }
241}
242DataList.displayName = 'DataList';
243DataList.defaultProps = {
244 children: null,
245 className: '',
246 selectedDataListItemId: '',
247 isCompact: false,
248 gridBreakpoint: 'md',
249 wrapModifier: null
250};
251//# sourceMappingURL=DataList.js.map
\No newline at end of file