1 | import { __rest } from "tslib";
|
2 | import * as React from 'react';
|
3 | import { css } from '@patternfly/react-styles';
|
4 | import styles from '@patternfly/react-styles/css/components/DataList/data-list';
|
5 | import stylesGrid from '@patternfly/react-styles/css/components/DataList/data-list-grid';
|
6 | const 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 | };
|
15 | export var DataListWrapModifier;
|
16 | (function (DataListWrapModifier) {
|
17 | DataListWrapModifier["nowrap"] = "nowrap";
|
18 | DataListWrapModifier["truncate"] = "truncate";
|
19 | DataListWrapModifier["breakWord"] = "breakWord";
|
20 | })(DataListWrapModifier || (DataListWrapModifier = {}));
|
21 | export const DataListContext = React.createContext({
|
22 | isSelectable: false
|
23 | });
|
24 | const 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 | };
|
33 | export 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 |
|
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 |
|
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 |
|
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 |
|
216 | onDragStart, onDragMove, onDragCancel, onDragFinish, gridBreakpoint, itemOrder } = _a,
|
217 |
|
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 | }
|
242 | DataList.displayName = 'DataList';
|
243 | DataList.defaultProps = {
|
244 | children: null,
|
245 | className: '',
|
246 | selectedDataListItemId: '',
|
247 | isCompact: false,
|
248 | gridBreakpoint: 'md',
|
249 | wrapModifier: null
|
250 | };
|
251 |
|
\ | No newline at end of file |