@instructure/ui-file-drop 8.25.1-snapshot-1 → 8.25.1-snapshot-10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +1 -1
- package/es/FileDrop/index.js +214 -227
- package/es/FileDrop/props.js +0 -98
- package/es/FileDrop/utils/getEventFiles.js +8 -6
- package/lib/FileDrop/index.js +216 -228
- package/lib/FileDrop/props.js +0 -98
- package/lib/FileDrop/utils/getEventFiles.js +8 -6
- package/package.json +15 -15
- package/src/FileDrop/index.tsx +75 -106
- package/src/FileDrop/props.ts +91 -76
- package/src/FileDrop/utils/accepts.ts +4 -4
- package/src/FileDrop/utils/getEventFiles.ts +13 -8
- package/tsconfig.build.tsbuildinfo +1 -1
- package/types/FileDrop/FileDropLocator.d.ts +4 -4
- package/types/FileDrop/index.d.ts +48 -43
- package/types/FileDrop/index.d.ts.map +1 -1
- package/types/FileDrop/props.d.ts +89 -8
- package/types/FileDrop/props.d.ts.map +1 -1
- package/types/FileDrop/utils/accepts.d.ts +2 -2
- package/types/FileDrop/utils/accepts.d.ts.map +1 -1
- package/types/FileDrop/utils/getEventFiles.d.ts +2 -1
- package/types/FileDrop/utils/getEventFiles.d.ts.map +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
All notable changes to this project will be documented in this file.
|
|
4
4
|
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
|
5
5
|
|
|
6
|
-
## [8.25.1-snapshot-
|
|
6
|
+
## [8.25.1-snapshot-10](https://github.com/instructure/instructure-ui/compare/v8.25.0...v8.25.1-snapshot-10) (2022-06-20)
|
|
7
7
|
|
|
8
8
|
**Note:** Version bump only for package @instructure/ui-file-drop
|
|
9
9
|
|
package/es/FileDrop/index.js
CHANGED
|
@@ -2,7 +2,7 @@ import _objectWithoutProperties from "@babel/runtime/helpers/esm/objectWithoutPr
|
|
|
2
2
|
import _slicedToArray from "@babel/runtime/helpers/esm/slicedToArray";
|
|
3
3
|
const _excluded = ["display", "height", "width", "minWidth", "maxWidth", "margin", "onDropAccepted", "onDropRejected"];
|
|
4
4
|
|
|
5
|
-
var _dec, _dec2, _dec3, _class
|
|
5
|
+
var _dec, _dec2, _dec3, _class;
|
|
6
6
|
|
|
7
7
|
/*
|
|
8
8
|
* The MIT License (MIT)
|
|
@@ -29,13 +29,12 @@ var _dec, _dec2, _dec3, _class, _class2;
|
|
|
29
29
|
*/
|
|
30
30
|
|
|
31
31
|
/** @jsx jsx */
|
|
32
|
-
import { Component } from 'react';
|
|
32
|
+
import React, { Component } from 'react';
|
|
33
33
|
import keycode from 'keycode';
|
|
34
34
|
import { FormFieldMessages } from '@instructure/ui-form-field';
|
|
35
35
|
import { View } from '@instructure/ui-view';
|
|
36
36
|
import { testable } from '@instructure/ui-testable';
|
|
37
37
|
import { callRenderProp, passthroughProps, getInteraction, withDeterministicId } from '@instructure/ui-react-utils';
|
|
38
|
-
import { isEdge } from '@instructure/ui-utils';
|
|
39
38
|
import { accepts, getAcceptList } from './utils/accepts';
|
|
40
39
|
import { getEventFiles } from './utils/getEventFiles';
|
|
41
40
|
import { withStyle, jsx } from '@instructure/emotion';
|
|
@@ -45,214 +44,77 @@ import { propTypes, allowedProps } from './props';
|
|
|
45
44
|
|
|
46
45
|
function keyEventIsClickButton(e) {
|
|
47
46
|
return e.keyCode === keycode.codes.space || e.keyCode === keycode.codes.enter;
|
|
48
|
-
} // Used try-catch due to missing document/navigator references in Jenkins
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
function isBrowserMS() {
|
|
52
|
-
let result = false;
|
|
53
|
-
|
|
54
|
-
try {
|
|
55
|
-
result = document.documentMode || isEdge;
|
|
56
|
-
} catch (e) {} // eslint-disable-line no-empty
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
return result;
|
|
60
47
|
}
|
|
61
|
-
|
|
62
|
-
const IS_MS = isBrowserMS();
|
|
63
48
|
/**
|
|
64
49
|
---
|
|
65
50
|
category: components
|
|
66
51
|
---
|
|
52
|
+
@tsProps
|
|
67
53
|
**/
|
|
68
54
|
|
|
69
|
-
let FileDrop = (_dec = withDeterministicId(), _dec2 = withStyle(generateStyle, generateComponentTheme), _dec3 = testable(), _dec(_class = _dec2(_class = _dec3(_class = (_class2 = class FileDrop extends Component {
|
|
70
|
-
constructor(props) {
|
|
71
|
-
super(props);
|
|
72
|
-
|
|
73
|
-
this.makeStyleProps = () => {
|
|
74
|
-
return {
|
|
75
|
-
functionallyDisabled: this.functionallyDisabled,
|
|
76
|
-
visuallyDisabled: this.interaction === 'disabled',
|
|
77
|
-
dragRejected: this.state.isDragRejected || this.invalid,
|
|
78
|
-
dragAccepted: this.state.isDragAccepted
|
|
79
|
-
};
|
|
80
|
-
};
|
|
81
|
-
|
|
82
|
-
this.state = {
|
|
83
|
-
isDragAccepted: false,
|
|
84
|
-
isDragRejected: false,
|
|
85
|
-
isFocused: false,
|
|
86
|
-
isFileBrowserDisplayed: false
|
|
87
|
-
};
|
|
88
|
-
this.enterCounter = 0;
|
|
89
|
-
this.fileInputEl = null;
|
|
90
|
-
this.defaultId = null;
|
|
91
|
-
this.messagesId = '';
|
|
92
|
-
this.ref = null;
|
|
93
|
-
|
|
94
|
-
this.handleElementRef = el => {
|
|
95
|
-
this.ref = el;
|
|
96
|
-
};
|
|
97
|
-
|
|
98
|
-
this.handleDragEnter = e => {
|
|
99
|
-
e.preventDefault(); // Count the dropzone and any children that are entered.
|
|
100
|
-
|
|
101
|
-
this.enterCounter += 1; // Don't trigger onDragEnter for each children after the first one
|
|
102
|
-
|
|
103
|
-
if (this.enterCounter > 1) {
|
|
104
|
-
return;
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
const allFilesAccepted = this.allFilesAccepted(this.getDataTransferItems(e));
|
|
108
|
-
this.setState({
|
|
109
|
-
isDragAccepted: allFilesAccepted,
|
|
110
|
-
isDragRejected: !allFilesAccepted
|
|
111
|
-
});
|
|
112
|
-
this.props.onDragEnter(e);
|
|
113
|
-
};
|
|
114
|
-
|
|
115
|
-
this.handleDragOver = e => {
|
|
116
|
-
e.preventDefault();
|
|
117
|
-
e.stopPropagation();
|
|
118
|
-
|
|
119
|
-
try {
|
|
120
|
-
const event = e;
|
|
121
|
-
event.dataTransfer.dropEffect = 'copy';
|
|
122
|
-
} catch (err) {// continue regardless of error
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
;
|
|
126
|
-
this.props.onDragOver(e);
|
|
127
|
-
return false;
|
|
128
|
-
};
|
|
129
|
-
|
|
130
|
-
this.handleDragLeave = e => {
|
|
131
|
-
e.preventDefault();
|
|
132
|
-
this.enterCounter -= 1; // Only deactivate once the dropzone and all children was left
|
|
133
|
-
|
|
134
|
-
if (this.enterCounter > 0) {
|
|
135
|
-
return;
|
|
136
|
-
}
|
|
137
|
-
|
|
138
|
-
this.setState({
|
|
139
|
-
isDragAccepted: false,
|
|
140
|
-
isDragRejected: false
|
|
141
|
-
});
|
|
142
|
-
this.props.onDragLeave(e);
|
|
143
|
-
};
|
|
144
|
-
|
|
145
|
-
this.handleChange = e => {
|
|
146
|
-
const _this$props = this.props,
|
|
147
|
-
onDrop = _this$props.onDrop,
|
|
148
|
-
onDropAccepted = _this$props.onDropAccepted,
|
|
149
|
-
onDropRejected = _this$props.onDropRejected,
|
|
150
|
-
shouldEnablePreview = _this$props.shouldEnablePreview;
|
|
151
|
-
const fileList = this.getDataTransferItems(e, shouldEnablePreview);
|
|
152
|
-
|
|
153
|
-
const _this$parseFiles = this.parseFiles(fileList),
|
|
154
|
-
_this$parseFiles2 = _slicedToArray(_this$parseFiles, 2),
|
|
155
|
-
accepted = _this$parseFiles2[0],
|
|
156
|
-
rejected = _this$parseFiles2[1];
|
|
157
|
-
|
|
158
|
-
e.preventDefault();
|
|
159
|
-
this.enterCounter = 0;
|
|
160
|
-
onDrop(accepted, rejected, e);
|
|
161
|
-
|
|
162
|
-
if (rejected.length > 0) {
|
|
163
|
-
onDropRejected(rejected, e);
|
|
164
|
-
}
|
|
165
|
-
|
|
166
|
-
if (accepted.length > 0) {
|
|
167
|
-
onDropAccepted(accepted, e);
|
|
168
|
-
}
|
|
169
|
-
|
|
170
|
-
this.setState({
|
|
171
|
-
isDragAccepted: false,
|
|
172
|
-
isDragRejected: false,
|
|
173
|
-
isFileBrowserDisplayed: false
|
|
174
|
-
});
|
|
175
|
-
};
|
|
176
|
-
|
|
177
|
-
this.fileAccepted = file => {
|
|
178
|
-
return accepts(file, this.props.accept);
|
|
179
|
-
};
|
|
180
|
-
|
|
181
|
-
this.handleRef = el => {
|
|
182
|
-
this.fileInputEl = el;
|
|
183
|
-
};
|
|
184
|
-
|
|
185
|
-
this.handleBlur = () => {
|
|
186
|
-
this.setState({
|
|
187
|
-
isFocused: false,
|
|
188
|
-
isFileBrowserDisplayed: false
|
|
189
|
-
});
|
|
190
|
-
};
|
|
191
|
-
|
|
192
|
-
this.handleFocus = () => {
|
|
193
|
-
this.setState({
|
|
194
|
-
isFocused: true,
|
|
195
|
-
isFileBrowserDisplayed: false
|
|
196
|
-
});
|
|
197
|
-
};
|
|
198
|
-
|
|
199
|
-
this.handleClick = e => {
|
|
200
|
-
if (this.fileInputEl.value && this.props.shouldAllowRepeats) {
|
|
201
|
-
this.fileInputEl.value = null;
|
|
202
|
-
} // focus the input (because FF won't)
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
this.fileInputEl.focus();
|
|
206
|
-
this.props.onClick(e);
|
|
207
|
-
this.setState({
|
|
208
|
-
isFileBrowserDisplayed: true
|
|
209
|
-
});
|
|
210
|
-
};
|
|
211
|
-
|
|
212
|
-
this.handleKeyDown = e => {
|
|
213
|
-
if (this.state.isFocused && keyEventIsClickButton(e)) {
|
|
214
|
-
if (this.props.shouldAllowRepeats) {
|
|
215
|
-
this.fileInputEl.value = null;
|
|
216
|
-
} // This bit of logic is necessary for MS browsers but causes unwanted warnings in Firefox
|
|
217
|
-
// So we need to apply this logic only on MS browsers
|
|
218
|
-
|
|
219
|
-
/* istanbul ignore if */
|
|
220
55
|
|
|
56
|
+
let FileDrop = (_dec = withDeterministicId(), _dec2 = withStyle(generateStyle, generateComponentTheme), _dec3 = testable(), _dec(_class = _dec2(_class = _dec3(_class = class FileDrop extends Component {
|
|
57
|
+
static displayName = "FileDrop";
|
|
58
|
+
static componentId = 'FileDrop';
|
|
59
|
+
static propTypes = propTypes;
|
|
60
|
+
static allowedProps = allowedProps;
|
|
61
|
+
static defaultProps = {
|
|
62
|
+
onClick: function (_e) {},
|
|
63
|
+
shouldEnablePreview: false,
|
|
64
|
+
shouldAllowMultiple: false,
|
|
65
|
+
shouldAllowRepeats: true,
|
|
66
|
+
maxSize: Infinity,
|
|
67
|
+
minSize: 0,
|
|
68
|
+
// Leave interaction default undefined so that `disabled` and `readOnly` can also be supplied
|
|
69
|
+
messages: [],
|
|
70
|
+
display: 'block'
|
|
71
|
+
};
|
|
221
72
|
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
e.preventDefault();
|
|
225
|
-
this.fileInputEl.click();
|
|
226
|
-
}
|
|
227
|
-
}
|
|
228
|
-
};
|
|
229
|
-
|
|
230
|
-
this.handleKeyUp = e => {
|
|
231
|
-
// This is to handle the case where ESC is pressed inside a Dialog so that
|
|
232
|
-
// closing the file browser dialog doesn't also close the Dialog.
|
|
233
|
-
if (e.keyCode === keycode.codes.esc && this.state.isFileBrowserDisplayed) {
|
|
234
|
-
e.stopPropagation();
|
|
235
|
-
e.nativeEvent.stopImmediatePropagation();
|
|
236
|
-
this.setState({
|
|
237
|
-
isFileBrowserDisplayed: false
|
|
238
|
-
});
|
|
239
|
-
}
|
|
240
|
-
};
|
|
241
|
-
|
|
73
|
+
constructor(props) {
|
|
74
|
+
super(props);
|
|
242
75
|
this.defaultId = props.deterministicId();
|
|
243
76
|
this.messagesId = props.deterministicId('FileDrop-messages');
|
|
244
77
|
}
|
|
245
78
|
|
|
246
79
|
componentDidMount() {
|
|
247
|
-
;
|
|
248
|
-
|
|
80
|
+
var _this$props$makeStyle, _this$props;
|
|
81
|
+
|
|
82
|
+
(_this$props$makeStyle = (_this$props = this.props).makeStyles) === null || _this$props$makeStyle === void 0 ? void 0 : _this$props$makeStyle.call(_this$props, this.makeStyleProps());
|
|
249
83
|
}
|
|
250
84
|
|
|
251
85
|
componentDidUpdate() {
|
|
252
|
-
;
|
|
253
|
-
|
|
86
|
+
var _this$props$makeStyle2, _this$props2;
|
|
87
|
+
|
|
88
|
+
(_this$props$makeStyle2 = (_this$props2 = this.props).makeStyles) === null || _this$props$makeStyle2 === void 0 ? void 0 : _this$props$makeStyle2.call(_this$props2, this.makeStyleProps());
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
convertToFile(fileLikeItem) {
|
|
92
|
+
if (fileLikeItem instanceof DataTransferItem) return fileLikeItem.getAsFile();else return fileLikeItem;
|
|
254
93
|
}
|
|
255
94
|
|
|
95
|
+
makeStyleProps = () => {
|
|
96
|
+
return {
|
|
97
|
+
functionallyDisabled: this.functionallyDisabled,
|
|
98
|
+
visuallyDisabled: this.interaction === 'disabled',
|
|
99
|
+
dragRejected: this.state.isDragRejected || this.invalid,
|
|
100
|
+
dragAccepted: this.state.isDragAccepted
|
|
101
|
+
};
|
|
102
|
+
};
|
|
103
|
+
state = {
|
|
104
|
+
isDragAccepted: false,
|
|
105
|
+
isDragRejected: false,
|
|
106
|
+
isFocused: false,
|
|
107
|
+
isFileBrowserDisplayed: false
|
|
108
|
+
};
|
|
109
|
+
enterCounter = 0;
|
|
110
|
+
fileInputEl = null;
|
|
111
|
+
defaultId = null;
|
|
112
|
+
messagesId = '';
|
|
113
|
+
ref = null;
|
|
114
|
+
handleElementRef = el => {
|
|
115
|
+
this.ref = el;
|
|
116
|
+
};
|
|
117
|
+
|
|
256
118
|
get functionallyDisabled() {
|
|
257
119
|
return this.interaction === 'disabled' || this.interaction === 'readonly';
|
|
258
120
|
}
|
|
@@ -274,7 +136,11 @@ let FileDrop = (_dec = withDeterministicId(), _dec2 = withStyle(generateStyle, g
|
|
|
274
136
|
}
|
|
275
137
|
|
|
276
138
|
getDataTransferItems(e, shouldEnablePreview) {
|
|
277
|
-
let list =
|
|
139
|
+
let list = [];
|
|
140
|
+
Array.from(getEventFiles(e, this.fileInputEl)).forEach(file => {
|
|
141
|
+
const fileObj = this.convertToFile(file);
|
|
142
|
+
if (fileObj) list.push(fileObj);
|
|
143
|
+
});
|
|
278
144
|
|
|
279
145
|
if (list.length > 1) {
|
|
280
146
|
list = this.props.shouldAllowMultiple ? list : [list[0]];
|
|
@@ -289,11 +155,63 @@ let FileDrop = (_dec = withDeterministicId(), _dec2 = withStyle(generateStyle, g
|
|
|
289
155
|
return list;
|
|
290
156
|
}
|
|
291
157
|
|
|
158
|
+
handleDragEnter = e => {
|
|
159
|
+
var _this$props$onDragEnt, _this$props3;
|
|
160
|
+
|
|
161
|
+
e.preventDefault(); // Count the dropzone and any children that are entered.
|
|
162
|
+
|
|
163
|
+
this.enterCounter += 1; // Don't trigger onDragEnter for each children after the first one
|
|
164
|
+
|
|
165
|
+
if (this.enterCounter > 1) {
|
|
166
|
+
return;
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
const allFilesAccepted = this.allFilesAccepted(this.getDataTransferItems(e));
|
|
170
|
+
this.setState({
|
|
171
|
+
isDragAccepted: allFilesAccepted,
|
|
172
|
+
isDragRejected: !allFilesAccepted
|
|
173
|
+
});
|
|
174
|
+
(_this$props$onDragEnt = (_this$props3 = this.props).onDragEnter) === null || _this$props$onDragEnt === void 0 ? void 0 : _this$props$onDragEnt.call(_this$props3, e);
|
|
175
|
+
};
|
|
176
|
+
handleDragOver = e => {
|
|
177
|
+
var _this$props$onDragOve, _this$props4;
|
|
178
|
+
|
|
179
|
+
e.preventDefault();
|
|
180
|
+
e.stopPropagation();
|
|
181
|
+
|
|
182
|
+
try {
|
|
183
|
+
const event = e;
|
|
184
|
+
event.dataTransfer.dropEffect = 'copy';
|
|
185
|
+
} catch (err) {// continue regardless of error
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
(_this$props$onDragOve = (_this$props4 = this.props).onDragOver) === null || _this$props$onDragOve === void 0 ? void 0 : _this$props$onDragOve.call(_this$props4, e);
|
|
189
|
+
return false;
|
|
190
|
+
};
|
|
191
|
+
handleDragLeave = e => {
|
|
192
|
+
var _this$props$onDragLea, _this$props5;
|
|
193
|
+
|
|
194
|
+
e.preventDefault();
|
|
195
|
+
this.enterCounter -= 1; // Only deactivate once the dropzone and all children was left
|
|
196
|
+
|
|
197
|
+
if (this.enterCounter > 0) {
|
|
198
|
+
return;
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
this.setState({
|
|
202
|
+
isDragAccepted: false,
|
|
203
|
+
isDragRejected: false
|
|
204
|
+
});
|
|
205
|
+
(_this$props$onDragLea = (_this$props5 = this.props).onDragLeave) === null || _this$props$onDragLea === void 0 ? void 0 : _this$props$onDragLea.call(_this$props5, e);
|
|
206
|
+
};
|
|
207
|
+
|
|
292
208
|
parseFiles(fileList) {
|
|
293
209
|
const accepted = [];
|
|
294
210
|
const rejected = [];
|
|
295
211
|
fileList.forEach(file => {
|
|
296
|
-
|
|
212
|
+
const fileObj = this.convertToFile(file);
|
|
213
|
+
|
|
214
|
+
if (fileObj && this.fileAccepted(fileObj) && this.fileMatchSize(fileObj)) {
|
|
297
215
|
accepted.push(file);
|
|
298
216
|
} else {
|
|
299
217
|
rejected.push(file);
|
|
@@ -302,6 +220,41 @@ let FileDrop = (_dec = withDeterministicId(), _dec2 = withStyle(generateStyle, g
|
|
|
302
220
|
return [accepted, rejected];
|
|
303
221
|
}
|
|
304
222
|
|
|
223
|
+
handleChange = e => {
|
|
224
|
+
const _this$props6 = this.props,
|
|
225
|
+
onDrop = _this$props6.onDrop,
|
|
226
|
+
onDropAccepted = _this$props6.onDropAccepted,
|
|
227
|
+
onDropRejected = _this$props6.onDropRejected,
|
|
228
|
+
shouldEnablePreview = _this$props6.shouldEnablePreview;
|
|
229
|
+
const fileList = this.getDataTransferItems(e, shouldEnablePreview);
|
|
230
|
+
|
|
231
|
+
const _this$parseFiles = this.parseFiles(fileList),
|
|
232
|
+
_this$parseFiles2 = _slicedToArray(_this$parseFiles, 2),
|
|
233
|
+
accepted = _this$parseFiles2[0],
|
|
234
|
+
rejected = _this$parseFiles2[1];
|
|
235
|
+
|
|
236
|
+
e.preventDefault();
|
|
237
|
+
this.enterCounter = 0;
|
|
238
|
+
onDrop && onDrop(accepted, rejected, e);
|
|
239
|
+
|
|
240
|
+
if (rejected.length > 0 && onDropRejected) {
|
|
241
|
+
onDropRejected(rejected, e);
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
if (accepted.length > 0 && onDropAccepted) {
|
|
245
|
+
onDropAccepted(accepted, e);
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
this.setState({
|
|
249
|
+
isDragAccepted: false,
|
|
250
|
+
isDragRejected: false,
|
|
251
|
+
isFileBrowserDisplayed: false
|
|
252
|
+
});
|
|
253
|
+
};
|
|
254
|
+
fileAccepted = file => {
|
|
255
|
+
if (this.props.accept) return accepts(file, this.props.accept);else return true;
|
|
256
|
+
};
|
|
257
|
+
|
|
305
258
|
fileMatchSize(file) {
|
|
306
259
|
return file.size <= this.props.maxSize && file.size >= this.props.minSize;
|
|
307
260
|
}
|
|
@@ -312,7 +265,7 @@ let FileDrop = (_dec = withDeterministicId(), _dec2 = withStyle(generateStyle, g
|
|
|
312
265
|
|
|
313
266
|
acceptStr() {
|
|
314
267
|
const accept = this.props.accept;
|
|
315
|
-
return accept ? getAcceptList(accept).join(',') :
|
|
268
|
+
return accept ? getAcceptList(accept).join(',') : void 0;
|
|
316
269
|
}
|
|
317
270
|
|
|
318
271
|
renderLabel() {
|
|
@@ -324,17 +277,67 @@ let FileDrop = (_dec = withDeterministicId(), _dec2 = withStyle(generateStyle, g
|
|
|
324
277
|
});
|
|
325
278
|
}
|
|
326
279
|
|
|
280
|
+
handleRef = el => {
|
|
281
|
+
this.fileInputEl = el;
|
|
282
|
+
};
|
|
283
|
+
handleBlur = () => {
|
|
284
|
+
this.setState({
|
|
285
|
+
isFocused: false,
|
|
286
|
+
isFileBrowserDisplayed: false
|
|
287
|
+
});
|
|
288
|
+
};
|
|
289
|
+
handleFocus = () => {
|
|
290
|
+
this.setState({
|
|
291
|
+
isFocused: true,
|
|
292
|
+
isFileBrowserDisplayed: false
|
|
293
|
+
});
|
|
294
|
+
};
|
|
295
|
+
handleClick = e => {
|
|
296
|
+
var _this$fileInputEl;
|
|
297
|
+
|
|
298
|
+
if (this.fileInputEl.value && this.props.shouldAllowRepeats) {
|
|
299
|
+
this.fileInputEl.value = null;
|
|
300
|
+
} // focus the input (because FF won't)
|
|
301
|
+
|
|
302
|
+
|
|
303
|
+
(_this$fileInputEl = this.fileInputEl) === null || _this$fileInputEl === void 0 ? void 0 : _this$fileInputEl.focus();
|
|
304
|
+
this.props.onClick(e);
|
|
305
|
+
this.setState({
|
|
306
|
+
isFileBrowserDisplayed: true
|
|
307
|
+
});
|
|
308
|
+
};
|
|
309
|
+
handleKeyDown = e => {
|
|
310
|
+
if (this.state.isFocused && keyEventIsClickButton(e)) {
|
|
311
|
+
if (this.props.shouldAllowRepeats) {
|
|
312
|
+
this.fileInputEl.value = null;
|
|
313
|
+
}
|
|
314
|
+
}
|
|
315
|
+
};
|
|
316
|
+
handleKeyUp = e => {
|
|
317
|
+
// This is to handle the case where ESC is pressed inside a Dialog so that
|
|
318
|
+
// closing the file browser dialog doesn't also close the Dialog.
|
|
319
|
+
if (e.keyCode === keycode.codes.esc && this.state.isFileBrowserDisplayed) {
|
|
320
|
+
e.stopPropagation();
|
|
321
|
+
e.nativeEvent.stopImmediatePropagation();
|
|
322
|
+
this.setState({
|
|
323
|
+
isFileBrowserDisplayed: false
|
|
324
|
+
});
|
|
325
|
+
}
|
|
326
|
+
};
|
|
327
|
+
|
|
327
328
|
render() {
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
329
|
+
var _this$props$styles, _this$props$styles2, _this$props$styles3, _this$props$styles4;
|
|
330
|
+
|
|
331
|
+
const _this$props7 = this.props,
|
|
332
|
+
display = _this$props7.display,
|
|
333
|
+
height = _this$props7.height,
|
|
334
|
+
width = _this$props7.width,
|
|
335
|
+
minWidth = _this$props7.minWidth,
|
|
336
|
+
maxWidth = _this$props7.maxWidth,
|
|
337
|
+
margin = _this$props7.margin,
|
|
338
|
+
onDropAccepted = _this$props7.onDropAccepted,
|
|
339
|
+
onDropRejected = _this$props7.onDropRejected,
|
|
340
|
+
props = _objectWithoutProperties(_this$props7, _excluded);
|
|
338
341
|
|
|
339
342
|
const id = this.props.id || this.defaultId;
|
|
340
343
|
const focusColor = this.state.isDragRejected || this.invalid ? 'danger' : void 0;
|
|
@@ -349,7 +352,7 @@ let FileDrop = (_dec = withDeterministicId(), _dec2 = withStyle(generateStyle, g
|
|
|
349
352
|
height: height,
|
|
350
353
|
elementRef: this.handleElementRef
|
|
351
354
|
}, jsx("label", {
|
|
352
|
-
css: this.props.styles.fileDropLabel,
|
|
355
|
+
css: (_this$props$styles = this.props.styles) === null || _this$props$styles === void 0 ? void 0 : _this$props$styles.fileDropLabel,
|
|
353
356
|
htmlFor: id,
|
|
354
357
|
onDragEnter: this.handleDragEnter,
|
|
355
358
|
onDragOver: this.handleDragOver,
|
|
@@ -363,15 +366,15 @@ let FileDrop = (_dec = withDeterministicId(), _dec2 = withStyle(generateStyle, g
|
|
|
363
366
|
focusColor: focusColor,
|
|
364
367
|
height: height
|
|
365
368
|
}, jsx("span", {
|
|
366
|
-
css: this.props.styles.fileDropLabelContent
|
|
369
|
+
css: (_this$props$styles2 = this.props.styles) === null || _this$props$styles2 === void 0 ? void 0 : _this$props$styles2.fileDropLabelContent
|
|
367
370
|
}, jsx("span", {
|
|
368
|
-
css: this.props.styles.fileDropLayout
|
|
371
|
+
css: (_this$props$styles3 = this.props.styles) === null || _this$props$styles3 === void 0 ? void 0 : _this$props$styles3.fileDropLayout
|
|
369
372
|
}, jsx(View, {
|
|
370
373
|
height: height
|
|
371
374
|
}, this.renderLabel()))))), jsx("input", Object.assign({}, passthroughProps(props), {
|
|
372
375
|
onClick: this.handleClick,
|
|
373
376
|
type: "file",
|
|
374
|
-
css: this.props.styles.fileDropInput,
|
|
377
|
+
css: (_this$props$styles4 = this.props.styles) === null || _this$props$styles4 === void 0 ? void 0 : _this$props$styles4.fileDropInput,
|
|
375
378
|
id: id,
|
|
376
379
|
ref: this.handleRef,
|
|
377
380
|
onFocus: this.handleFocus,
|
|
@@ -381,7 +384,7 @@ let FileDrop = (_dec = withDeterministicId(), _dec2 = withStyle(generateStyle, g
|
|
|
381
384
|
multiple: this.props.shouldAllowMultiple,
|
|
382
385
|
accept: this.acceptStr(),
|
|
383
386
|
onChange: this.handleChange,
|
|
384
|
-
"aria-describedby": this.hasMessages ? this.messagesId :
|
|
387
|
+
"aria-describedby": this.hasMessages ? this.messagesId : void 0,
|
|
385
388
|
disabled: this.functionallyDisabled
|
|
386
389
|
})), this.hasMessages ? jsx(View, {
|
|
387
390
|
display: "block",
|
|
@@ -392,22 +395,6 @@ let FileDrop = (_dec = withDeterministicId(), _dec2 = withStyle(generateStyle, g
|
|
|
392
395
|
})) : null);
|
|
393
396
|
}
|
|
394
397
|
|
|
395
|
-
}
|
|
396
|
-
onClick: function (e) {},
|
|
397
|
-
onDrop: function (accepted, rejected, e) {},
|
|
398
|
-
onDropAccepted: function (accepted, e) {},
|
|
399
|
-
onDropRejected: function (rejected, e) {},
|
|
400
|
-
onDragEnter: function (e) {},
|
|
401
|
-
onDragOver: function (e) {},
|
|
402
|
-
onDragLeave: function (e) {},
|
|
403
|
-
shouldEnablePreview: false,
|
|
404
|
-
shouldAllowMultiple: false,
|
|
405
|
-
shouldAllowRepeats: true,
|
|
406
|
-
maxSize: Infinity,
|
|
407
|
-
minSize: 0,
|
|
408
|
-
// Leave interaction default undefined so that `disabled` and `readOnly` can also be supplied
|
|
409
|
-
messages: [],
|
|
410
|
-
display: 'block'
|
|
411
|
-
}, _class2)) || _class) || _class) || _class);
|
|
398
|
+
}) || _class) || _class) || _class);
|
|
412
399
|
export default FileDrop;
|
|
413
400
|
export { FileDrop };
|
package/es/FileDrop/props.js
CHANGED
|
@@ -25,126 +25,28 @@ import PropTypes from 'prop-types';
|
|
|
25
25
|
import { FormPropTypes } from '@instructure/ui-form-field';
|
|
26
26
|
import { ThemeablePropTypes } from '@instructure/emotion';
|
|
27
27
|
const propTypes = {
|
|
28
|
-
/**
|
|
29
|
-
* The id of the input (to link it to its label for a11y)
|
|
30
|
-
*/
|
|
31
28
|
id: PropTypes.string,
|
|
32
|
-
|
|
33
|
-
/**
|
|
34
|
-
* The content of FileDrop; can be a component or React node.
|
|
35
|
-
* Components receive `isDragAccepted` and `isDragRejected` as props.
|
|
36
|
-
*/
|
|
37
29
|
renderLabel: PropTypes.oneOfType([PropTypes.func, PropTypes.node]).isRequired,
|
|
38
|
-
|
|
39
|
-
/**
|
|
40
|
-
* The mime media type/s or file extension/s allowed to be dropped inside
|
|
41
|
-
*/
|
|
42
30
|
accept: PropTypes.oneOfType([PropTypes.string, PropTypes.arrayOf(PropTypes.string)]),
|
|
43
|
-
|
|
44
|
-
/**
|
|
45
|
-
* object with shape: `{
|
|
46
|
-
* text: PropTypes.node,
|
|
47
|
-
* type: PropTypes.oneOf(['error', 'hint', 'success', 'screenreader-only'])
|
|
48
|
-
* }`
|
|
49
|
-
*/
|
|
50
31
|
messages: PropTypes.arrayOf(FormPropTypes.message),
|
|
51
|
-
|
|
52
|
-
/**
|
|
53
|
-
* Called when clicking on drop area to select files to upload
|
|
54
|
-
*/
|
|
55
32
|
onClick: PropTypes.func,
|
|
56
|
-
|
|
57
|
-
/**
|
|
58
|
-
* Called when dropping files or when file dialog window exits successfully
|
|
59
|
-
*/
|
|
60
33
|
onDrop: PropTypes.func,
|
|
61
|
-
|
|
62
|
-
/**
|
|
63
|
-
* Called when dropping allowed files
|
|
64
|
-
*/
|
|
65
34
|
onDropAccepted: PropTypes.func,
|
|
66
|
-
|
|
67
|
-
/**
|
|
68
|
-
* Called when dropping rejected files
|
|
69
|
-
*/
|
|
70
35
|
onDropRejected: PropTypes.func,
|
|
71
|
-
|
|
72
|
-
/**
|
|
73
|
-
* Called when dragging files
|
|
74
|
-
* and passing through FileDrop's content for the first time
|
|
75
|
-
*/
|
|
76
36
|
onDragEnter: PropTypes.func,
|
|
77
|
-
|
|
78
|
-
/**
|
|
79
|
-
* Called when dragging files and passing through FileDrop's content
|
|
80
|
-
*/
|
|
81
37
|
onDragOver: PropTypes.func,
|
|
82
|
-
|
|
83
|
-
/**
|
|
84
|
-
* Called when dragging files and leaving FileDrop's content
|
|
85
|
-
*/
|
|
86
38
|
onDragLeave: PropTypes.func,
|
|
87
|
-
|
|
88
|
-
/**
|
|
89
|
-
* Flag to use window.URL.createObjectURL for each dropped file and pass it through file.preview
|
|
90
|
-
*/
|
|
91
39
|
shouldEnablePreview: PropTypes.bool,
|
|
92
|
-
|
|
93
|
-
/**
|
|
94
|
-
* Flag to allow multiple files to drop at once
|
|
95
|
-
*/
|
|
96
40
|
shouldAllowMultiple: PropTypes.bool,
|
|
97
|
-
|
|
98
|
-
/**
|
|
99
|
-
* Flag to allow upload of the same file more than once
|
|
100
|
-
*/
|
|
101
41
|
shouldAllowRepeats: PropTypes.bool,
|
|
102
|
-
|
|
103
|
-
/**
|
|
104
|
-
* the maximum file size allowed
|
|
105
|
-
*/
|
|
106
42
|
maxSize: PropTypes.number,
|
|
107
|
-
|
|
108
|
-
/**
|
|
109
|
-
* the minimum file size allowed
|
|
110
|
-
*/
|
|
111
43
|
minSize: PropTypes.number,
|
|
112
|
-
|
|
113
|
-
/**
|
|
114
|
-
* Specifies if interaction with the input is enabled, disabled, or readonly.
|
|
115
|
-
*/
|
|
116
44
|
interaction: PropTypes.oneOf(['enabled', 'disabled', 'readonly']),
|
|
117
|
-
|
|
118
|
-
/**
|
|
119
|
-
* Set the CSS `display` property on FileInput's outermost element
|
|
120
|
-
*/
|
|
121
45
|
display: PropTypes.oneOf(['block', 'inline-block']),
|
|
122
|
-
|
|
123
|
-
/**
|
|
124
|
-
* Set the CSS `height` property on FileInput's outermost element
|
|
125
|
-
*/
|
|
126
46
|
height: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
|
|
127
|
-
|
|
128
|
-
/**
|
|
129
|
-
* Set the CSS `width` property on FileInput's outermost element
|
|
130
|
-
*/
|
|
131
47
|
width: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
|
|
132
|
-
|
|
133
|
-
/**
|
|
134
|
-
* Set the CSS `maxWidth` property on FileInput's outermost element
|
|
135
|
-
*/
|
|
136
48
|
maxWidth: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
|
|
137
|
-
|
|
138
|
-
/**
|
|
139
|
-
* Set the CSS `minWidth` property on FileInput's outermost element
|
|
140
|
-
*/
|
|
141
49
|
minWidth: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
|
|
142
|
-
|
|
143
|
-
/**
|
|
144
|
-
* Valid values are 0, none, auto, xxx-small, xx-small, x-small, small,
|
|
145
|
-
* medium, large, x-large, xx-large. Apply these values via familiar
|
|
146
|
-
* CSS-like shorthand. For example: margin="small auto large".
|
|
147
|
-
*/
|
|
148
50
|
margin: ThemeablePropTypes.spacing
|
|
149
51
|
};
|
|
150
52
|
const allowedProps = ['id', 'renderLabel', 'accept', 'messages', 'onClick', 'onDrop', 'onDropAccepted', 'onDropRejected', 'onDragEnter', 'onDragOver', 'onDragLeave', 'shouldEnablePreview', 'shouldAllowMultiple', 'shouldAllowRepeats', 'maxSize', 'minSize', 'interaction', 'display', 'height', 'width', 'maxWidth', 'minWidth', 'margin'];
|