@sb1/ffe-file-upload-react 10.0.52 → 11.0.0

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/es/FileItem.js CHANGED
@@ -1,7 +1,6 @@
1
1
  import React from 'react';
2
- import { func, shape, object, string as stringType } from 'prop-types';
3
2
  import { Icon } from '@sb1/ffe-icons-react';
4
- var FileItem = function FileItem(_ref) {
3
+ export function FileItem(_ref) {
5
4
  var file = _ref.file,
6
5
  onFileDeleted = _ref.onFileDeleted,
7
6
  cancelText = _ref.cancelText,
@@ -74,21 +73,4 @@ var FileItem = function FileItem(_ref) {
74
73
  }, file.name), /*#__PURE__*/React.createElement("div", {
75
74
  className: "ffe-file-upload__file-item-error-message"
76
75
  }, file.error))));
77
- };
78
- FileItem.propTypes = {
79
- /** Shape of the file type, name is required, error and document.content is optional */
80
- file: shape({
81
- name: stringType.isRequired,
82
- document: object,
83
- error: stringType
84
- }).isRequired,
85
- /**
86
- * Called when the user clicks the delete button for a given file. Is called with the name of the file in question.
87
- */
88
- onFileDeleted: func.isRequired,
89
- /** Label for the cancel button */
90
- cancelText: stringType,
91
- /** Label for the delete button */
92
- deleteText: stringType
93
- };
94
- export default FileItem;
76
+ }
package/es/FileUpload.js CHANGED
@@ -1,203 +1,112 @@
1
- function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); }
2
- function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
3
- function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, _toPropertyKey(descriptor.key), descriptor); } }
4
- function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); Object.defineProperty(Constructor, "prototype", { writable: false }); return Constructor; }
5
- function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == _typeof(i) ? i : i + ""; }
6
- function _toPrimitive(t, r) { if ("object" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != _typeof(i)) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); }
7
- function _callSuper(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); }
8
- function _possibleConstructorReturn(self, call) { if (call && (_typeof(call) === "object" || typeof call === "function")) { return call; } else if (call !== void 0) { throw new TypeError("Derived constructors may only return object or undefined"); } return _assertThisInitialized(self); }
9
- function _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return self; }
10
- function _isNativeReflectConstruct() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct = function _isNativeReflectConstruct() { return !!t; })(); }
11
- function _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf.bind() : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); }
12
- function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function"); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, writable: true, configurable: true } }); Object.defineProperty(subClass, "prototype", { writable: false }); if (superClass) _setPrototypeOf(subClass, superClass); }
13
- function _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); }
14
- import React from 'react';
15
- import { object, bool, func, string as stringType } from 'prop-types';
16
- import FileItem from './FileItem';
1
+ function _slicedToArray(arr, i) { return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _unsupportedIterableToArray(arr, i) || _nonIterableRest(); }
2
+ function _nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
3
+ function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); }
4
+ function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i]; return arr2; }
5
+ function _iterableToArrayLimit(r, l) { var t = null == r ? null : "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"]; if (null != t) { var e, n, i, u, a = [], f = !0, o = !1; try { if (i = (t = t.call(r)).next, 0 === l) { if (Object(t) !== t) return; f = !1; } else for (; !(f = (e = i.call(t)).done) && (a.push(e.value), a.length !== l); f = !0); } catch (r) { o = !0, n = r; } finally { try { if (!f && null != t.return && (u = t.return(), Object(u) !== u)) return; } finally { if (o) throw n; } } return a; } }
6
+ function _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; }
7
+ import React, { useRef, useState } from 'react';
8
+ import { FileItem } from './FileItem';
17
9
  import classNames from 'classnames';
18
10
  import { SecondaryButton } from '@sb1/ffe-buttons-react';
19
11
  import { Icon } from '@sb1/ffe-icons-react';
20
- var FileUpload = /*#__PURE__*/function (_React$Component) {
21
- function FileUpload(props) {
22
- var _this;
23
- _classCallCheck(this, FileUpload);
24
- _this = _callSuper(this, FileUpload, [props]);
25
- _this.onFilesSelected = _this.onFilesSelected.bind(_this);
26
- _this.onFilesDropped = _this.onFilesDropped.bind(_this);
27
- _this.onFileDeleted = _this.onFileDeleted.bind(_this);
28
- _this.setFileInputElement = _this.setFileInputElement.bind(_this);
29
- _this.triggerUploadFileNativeHandler = _this.triggerUploadFileNativeHandler.bind(_this);
30
- _this.state = {
31
- hover: false
32
- };
33
- return _this;
34
- }
35
- _inherits(FileUpload, _React$Component);
36
- return _createClass(FileUpload, [{
37
- key: "setFileInputElement",
38
- value: function setFileInputElement(element) {
39
- this.fileInputElement = element;
12
+ export function FileUpload(_ref) {
13
+ var id = _ref.id,
14
+ label = _ref.label,
15
+ files = _ref.files,
16
+ cancelText = _ref.cancelText,
17
+ deleteText = _ref.deleteText,
18
+ multiple = _ref.multiple,
19
+ title = _ref.title,
20
+ infoText = _ref.infoText,
21
+ infoSubText = _ref.infoSubText,
22
+ uploadTitle = _ref.uploadTitle,
23
+ uploadMicroText = _ref.uploadMicroText,
24
+ uploadSubText = _ref.uploadSubText,
25
+ accept = _ref.accept,
26
+ onFilesDropped = _ref.onFilesDropped,
27
+ onFileDeleted = _ref.onFileDeleted,
28
+ onFilesSelected = _ref.onFilesSelected;
29
+ var _useState = useState(false),
30
+ _useState2 = _slicedToArray(_useState, 2),
31
+ isHover = _useState2[0],
32
+ setIsHover = _useState2[1];
33
+ var fileInputElement = useRef(null);
34
+ var downloadIcon = 'data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIGhlaWdodD0iMjAiIHZpZXdCb3g9IjAgLTk2MCA5NjAgOTYwIiB3aWR0aD0iMjAiPjxwYXRoIGQ9Ik00NzkuOC0zNTcuNTM5cS02LjQzMSAwLTExLjk2MS0yLjMwOC01LjUzMS0yLjMwNy0xMC4xNDYtNi45MjNMMzM1LjMwOS00ODkuMTUzcS03LjkyMy03LjgzMi03LjgwNy0xOC4zMzguMTE1LTEwLjUwNyA4LjMyOS0xOC44MTUgOC43ODYtOC4zMDcgMTguODYyLTguMTE1IDEwLjA3Ny4xOTIgMTguMzg1IDguNWw4MC45MjMgODEuOTIzdi0zMjYuMDAxcTAtMTEuMDY5IDcuNDA0LTE4LjUzNCA3LjQwNS03LjQ2NiAxOC4zODQtNy40NjYgMTAuOTggMCAxOC41OTUgNy40NjYgNy42MTUgNy40NjUgNy42MTUgMTguNTM0djMyNi4wMDFsODEuOTIzLTgxLjkyM3E3LjU5LTcuOTIzIDE4LjAyNi03LjgwOCAxMC40MzUuMTE2IDE5LjIyMSA4LjQyMyA4LjIxNCA4LjMwOCA4LjAyMSAxOC41NzctLjE5MiAxMC4yNjktOC40OTkgMTguNTc2TDUwMi4zMDctMzY2Ljc3cS01LjAxNSA0LjYxNi0xMC41NDYgNi45MjMtNS41MyAyLjMwOC0xMS45NjEgMi4zMDhaTTI3Ni4wMjUtMjEyLjAwMXEtMjcuMDI0IDAtNDUuNTI0LTE4LjY1dC0xOC41LTQ1LjY1OHYtMzQuNDYxcTAtMTEuMDY5IDcuNDA1LTE4LjUzNCA3LjQwNS03LjQ2NSAxOC4zODQtNy40NjUgMTAuOTggMCAxOC41OTUgNy40NjVRMjY0LTMyMS44MzkgMjY0LTMxMC43N3YzNC40NjFxMCA0LjYxNiAzLjg0NiA4LjQ2MyAzLjg0NyAzLjg0NiA4LjQ2MyAzLjg0Nmg0MDcuMzgycTQuNjE2IDAgOC40NjMtMy44NDYgMy44NDYtMy44NDcgMy44NDYtOC40NjN2LTM0LjQ2MXEwLTExLjA2OSA3LjQwNS0xOC41MzQgNy40MDQtNy40NjUgMTguMzg0LTcuNDY1IDEwLjk3OSAwIDE4LjU5NCA3LjQ2NSA3LjYxNiA3LjQ2NSA3LjYxNiAxOC41MzR2MzQuNDYxcTAgMjcuMDA4LTE4LjY2MiA0NS42NTgtMTguNjYyIDE4LjY1LTQ1LjY4NiAxOC42NUgyNzYuMDI1WiIvPjwvc3ZnPg==';
35
+ var handleFilesDropped = function handleFilesDropped(event) {
36
+ event.preventDefault();
37
+ setIsHover(false);
38
+ onFilesDropped(event.dataTransfer.files);
39
+ };
40
+ var handleFileDeleted = function handleFileDeleted(event) {
41
+ onFileDeleted(files[event.currentTarget.id]);
42
+ };
43
+ var triggerUploadFileNativeHandler = function triggerUploadFileNativeHandler() {
44
+ // clear file input to trigger onChange when uploading same filename
45
+ if (fileInputElement.current) {
46
+ fileInputElement.current.value = '';
47
+ fileInputElement.current.click();
40
48
  }
41
- }, {
42
- key: "triggerUploadFileNativeHandler",
43
- value: function triggerUploadFileNativeHandler() {
44
- // clear file input to trigger onChange when uploading same filename
45
- if (this.fileInputElement) {
46
- this.fileInputElement.value = '';
47
- }
48
- this.fileInputElement.click();
49
- }
50
- }, {
51
- key: "onFilesSelected",
52
- value: function onFilesSelected(event) {
53
- this.props.onFilesSelected(event.target.files);
54
- }
55
- }, {
56
- key: "onFilesDropped",
57
- value: function onFilesDropped(event) {
49
+ };
50
+ var handleFileSelected = function handleFileSelected(event) {
51
+ onFilesSelected(event.target.files);
52
+ };
53
+ return /*#__PURE__*/React.createElement("div", {
54
+ className: "ffe-file-upload"
55
+ }, /*#__PURE__*/React.createElement("div", {
56
+ className: "ffe-file-upload__title"
57
+ }, title), Object.keys(files).length > 0 ? /*#__PURE__*/React.createElement("div", {
58
+ className: "ffe-file-upload__file-items-section"
59
+ }, Object.keys(files).map(function (file) {
60
+ return /*#__PURE__*/React.createElement(FileItem, {
61
+ key: file,
62
+ file: files[file],
63
+ cancelText: cancelText,
64
+ deleteText: deleteText,
65
+ onFileDeleted: handleFileDeleted
66
+ });
67
+ })) : /*#__PURE__*/React.createElement("div", {
68
+ className: "ffe-file-upload__info-section"
69
+ }, /*#__PURE__*/React.createElement("div", {
70
+ className: "ffe-file-upload__info-section-text"
71
+ }, infoText), /*#__PURE__*/React.createElement("div", {
72
+ className: "ffe-file-upload__info-section-subtext"
73
+ }, infoSubText)), /*#__PURE__*/React.createElement("div", {
74
+ className: "ffe-file-upload__upload-section",
75
+ role: "presentation",
76
+ onDrop: handleFilesDropped,
77
+ onDragOver: function onDragOver(event) {
58
78
  event.preventDefault();
59
- this.setState({
60
- hover: false
61
- });
62
- this.props.onFilesDropped(event.dataTransfer.files);
63
- }
64
- }, {
65
- key: "onFileDeleted",
66
- value: function onFileDeleted(event) {
67
- this.props.onFileDeleted(this.props.files[event.currentTarget.id]);
68
- }
69
- }, {
70
- key: "render",
71
- value: function render() {
72
- var _this2 = this;
73
- var _this$props = this.props,
74
- id = _this$props.id,
75
- label = _this$props.label,
76
- files = _this$props.files,
77
- cancelText = _this$props.cancelText,
78
- deleteText = _this$props.deleteText,
79
- multiple = _this$props.multiple,
80
- title = _this$props.title,
81
- infoText = _this$props.infoText,
82
- infoSubText = _this$props.infoSubText,
83
- uploadTitle = _this$props.uploadTitle,
84
- uploadMicroText = _this$props.uploadMicroText,
85
- uploadSubText = _this$props.uploadSubText,
86
- accept = _this$props.accept;
87
- var downloadIcon = 'data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIGhlaWdodD0iMjAiIHZpZXdCb3g9IjAgLTk2MCA5NjAgOTYwIiB3aWR0aD0iMjAiPjxwYXRoIGQ9Ik00NzkuOC0zNTcuNTM5cS02LjQzMSAwLTExLjk2MS0yLjMwOC01LjUzMS0yLjMwNy0xMC4xNDYtNi45MjNMMzM1LjMwOS00ODkuMTUzcS03LjkyMy03LjgzMi03LjgwNy0xOC4zMzguMTE1LTEwLjUwNyA4LjMyOS0xOC44MTUgOC43ODYtOC4zMDcgMTguODYyLTguMTE1IDEwLjA3Ny4xOTIgMTguMzg1IDguNWw4MC45MjMgODEuOTIzdi0zMjYuMDAxcTAtMTEuMDY5IDcuNDA0LTE4LjUzNCA3LjQwNS03LjQ2NiAxOC4zODQtNy40NjYgMTAuOTggMCAxOC41OTUgNy40NjYgNy42MTUgNy40NjUgNy42MTUgMTguNTM0djMyNi4wMDFsODEuOTIzLTgxLjkyM3E3LjU5LTcuOTIzIDE4LjAyNi03LjgwOCAxMC40MzUuMTE2IDE5LjIyMSA4LjQyMyA4LjIxNCA4LjMwOCA4LjAyMSAxOC41NzctLjE5MiAxMC4yNjktOC40OTkgMTguNTc2TDUwMi4zMDctMzY2Ljc3cS01LjAxNSA0LjYxNi0xMC41NDYgNi45MjMtNS41MyAyLjMwOC0xMS45NjEgMi4zMDhaTTI3Ni4wMjUtMjEyLjAwMXEtMjcuMDI0IDAtNDUuNTI0LTE4LjY1dC0xOC41LTQ1LjY1OHYtMzQuNDYxcTAtMTEuMDY5IDcuNDA1LTE4LjUzNCA3LjQwNS03LjQ2NSAxOC4zODQtNy40NjUgMTAuOTggMCAxOC41OTUgNy40NjVRMjY0LTMyMS44MzkgMjY0LTMxMC43N3YzNC40NjFxMCA0LjYxNiAzLjg0NiA4LjQ2MyAzLjg0NyAzLjg0NiA4LjQ2MyAzLjg0Nmg0MDcuMzgycTQuNjE2IDAgOC40NjMtMy44NDYgMy44NDYtMy44NDcgMy44NDYtOC40NjN2LTM0LjQ2MXEwLTExLjA2OSA3LjQwNS0xOC41MzQgNy40MDQtNy40NjUgMTguMzg0LTcuNDY1IDEwLjk3OSAwIDE4LjU5NCA3LjQ2NSA3LjYxNiA3LjQ2NSA3LjYxNiAxOC41MzR2MzQuNDYxcTAgMjcuMDA4LTE4LjY2MiA0NS42NTgtMTguNjYyIDE4LjY1LTQ1LjY4NiAxOC42NUgyNzYuMDI1WiIvPjwvc3ZnPg==';
88
- return /*#__PURE__*/React.createElement("div", {
89
- className: "ffe-file-upload"
90
- }, /*#__PURE__*/React.createElement("div", {
91
- className: "ffe-file-upload__title"
92
- }, title), Object.keys(files).length > 0 ? /*#__PURE__*/React.createElement("div", {
93
- className: "ffe-file-upload__file-items-section"
94
- }, Object.keys(files).map(function (file) {
95
- return /*#__PURE__*/React.createElement(FileItem, {
96
- key: file,
97
- file: files[file],
98
- cancelText: cancelText,
99
- deleteText: deleteText,
100
- onFileDeleted: _this2.onFileDeleted
101
- });
102
- })) : /*#__PURE__*/React.createElement("div", {
103
- className: "ffe-file-upload__info-section"
104
- }, /*#__PURE__*/React.createElement("div", {
105
- className: "ffe-file-upload__info-section-text"
106
- }, infoText), /*#__PURE__*/React.createElement("div", {
107
- className: "ffe-file-upload__info-section-subtext"
108
- }, infoSubText)), /*#__PURE__*/React.createElement("div", {
109
- className: "ffe-file-upload__upload-section",
110
- role: "presentation",
111
- onDrop: this.onFilesDropped,
112
- onDragOver: function onDragOver(event) {
113
- event.preventDefault();
114
- _this2.setState({
115
- hover: true
116
- });
117
- },
118
- onDragLeave: function onDragLeave() {
119
- return _this2.setState({
120
- hover: false
121
- });
122
- }
123
- }, /*#__PURE__*/React.createElement("div", {
124
- className: classNames('ffe-file-upload__upload-section-border', {
125
- 'ffe-file-upload__upload-section-border--hover': this.state.hover
126
- })
127
- }, /*#__PURE__*/React.createElement("div", {
128
- className: "ffe-file-upload__upload-section-title"
129
- }, uploadTitle), /*#__PURE__*/React.createElement("div", {
130
- className: "ffe-file-upload__upload-section-microtext"
131
- }, uploadMicroText), /*#__PURE__*/React.createElement(SecondaryButton, {
132
- leftIcon: /*#__PURE__*/React.createElement(Icon, {
133
- fileUrl: downloadIcon,
134
- size: "sm"
135
- }),
136
- onClick: this.triggerUploadFileNativeHandler,
137
- id: "".concat(id, "-button")
138
- }, /*#__PURE__*/React.createElement("span", {
139
- id: "".concat(id, "-label")
140
- }, label)), /*#__PURE__*/React.createElement("div", {
141
- className: "ffe-file-upload__upload-section-subtext"
142
- }, uploadSubText))), /*#__PURE__*/React.createElement("input", {
143
- id: id,
144
- type: "file",
145
- multiple: multiple,
146
- ref: this.setFileInputElement,
147
- onChange: this.onFilesSelected,
148
- "aria-labelledby": "".concat(id, "-label"),
149
- accept: accept || '*'
150
- }));
79
+ setIsHover(true);
80
+ },
81
+ onDragLeave: function onDragLeave() {
82
+ return setIsHover(false);
151
83
  }
152
- }]);
153
- }(React.Component);
154
- FileUpload.propTypes = {
155
- /** ID for the input field. The ID is used as a base for the label ID as well. */
156
- id: stringType.isRequired,
157
- /** Label for the button to trigger native upload handling. */
158
- label: stringType.isRequired,
159
- /**
160
- * A map of files, indexed by file name (check file-shape on FileItem.js propTypes), that the user has uploaded.
161
- * Must be maintained outside of `FileUpload`. It is up to the implementation to deny or accept file types, sizes, etc,
162
- * and it is important that duplicates are not allowed.
163
- * */
164
- files: object.isRequired,
165
- /**
166
- * Will be called with `FileList`-object containing the `File`-objects the user selected.
167
- * See MDN for documentation on
168
- * [FileList](https://developer.mozilla.org/en-US/docs/Web/API/FileList) and
169
- * [File](https://developer.mozilla.org/en-US/docs/Web/API/File).
170
- */
171
- onFilesSelected: func.isRequired,
172
- /** Will be called when objects are dropped over the upload-section. */
173
- onFilesDropped: func.isRequired,
174
- /**
175
- * Called when the user clicks the delete button for a given file. Is called with the `File`
176
- * object of the file in question.
177
- */
178
- onFileDeleted: func.isRequired,
179
- /** Whether or not uploading multiple files at once via the native file handler is allowed*/
180
- multiple: bool,
181
- /** Title module */
182
- title: stringType.isRequired,
183
- /** Text on the info-section */
184
- infoText: stringType.isRequired,
185
- /** Subtext on the info-section */
186
- infoSubText: stringType,
187
- /** Label for the cancel button */
188
- cancelText: stringType,
189
- /** Label for the delete button */
190
- deleteText: stringType,
191
- /** Title on the upload-section */
192
- uploadTitle: stringType.isRequired,
193
- /** MicroText on the upload-section */
194
- uploadMicroText: stringType.isRequired,
195
- /** SubText on the upload-section */
196
- uploadSubText: stringType.isRequired,
197
- /** Unique file type specifier that describes a type of file that may be selected by the user, e.g. ".pdf"
198
- * See MDN for documentation on
199
- * [Unique file type specifiers](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input/file#unique_file_type_specifiers)
200
- */
201
- accept: stringType
202
- };
203
- export default FileUpload;
84
+ }, /*#__PURE__*/React.createElement("div", {
85
+ className: classNames('ffe-file-upload__upload-section-border', {
86
+ 'ffe-file-upload__upload-section-border--hover': isHover
87
+ })
88
+ }, /*#__PURE__*/React.createElement("div", {
89
+ className: "ffe-file-upload__upload-section-title"
90
+ }, uploadTitle), /*#__PURE__*/React.createElement("div", {
91
+ className: "ffe-file-upload__upload-section-microtext"
92
+ }, uploadMicroText), /*#__PURE__*/React.createElement(SecondaryButton, {
93
+ leftIcon: /*#__PURE__*/React.createElement(Icon, {
94
+ fileUrl: downloadIcon,
95
+ size: "sm"
96
+ }),
97
+ onClick: triggerUploadFileNativeHandler,
98
+ id: "".concat(id, "-button")
99
+ }, /*#__PURE__*/React.createElement("span", {
100
+ id: "".concat(id, "-label")
101
+ }, label)), /*#__PURE__*/React.createElement("div", {
102
+ className: "ffe-file-upload__upload-section-subtext"
103
+ }, uploadSubText))), /*#__PURE__*/React.createElement("input", {
104
+ id: id,
105
+ type: "file",
106
+ multiple: multiple,
107
+ ref: fileInputElement,
108
+ onChange: handleFileSelected,
109
+ "aria-labelledby": "".concat(id, "-label"),
110
+ accept: accept || '*'
111
+ }));
112
+ }
@@ -0,0 +1,62 @@
1
+ function _extends() { _extends = Object.assign ? Object.assign.bind() : function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); }
2
+ import React from 'react';
3
+ import { spy } from 'sinon';
4
+ import { FileUpload } from './FileUpload';
5
+ import { render, screen, fireEvent } from '@testing-library/react';
6
+ var renderFileUpload = function renderFileUpload(props) {
7
+ return render( /*#__PURE__*/React.createElement(FileUpload, _extends({
8
+ id: "file-upload",
9
+ label: "label",
10
+ title: "title",
11
+ infoText: "infoText",
12
+ uploadTitle: "uploadTitle",
13
+ uploadMicroText: "uploadMicroText",
14
+ uploadSubText: "uploadSubText",
15
+ files: {},
16
+ onFilesSelected: function onFilesSelected() {},
17
+ onFileDeleted: function onFileDeleted() {},
18
+ onFilesDropped: function onFilesDropped() {}
19
+ }, props)));
20
+ };
21
+ describe('<FileUpload/>', function () {
22
+ it('should have a button and input', function () {
23
+ var _renderFileUpload = renderFileUpload(),
24
+ container = _renderFileUpload.container;
25
+ expect(container.querySelector('#file-upload-button')).toBeTruthy();
26
+ expect(container.querySelector('#file-upload')).toBeTruthy();
27
+ });
28
+ it('should render input label', function () {
29
+ renderFileUpload();
30
+ expect(screen.getByRole('button', {
31
+ name: 'label'
32
+ })).toBeInTheDocument();
33
+ });
34
+ it('should extract and return files when user finishes selecting files', function () {
35
+ var onFilesSelected = spy();
36
+ var _renderFileUpload2 = renderFileUpload({
37
+ onFilesSelected: onFilesSelected
38
+ }),
39
+ container = _renderFileUpload2.container;
40
+ var input = container.querySelector('input#file-upload');
41
+ fireEvent.change(input);
42
+ expect(onFilesSelected.calledOnce).toBe(true);
43
+ });
44
+ it('should remove file from files when delete button is clicked', function () {
45
+ var onFileDeleted = spy();
46
+ // Do click on span inside button with event listener instead of actual button to catch nested clicks.
47
+ var _renderFileUpload3 = renderFileUpload({
48
+ onFileDeleted: onFileDeleted,
49
+ files: {
50
+ fileToDelete: {
51
+ name: 'fileToDelete'
52
+ }
53
+ }
54
+ }),
55
+ container = _renderFileUpload3.container;
56
+ var deleteButton = container.querySelector('.ffe-file-upload__file-item-delete-button-text');
57
+ fireEvent.click(deleteButton);
58
+ expect(onFileDeleted.calledWith({
59
+ name: 'fileToDelete'
60
+ })).toBe(true);
61
+ });
62
+ });
@@ -2,7 +2,7 @@ export var getFileContent = function getFileContent(file) {
2
2
  return new Promise(function (resolve, reject) {
3
3
  var reader = new window.FileReader();
4
4
  reader.onload = function (event) {
5
- return resolve(event.target.result);
5
+ return resolve(event.target ? event.target.result : null);
6
6
  };
7
7
  reader.onerror = function (error) {
8
8
  return reject(error);
package/es/index.js CHANGED
@@ -1,3 +1,2 @@
1
- import FileUpload from './FileUpload';
2
- export { getFileContent } from './file-content';
3
- export default FileUpload;
1
+ export { FileUpload, FileUploadProps } from './FileUpload';
2
+ export { getFileContent } from './getFileContent';
package/lib/FileItem.js CHANGED
@@ -3,12 +3,11 @@
3
3
  Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
- exports.default = void 0;
6
+ exports.FileItem = FileItem;
7
7
  var _react = _interopRequireDefault(require("react"));
8
- var _propTypes = require("prop-types");
9
8
  var _ffeIconsReact = require("@sb1/ffe-icons-react");
10
9
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
11
- var FileItem = function FileItem(_ref) {
10
+ function FileItem(_ref) {
12
11
  var file = _ref.file,
13
12
  onFileDeleted = _ref.onFileDeleted,
14
13
  cancelText = _ref.cancelText,
@@ -81,21 +80,4 @@ var FileItem = function FileItem(_ref) {
81
80
  }, file.name), /*#__PURE__*/_react.default.createElement("div", {
82
81
  className: "ffe-file-upload__file-item-error-message"
83
82
  }, file.error))));
84
- };
85
- FileItem.propTypes = {
86
- /** Shape of the file type, name is required, error and document.content is optional */
87
- file: (0, _propTypes.shape)({
88
- name: _propTypes.string.isRequired,
89
- document: _propTypes.object,
90
- error: _propTypes.string
91
- }).isRequired,
92
- /**
93
- * Called when the user clicks the delete button for a given file. Is called with the name of the file in question.
94
- */
95
- onFileDeleted: _propTypes.func.isRequired,
96
- /** Label for the cancel button */
97
- cancelText: _propTypes.string,
98
- /** Label for the delete button */
99
- deleteText: _propTypes.string
100
- };
101
- var _default = exports.default = FileItem;
83
+ }
package/lib/FileUpload.js CHANGED
@@ -4,207 +4,119 @@ function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" ==
4
4
  Object.defineProperty(exports, "__esModule", {
5
5
  value: true
6
6
  });
7
- exports.default = void 0;
8
- var _react = _interopRequireDefault(require("react"));
9
- var _propTypes = require("prop-types");
10
- var _FileItem = _interopRequireDefault(require("./FileItem"));
7
+ exports.FileUpload = FileUpload;
8
+ var _react = _interopRequireWildcard(require("react"));
9
+ var _FileItem = require("./FileItem");
11
10
  var _classnames = _interopRequireDefault(require("classnames"));
12
11
  var _ffeButtonsReact = require("@sb1/ffe-buttons-react");
13
12
  var _ffeIconsReact = require("@sb1/ffe-icons-react");
14
13
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
15
- function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
16
- function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, _toPropertyKey(descriptor.key), descriptor); } }
17
- function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); Object.defineProperty(Constructor, "prototype", { writable: false }); return Constructor; }
18
- function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == _typeof(i) ? i : i + ""; }
19
- function _toPrimitive(t, r) { if ("object" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != _typeof(i)) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); }
20
- function _callSuper(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); }
21
- function _possibleConstructorReturn(self, call) { if (call && (_typeof(call) === "object" || typeof call === "function")) { return call; } else if (call !== void 0) { throw new TypeError("Derived constructors may only return object or undefined"); } return _assertThisInitialized(self); }
22
- function _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return self; }
23
- function _isNativeReflectConstruct() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct = function _isNativeReflectConstruct() { return !!t; })(); }
24
- function _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf.bind() : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); }
25
- function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function"); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, writable: true, configurable: true } }); Object.defineProperty(subClass, "prototype", { writable: false }); if (superClass) _setPrototypeOf(subClass, superClass); }
26
- function _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); }
27
- var FileUpload = /*#__PURE__*/function (_React$Component) {
28
- function FileUpload(props) {
29
- var _this;
30
- _classCallCheck(this, FileUpload);
31
- _this = _callSuper(this, FileUpload, [props]);
32
- _this.onFilesSelected = _this.onFilesSelected.bind(_this);
33
- _this.onFilesDropped = _this.onFilesDropped.bind(_this);
34
- _this.onFileDeleted = _this.onFileDeleted.bind(_this);
35
- _this.setFileInputElement = _this.setFileInputElement.bind(_this);
36
- _this.triggerUploadFileNativeHandler = _this.triggerUploadFileNativeHandler.bind(_this);
37
- _this.state = {
38
- hover: false
39
- };
40
- return _this;
41
- }
42
- _inherits(FileUpload, _React$Component);
43
- return _createClass(FileUpload, [{
44
- key: "setFileInputElement",
45
- value: function setFileInputElement(element) {
46
- this.fileInputElement = element;
14
+ function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function _getRequireWildcardCache(e) { return e ? t : r; })(e); }
15
+ function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != _typeof(e) && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && {}.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; }
16
+ function _slicedToArray(arr, i) { return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _unsupportedIterableToArray(arr, i) || _nonIterableRest(); }
17
+ function _nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
18
+ function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); }
19
+ function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i]; return arr2; }
20
+ function _iterableToArrayLimit(r, l) { var t = null == r ? null : "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"]; if (null != t) { var e, n, i, u, a = [], f = !0, o = !1; try { if (i = (t = t.call(r)).next, 0 === l) { if (Object(t) !== t) return; f = !1; } else for (; !(f = (e = i.call(t)).done) && (a.push(e.value), a.length !== l); f = !0); } catch (r) { o = !0, n = r; } finally { try { if (!f && null != t.return && (u = t.return(), Object(u) !== u)) return; } finally { if (o) throw n; } } return a; } }
21
+ function _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; }
22
+ function FileUpload(_ref) {
23
+ var id = _ref.id,
24
+ label = _ref.label,
25
+ files = _ref.files,
26
+ cancelText = _ref.cancelText,
27
+ deleteText = _ref.deleteText,
28
+ multiple = _ref.multiple,
29
+ title = _ref.title,
30
+ infoText = _ref.infoText,
31
+ infoSubText = _ref.infoSubText,
32
+ uploadTitle = _ref.uploadTitle,
33
+ uploadMicroText = _ref.uploadMicroText,
34
+ uploadSubText = _ref.uploadSubText,
35
+ accept = _ref.accept,
36
+ onFilesDropped = _ref.onFilesDropped,
37
+ onFileDeleted = _ref.onFileDeleted,
38
+ onFilesSelected = _ref.onFilesSelected;
39
+ var _useState = (0, _react.useState)(false),
40
+ _useState2 = _slicedToArray(_useState, 2),
41
+ isHover = _useState2[0],
42
+ setIsHover = _useState2[1];
43
+ var fileInputElement = (0, _react.useRef)(null);
44
+ var downloadIcon = 'data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIGhlaWdodD0iMjAiIHZpZXdCb3g9IjAgLTk2MCA5NjAgOTYwIiB3aWR0aD0iMjAiPjxwYXRoIGQ9Ik00NzkuOC0zNTcuNTM5cS02LjQzMSAwLTExLjk2MS0yLjMwOC01LjUzMS0yLjMwNy0xMC4xNDYtNi45MjNMMzM1LjMwOS00ODkuMTUzcS03LjkyMy03LjgzMi03LjgwNy0xOC4zMzguMTE1LTEwLjUwNyA4LjMyOS0xOC44MTUgOC43ODYtOC4zMDcgMTguODYyLTguMTE1IDEwLjA3Ny4xOTIgMTguMzg1IDguNWw4MC45MjMgODEuOTIzdi0zMjYuMDAxcTAtMTEuMDY5IDcuNDA0LTE4LjUzNCA3LjQwNS03LjQ2NiAxOC4zODQtNy40NjYgMTAuOTggMCAxOC41OTUgNy40NjYgNy42MTUgNy40NjUgNy42MTUgMTguNTM0djMyNi4wMDFsODEuOTIzLTgxLjkyM3E3LjU5LTcuOTIzIDE4LjAyNi03LjgwOCAxMC40MzUuMTE2IDE5LjIyMSA4LjQyMyA4LjIxNCA4LjMwOCA4LjAyMSAxOC41NzctLjE5MiAxMC4yNjktOC40OTkgMTguNTc2TDUwMi4zMDctMzY2Ljc3cS01LjAxNSA0LjYxNi0xMC41NDYgNi45MjMtNS41MyAyLjMwOC0xMS45NjEgMi4zMDhaTTI3Ni4wMjUtMjEyLjAwMXEtMjcuMDI0IDAtNDUuNTI0LTE4LjY1dC0xOC41LTQ1LjY1OHYtMzQuNDYxcTAtMTEuMDY5IDcuNDA1LTE4LjUzNCA3LjQwNS03LjQ2NSAxOC4zODQtNy40NjUgMTAuOTggMCAxOC41OTUgNy40NjVRMjY0LTMyMS44MzkgMjY0LTMxMC43N3YzNC40NjFxMCA0LjYxNiAzLjg0NiA4LjQ2MyAzLjg0NyAzLjg0NiA4LjQ2MyAzLjg0Nmg0MDcuMzgycTQuNjE2IDAgOC40NjMtMy44NDYgMy44NDYtMy44NDcgMy44NDYtOC40NjN2LTM0LjQ2MXEwLTExLjA2OSA3LjQwNS0xOC41MzQgNy40MDQtNy40NjUgMTguMzg0LTcuNDY1IDEwLjk3OSAwIDE4LjU5NCA3LjQ2NSA3LjYxNiA3LjQ2NSA3LjYxNiAxOC41MzR2MzQuNDYxcTAgMjcuMDA4LTE4LjY2MiA0NS42NTgtMTguNjYyIDE4LjY1LTQ1LjY4NiAxOC42NUgyNzYuMDI1WiIvPjwvc3ZnPg==';
45
+ var handleFilesDropped = function handleFilesDropped(event) {
46
+ event.preventDefault();
47
+ setIsHover(false);
48
+ onFilesDropped(event.dataTransfer.files);
49
+ };
50
+ var handleFileDeleted = function handleFileDeleted(event) {
51
+ onFileDeleted(files[event.currentTarget.id]);
52
+ };
53
+ var triggerUploadFileNativeHandler = function triggerUploadFileNativeHandler() {
54
+ // clear file input to trigger onChange when uploading same filename
55
+ if (fileInputElement.current) {
56
+ fileInputElement.current.value = '';
57
+ fileInputElement.current.click();
47
58
  }
48
- }, {
49
- key: "triggerUploadFileNativeHandler",
50
- value: function triggerUploadFileNativeHandler() {
51
- // clear file input to trigger onChange when uploading same filename
52
- if (this.fileInputElement) {
53
- this.fileInputElement.value = '';
54
- }
55
- this.fileInputElement.click();
56
- }
57
- }, {
58
- key: "onFilesSelected",
59
- value: function onFilesSelected(event) {
60
- this.props.onFilesSelected(event.target.files);
61
- }
62
- }, {
63
- key: "onFilesDropped",
64
- value: function onFilesDropped(event) {
59
+ };
60
+ var handleFileSelected = function handleFileSelected(event) {
61
+ onFilesSelected(event.target.files);
62
+ };
63
+ return /*#__PURE__*/_react.default.createElement("div", {
64
+ className: "ffe-file-upload"
65
+ }, /*#__PURE__*/_react.default.createElement("div", {
66
+ className: "ffe-file-upload__title"
67
+ }, title), Object.keys(files).length > 0 ? /*#__PURE__*/_react.default.createElement("div", {
68
+ className: "ffe-file-upload__file-items-section"
69
+ }, Object.keys(files).map(function (file) {
70
+ return /*#__PURE__*/_react.default.createElement(_FileItem.FileItem, {
71
+ key: file,
72
+ file: files[file],
73
+ cancelText: cancelText,
74
+ deleteText: deleteText,
75
+ onFileDeleted: handleFileDeleted
76
+ });
77
+ })) : /*#__PURE__*/_react.default.createElement("div", {
78
+ className: "ffe-file-upload__info-section"
79
+ }, /*#__PURE__*/_react.default.createElement("div", {
80
+ className: "ffe-file-upload__info-section-text"
81
+ }, infoText), /*#__PURE__*/_react.default.createElement("div", {
82
+ className: "ffe-file-upload__info-section-subtext"
83
+ }, infoSubText)), /*#__PURE__*/_react.default.createElement("div", {
84
+ className: "ffe-file-upload__upload-section",
85
+ role: "presentation",
86
+ onDrop: handleFilesDropped,
87
+ onDragOver: function onDragOver(event) {
65
88
  event.preventDefault();
66
- this.setState({
67
- hover: false
68
- });
69
- this.props.onFilesDropped(event.dataTransfer.files);
70
- }
71
- }, {
72
- key: "onFileDeleted",
73
- value: function onFileDeleted(event) {
74
- this.props.onFileDeleted(this.props.files[event.currentTarget.id]);
75
- }
76
- }, {
77
- key: "render",
78
- value: function render() {
79
- var _this2 = this;
80
- var _this$props = this.props,
81
- id = _this$props.id,
82
- label = _this$props.label,
83
- files = _this$props.files,
84
- cancelText = _this$props.cancelText,
85
- deleteText = _this$props.deleteText,
86
- multiple = _this$props.multiple,
87
- title = _this$props.title,
88
- infoText = _this$props.infoText,
89
- infoSubText = _this$props.infoSubText,
90
- uploadTitle = _this$props.uploadTitle,
91
- uploadMicroText = _this$props.uploadMicroText,
92
- uploadSubText = _this$props.uploadSubText,
93
- accept = _this$props.accept;
94
- var downloadIcon = 'data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIGhlaWdodD0iMjAiIHZpZXdCb3g9IjAgLTk2MCA5NjAgOTYwIiB3aWR0aD0iMjAiPjxwYXRoIGQ9Ik00NzkuOC0zNTcuNTM5cS02LjQzMSAwLTExLjk2MS0yLjMwOC01LjUzMS0yLjMwNy0xMC4xNDYtNi45MjNMMzM1LjMwOS00ODkuMTUzcS03LjkyMy03LjgzMi03LjgwNy0xOC4zMzguMTE1LTEwLjUwNyA4LjMyOS0xOC44MTUgOC43ODYtOC4zMDcgMTguODYyLTguMTE1IDEwLjA3Ny4xOTIgMTguMzg1IDguNWw4MC45MjMgODEuOTIzdi0zMjYuMDAxcTAtMTEuMDY5IDcuNDA0LTE4LjUzNCA3LjQwNS03LjQ2NiAxOC4zODQtNy40NjYgMTAuOTggMCAxOC41OTUgNy40NjYgNy42MTUgNy40NjUgNy42MTUgMTguNTM0djMyNi4wMDFsODEuOTIzLTgxLjkyM3E3LjU5LTcuOTIzIDE4LjAyNi03LjgwOCAxMC40MzUuMTE2IDE5LjIyMSA4LjQyMyA4LjIxNCA4LjMwOCA4LjAyMSAxOC41NzctLjE5MiAxMC4yNjktOC40OTkgMTguNTc2TDUwMi4zMDctMzY2Ljc3cS01LjAxNSA0LjYxNi0xMC41NDYgNi45MjMtNS41MyAyLjMwOC0xMS45NjEgMi4zMDhaTTI3Ni4wMjUtMjEyLjAwMXEtMjcuMDI0IDAtNDUuNTI0LTE4LjY1dC0xOC41LTQ1LjY1OHYtMzQuNDYxcTAtMTEuMDY5IDcuNDA1LTE4LjUzNCA3LjQwNS03LjQ2NSAxOC4zODQtNy40NjUgMTAuOTggMCAxOC41OTUgNy40NjVRMjY0LTMyMS44MzkgMjY0LTMxMC43N3YzNC40NjFxMCA0LjYxNiAzLjg0NiA4LjQ2MyAzLjg0NyAzLjg0NiA4LjQ2MyAzLjg0Nmg0MDcuMzgycTQuNjE2IDAgOC40NjMtMy44NDYgMy44NDYtMy44NDcgMy44NDYtOC40NjN2LTM0LjQ2MXEwLTExLjA2OSA3LjQwNS0xOC41MzQgNy40MDQtNy40NjUgMTguMzg0LTcuNDY1IDEwLjk3OSAwIDE4LjU5NCA3LjQ2NSA3LjYxNiA3LjQ2NSA3LjYxNiAxOC41MzR2MzQuNDYxcTAgMjcuMDA4LTE4LjY2MiA0NS42NTgtMTguNjYyIDE4LjY1LTQ1LjY4NiAxOC42NUgyNzYuMDI1WiIvPjwvc3ZnPg==';
95
- return /*#__PURE__*/_react.default.createElement("div", {
96
- className: "ffe-file-upload"
97
- }, /*#__PURE__*/_react.default.createElement("div", {
98
- className: "ffe-file-upload__title"
99
- }, title), Object.keys(files).length > 0 ? /*#__PURE__*/_react.default.createElement("div", {
100
- className: "ffe-file-upload__file-items-section"
101
- }, Object.keys(files).map(function (file) {
102
- return /*#__PURE__*/_react.default.createElement(_FileItem.default, {
103
- key: file,
104
- file: files[file],
105
- cancelText: cancelText,
106
- deleteText: deleteText,
107
- onFileDeleted: _this2.onFileDeleted
108
- });
109
- })) : /*#__PURE__*/_react.default.createElement("div", {
110
- className: "ffe-file-upload__info-section"
111
- }, /*#__PURE__*/_react.default.createElement("div", {
112
- className: "ffe-file-upload__info-section-text"
113
- }, infoText), /*#__PURE__*/_react.default.createElement("div", {
114
- className: "ffe-file-upload__info-section-subtext"
115
- }, infoSubText)), /*#__PURE__*/_react.default.createElement("div", {
116
- className: "ffe-file-upload__upload-section",
117
- role: "presentation",
118
- onDrop: this.onFilesDropped,
119
- onDragOver: function onDragOver(event) {
120
- event.preventDefault();
121
- _this2.setState({
122
- hover: true
123
- });
124
- },
125
- onDragLeave: function onDragLeave() {
126
- return _this2.setState({
127
- hover: false
128
- });
129
- }
130
- }, /*#__PURE__*/_react.default.createElement("div", {
131
- className: (0, _classnames.default)('ffe-file-upload__upload-section-border', {
132
- 'ffe-file-upload__upload-section-border--hover': this.state.hover
133
- })
134
- }, /*#__PURE__*/_react.default.createElement("div", {
135
- className: "ffe-file-upload__upload-section-title"
136
- }, uploadTitle), /*#__PURE__*/_react.default.createElement("div", {
137
- className: "ffe-file-upload__upload-section-microtext"
138
- }, uploadMicroText), /*#__PURE__*/_react.default.createElement(_ffeButtonsReact.SecondaryButton, {
139
- leftIcon: /*#__PURE__*/_react.default.createElement(_ffeIconsReact.Icon, {
140
- fileUrl: downloadIcon,
141
- size: "sm"
142
- }),
143
- onClick: this.triggerUploadFileNativeHandler,
144
- id: "".concat(id, "-button")
145
- }, /*#__PURE__*/_react.default.createElement("span", {
146
- id: "".concat(id, "-label")
147
- }, label)), /*#__PURE__*/_react.default.createElement("div", {
148
- className: "ffe-file-upload__upload-section-subtext"
149
- }, uploadSubText))), /*#__PURE__*/_react.default.createElement("input", {
150
- id: id,
151
- type: "file",
152
- multiple: multiple,
153
- ref: this.setFileInputElement,
154
- onChange: this.onFilesSelected,
155
- "aria-labelledby": "".concat(id, "-label"),
156
- accept: accept || '*'
157
- }));
89
+ setIsHover(true);
90
+ },
91
+ onDragLeave: function onDragLeave() {
92
+ return setIsHover(false);
158
93
  }
159
- }]);
160
- }(_react.default.Component);
161
- FileUpload.propTypes = {
162
- /** ID for the input field. The ID is used as a base for the label ID as well. */
163
- id: _propTypes.string.isRequired,
164
- /** Label for the button to trigger native upload handling. */
165
- label: _propTypes.string.isRequired,
166
- /**
167
- * A map of files, indexed by file name (check file-shape on FileItem.js propTypes), that the user has uploaded.
168
- * Must be maintained outside of `FileUpload`. It is up to the implementation to deny or accept file types, sizes, etc,
169
- * and it is important that duplicates are not allowed.
170
- * */
171
- files: _propTypes.object.isRequired,
172
- /**
173
- * Will be called with `FileList`-object containing the `File`-objects the user selected.
174
- * See MDN for documentation on
175
- * [FileList](https://developer.mozilla.org/en-US/docs/Web/API/FileList) and
176
- * [File](https://developer.mozilla.org/en-US/docs/Web/API/File).
177
- */
178
- onFilesSelected: _propTypes.func.isRequired,
179
- /** Will be called when objects are dropped over the upload-section. */
180
- onFilesDropped: _propTypes.func.isRequired,
181
- /**
182
- * Called when the user clicks the delete button for a given file. Is called with the `File`
183
- * object of the file in question.
184
- */
185
- onFileDeleted: _propTypes.func.isRequired,
186
- /** Whether or not uploading multiple files at once via the native file handler is allowed*/
187
- multiple: _propTypes.bool,
188
- /** Title module */
189
- title: _propTypes.string.isRequired,
190
- /** Text on the info-section */
191
- infoText: _propTypes.string.isRequired,
192
- /** Subtext on the info-section */
193
- infoSubText: _propTypes.string,
194
- /** Label for the cancel button */
195
- cancelText: _propTypes.string,
196
- /** Label for the delete button */
197
- deleteText: _propTypes.string,
198
- /** Title on the upload-section */
199
- uploadTitle: _propTypes.string.isRequired,
200
- /** MicroText on the upload-section */
201
- uploadMicroText: _propTypes.string.isRequired,
202
- /** SubText on the upload-section */
203
- uploadSubText: _propTypes.string.isRequired,
204
- /** Unique file type specifier that describes a type of file that may be selected by the user, e.g. ".pdf"
205
- * See MDN for documentation on
206
- * [Unique file type specifiers](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input/file#unique_file_type_specifiers)
207
- */
208
- accept: _propTypes.string
209
- };
210
- var _default = exports.default = FileUpload;
94
+ }, /*#__PURE__*/_react.default.createElement("div", {
95
+ className: (0, _classnames.default)('ffe-file-upload__upload-section-border', {
96
+ 'ffe-file-upload__upload-section-border--hover': isHover
97
+ })
98
+ }, /*#__PURE__*/_react.default.createElement("div", {
99
+ className: "ffe-file-upload__upload-section-title"
100
+ }, uploadTitle), /*#__PURE__*/_react.default.createElement("div", {
101
+ className: "ffe-file-upload__upload-section-microtext"
102
+ }, uploadMicroText), /*#__PURE__*/_react.default.createElement(_ffeButtonsReact.SecondaryButton, {
103
+ leftIcon: /*#__PURE__*/_react.default.createElement(_ffeIconsReact.Icon, {
104
+ fileUrl: downloadIcon,
105
+ size: "sm"
106
+ }),
107
+ onClick: triggerUploadFileNativeHandler,
108
+ id: "".concat(id, "-button")
109
+ }, /*#__PURE__*/_react.default.createElement("span", {
110
+ id: "".concat(id, "-label")
111
+ }, label)), /*#__PURE__*/_react.default.createElement("div", {
112
+ className: "ffe-file-upload__upload-section-subtext"
113
+ }, uploadSubText))), /*#__PURE__*/_react.default.createElement("input", {
114
+ id: id,
115
+ type: "file",
116
+ multiple: multiple,
117
+ ref: fileInputElement,
118
+ onChange: handleFileSelected,
119
+ "aria-labelledby": "".concat(id, "-label"),
120
+ accept: accept || '*'
121
+ }));
122
+ }
@@ -0,0 +1,65 @@
1
+ "use strict";
2
+
3
+ var _react = _interopRequireDefault(require("react"));
4
+ var _sinon = require("sinon");
5
+ var _FileUpload = require("./FileUpload");
6
+ var _react2 = require("@testing-library/react");
7
+ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
8
+ function _extends() { _extends = Object.assign ? Object.assign.bind() : function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); }
9
+ var renderFileUpload = function renderFileUpload(props) {
10
+ return (0, _react2.render)( /*#__PURE__*/_react.default.createElement(_FileUpload.FileUpload, _extends({
11
+ id: "file-upload",
12
+ label: "label",
13
+ title: "title",
14
+ infoText: "infoText",
15
+ uploadTitle: "uploadTitle",
16
+ uploadMicroText: "uploadMicroText",
17
+ uploadSubText: "uploadSubText",
18
+ files: {},
19
+ onFilesSelected: function onFilesSelected() {},
20
+ onFileDeleted: function onFileDeleted() {},
21
+ onFilesDropped: function onFilesDropped() {}
22
+ }, props)));
23
+ };
24
+ describe('<FileUpload/>', function () {
25
+ it('should have a button and input', function () {
26
+ var _renderFileUpload = renderFileUpload(),
27
+ container = _renderFileUpload.container;
28
+ expect(container.querySelector('#file-upload-button')).toBeTruthy();
29
+ expect(container.querySelector('#file-upload')).toBeTruthy();
30
+ });
31
+ it('should render input label', function () {
32
+ renderFileUpload();
33
+ expect(_react2.screen.getByRole('button', {
34
+ name: 'label'
35
+ })).toBeInTheDocument();
36
+ });
37
+ it('should extract and return files when user finishes selecting files', function () {
38
+ var onFilesSelected = (0, _sinon.spy)();
39
+ var _renderFileUpload2 = renderFileUpload({
40
+ onFilesSelected: onFilesSelected
41
+ }),
42
+ container = _renderFileUpload2.container;
43
+ var input = container.querySelector('input#file-upload');
44
+ _react2.fireEvent.change(input);
45
+ expect(onFilesSelected.calledOnce).toBe(true);
46
+ });
47
+ it('should remove file from files when delete button is clicked', function () {
48
+ var onFileDeleted = (0, _sinon.spy)();
49
+ // Do click on span inside button with event listener instead of actual button to catch nested clicks.
50
+ var _renderFileUpload3 = renderFileUpload({
51
+ onFileDeleted: onFileDeleted,
52
+ files: {
53
+ fileToDelete: {
54
+ name: 'fileToDelete'
55
+ }
56
+ }
57
+ }),
58
+ container = _renderFileUpload3.container;
59
+ var deleteButton = container.querySelector('.ffe-file-upload__file-item-delete-button-text');
60
+ _react2.fireEvent.click(deleteButton);
61
+ expect(onFileDeleted.calledWith({
62
+ name: 'fileToDelete'
63
+ })).toBe(true);
64
+ });
65
+ });
@@ -8,7 +8,7 @@ var getFileContent = exports.getFileContent = function getFileContent(file) {
8
8
  return new Promise(function (resolve, reject) {
9
9
  var reader = new window.FileReader();
10
10
  reader.onload = function (event) {
11
- return resolve(event.target.result);
11
+ return resolve(event.target ? event.target.result : null);
12
12
  };
13
13
  reader.onerror = function (error) {
14
14
  return reject(error);
package/lib/index.js CHANGED
@@ -3,14 +3,23 @@
3
3
  Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
- exports.default = void 0;
6
+ Object.defineProperty(exports, "FileUpload", {
7
+ enumerable: true,
8
+ get: function get() {
9
+ return _FileUpload.FileUpload;
10
+ }
11
+ });
12
+ Object.defineProperty(exports, "FileUploadProps", {
13
+ enumerable: true,
14
+ get: function get() {
15
+ return _FileUpload.FileUploadProps;
16
+ }
17
+ });
7
18
  Object.defineProperty(exports, "getFileContent", {
8
19
  enumerable: true,
9
20
  get: function get() {
10
- return _fileContent.getFileContent;
21
+ return _getFileContent.getFileContent;
11
22
  }
12
23
  });
13
- var _FileUpload = _interopRequireDefault(require("./FileUpload"));
14
- var _fileContent = require("./file-content");
15
- function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
16
- var _default = exports.default = _FileUpload.default;
24
+ var _FileUpload = require("./FileUpload");
25
+ var _getFileContent = require("./getFileContent");
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sb1/ffe-file-upload-react",
3
- "version": "10.0.52",
3
+ "version": "11.0.0",
4
4
  "description": "Upload file button with validation and list of uploaded files.",
5
5
  "keywords": [
6
6
  "ffe"
@@ -23,22 +23,24 @@
23
23
  "scripts": {
24
24
  "build": "ffe-buildtool babel",
25
25
  "watch": "ffe-buildtool babel-watch",
26
- "lint": "eslint src",
27
- "lint:fix": "eslint src --fix",
26
+ "lint": "eslint src --ext ts,tsx",
27
+ "lint:fix": "eslint src --fix --ext ts,tsx",
28
28
  "test": "ffe-buildtool jest",
29
29
  "test:watch": "ffe-buildtool jest --watch"
30
30
  },
31
31
  "dependencies": {
32
- "@sb1/ffe-buttons-react": "^22.0.4",
32
+ "@sb1/ffe-buttons-react": "^22.0.5",
33
33
  "@sb1/ffe-file-upload": "^10.0.39",
34
34
  "@sb1/ffe-form": "^29.0.13",
35
- "@sb1/ffe-icons-react": "^10.0.0",
35
+ "@sb1/ffe-icons-react": "^10.0.1",
36
36
  "classnames": "^2.3.1"
37
37
  },
38
38
  "devDependencies": {
39
39
  "@sb1/ffe-buildtool": "^0.6.1",
40
+ "@types/sinon": "^17.0.3",
40
41
  "react": "^16.9.0",
41
- "react-dom": "^16.9.0"
42
+ "react-dom": "^16.9.0",
43
+ "sinon": "^7.2.3"
42
44
  },
43
45
  "peerDependencies": {
44
46
  "react": ">=16.9.0"
@@ -46,8 +48,5 @@
46
48
  "publishConfig": {
47
49
  "access": "public"
48
50
  },
49
- "depencencies": {
50
- "prop-types": "^15.6.0"
51
- },
52
- "gitHead": "48bd1f6225acb09a6cf5f3c3e546b0abf9f59ef1"
51
+ "gitHead": "279a4e7d3afe4b4679448a28d1cdd8557740fdd5"
53
52
  }
package/es/index.d.js DELETED
@@ -1 +0,0 @@
1
- import * as React from 'react';
package/lib/index.d.js DELETED
@@ -1,6 +0,0 @@
1
- "use strict";
2
-
3
- function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); }
4
- var React = _interopRequireWildcard(require("react"));
5
- function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function _getRequireWildcardCache(e) { return e ? t : r; })(e); }
6
- function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != _typeof(e) && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && {}.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; }
package/types/index.d.ts DELETED
@@ -1,32 +0,0 @@
1
- import * as React from 'react';
2
-
3
- export interface FileItem<T> {
4
- name: string;
5
- document?: T;
6
- error?: string;
7
- }
8
-
9
- export interface FileUploadProps<T> {
10
- id: string;
11
- label: string;
12
- files: Record<string, FileItem<T>>;
13
- onFilesSelected(fileList: FileList): void;
14
- onFilesDropped(fileList: FileList): void;
15
- onFileDeleted(file: FileItem<T>): void;
16
- multiple?: boolean;
17
- title: string;
18
- infoText: string;
19
- infoSubText?: string;
20
- cancelText?: string;
21
- deleteText?: string;
22
- uploadTitle: string;
23
- uploadMicroText: string;
24
- uploadSubText: string;
25
- accept?: string;
26
- }
27
- declare class FileUpload<T> extends React.Component<FileUploadProps<T>, any> {}
28
-
29
- declare function getFileContent(file: File): Promise<string>;
30
-
31
- export default FileUpload;
32
- export { getFileContent };