@pingux/astro 2.44.0 → 2.44.1-alpha.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.
@@ -15,11 +15,11 @@ _Object$defineProperty(exports, "__esModule", {
15
15
  value: true
16
16
  });
17
17
  exports["default"] = void 0;
18
+ var _concat = _interopRequireDefault(require("@babel/runtime-corejs3/core-js-stable/instance/concat"));
18
19
  var _from = _interopRequireDefault(require("@babel/runtime-corejs3/core-js-stable/array/from"));
19
20
  var _slice = _interopRequireDefault(require("@babel/runtime-corejs3/core-js-stable/instance/slice"));
20
21
  var _map = _interopRequireDefault(require("@babel/runtime-corejs3/core-js-stable/instance/map"));
21
22
  var _url = _interopRequireDefault(require("@babel/runtime-corejs3/core-js-stable/url"));
22
- var _concat = _interopRequireDefault(require("@babel/runtime-corejs3/core-js-stable/instance/concat"));
23
23
  var _filter = _interopRequireDefault(require("@babel/runtime-corejs3/core-js-stable/instance/filter"));
24
24
  var _extends2 = _interopRequireDefault(require("@babel/runtime-corejs3/helpers/extends"));
25
25
  var _defineProperty2 = _interopRequireDefault(require("@babel/runtime-corejs3/helpers/defineProperty"));
@@ -28,6 +28,7 @@ var _objectWithoutProperties2 = _interopRequireDefault(require("@babel/runtime-c
28
28
  var _react = _interopRequireWildcard(require("react"));
29
29
  var _reactAria = require("react-aria");
30
30
  var _reactDropzone = require("react-dropzone");
31
+ var _pluralize = _interopRequireDefault(require("pluralize"));
31
32
  var _propTypes = _interopRequireDefault(require("prop-types"));
32
33
  var _uuid = require("uuid");
33
34
  var _ = require("../..");
@@ -44,7 +45,11 @@ var _excluded = ["defaultButtonText", "defaultFileList", "fileList", "helperText
44
45
  function _getRequireWildcardCache(nodeInterop) { if (typeof _WeakMap !== "function") return null; var cacheBabelInterop = new _WeakMap(); var cacheNodeInterop = new _WeakMap(); return (_getRequireWildcardCache = function _getRequireWildcardCache(nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }
45
46
  function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || _typeof(obj) !== "object" && typeof obj !== "function") { return { "default": obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = _Object$defineProperty && _Object$getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? _Object$getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { _Object$defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj["default"] = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
46
47
  function ownKeys(object, enumerableOnly) { var keys = _Object$keys(object); if (_Object$getOwnPropertySymbols) { var symbols = _Object$getOwnPropertySymbols(object); enumerableOnly && (symbols = _filterInstanceProperty2(symbols).call(symbols, function (sym) { return _Object$getOwnPropertyDescriptor(object, sym).enumerable; })), keys.push.apply(keys, symbols); } return keys; }
47
- function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var _context2, _context3; var source = null != arguments[i] ? arguments[i] : {}; i % 2 ? _forEachInstanceProperty(_context2 = ownKeys(Object(source), !0)).call(_context2, function (key) { (0, _defineProperty2["default"])(target, key, source[key]); }) : _Object$getOwnPropertyDescriptors ? _Object$defineProperties(target, _Object$getOwnPropertyDescriptors(source)) : _forEachInstanceProperty(_context3 = ownKeys(Object(source))).call(_context3, function (key) { _Object$defineProperty(target, key, _Object$getOwnPropertyDescriptor(source, key)); }); } return target; }
48
+ function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var _context3, _context4; var source = null != arguments[i] ? arguments[i] : {}; i % 2 ? _forEachInstanceProperty(_context3 = ownKeys(Object(source), !0)).call(_context3, function (key) { (0, _defineProperty2["default"])(target, key, source[key]); }) : _Object$getOwnPropertyDescriptors ? _Object$defineProperties(target, _Object$getOwnPropertyDescriptors(source)) : _forEachInstanceProperty(_context4 = ownKeys(Object(source))).call(_context4, function (key) { _Object$defineProperty(target, key, _Object$getOwnPropertyDescriptor(source, key)); }); } return target; }
49
+ var FILE_CHANGE_STATUS = {
50
+ ADDED: 'added',
51
+ DELETED: 'deleted'
52
+ };
48
53
  var FileInputField = /*#__PURE__*/(0, _react.forwardRef)(function (_ref, ref) {
49
54
  var defaultButtonText = _ref.defaultButtonText,
50
55
  defaultFileList = _ref.defaultFileList,
@@ -62,6 +67,14 @@ var FileInputField = /*#__PURE__*/(0, _react.forwardRef)(function (_ref, ref) {
62
67
  _useState2 = (0, _slicedToArray2["default"])(_useState, 2),
63
68
  uploadedFiles = _useState2[0],
64
69
  setUploadedFiles = _useState2[1];
70
+ var _useState3 = (0, _react.useState)(null),
71
+ _useState4 = (0, _slicedToArray2["default"])(_useState3, 2),
72
+ fileChangeStatus = _useState4[0],
73
+ setFileChangeStatus = _useState4[1];
74
+ var _useState5 = (0, _react.useState)(''),
75
+ _useState6 = (0, _slicedToArray2["default"])(_useState5, 2),
76
+ fileChangeMessage = _useState6[0],
77
+ setFileChangeMessage = _useState6[1];
65
78
  var inputRef = (0, _react.useRef)();
66
79
  /* istanbul ignore next */
67
80
  (0, _react.useImperativeHandle)(ref, function () {
@@ -85,7 +98,22 @@ var FileInputField = /*#__PURE__*/(0, _react.forwardRef)(function (_ref, ref) {
85
98
  inputRef.current.value = null;
86
99
  inputRef.current.click();
87
100
  }, [inputRef]);
88
- var handleFileUpload = (0, _react.useCallback)(function (event, newFiles) {
101
+ (0, _react.useEffect)(function () {
102
+ // TODO: The function works fine in Google Chrome, but sometimes voiceover skips the
103
+ // update/delete file status update on Safari
104
+
105
+ if (status === _statuses["default"].ERROR) {
106
+ setFileChangeMessage(helperText);
107
+ } else if (fileChangeStatus) {
108
+ var _context;
109
+ setFileChangeMessage((0, _concat["default"])(_context = "".concat((0, _pluralize["default"])('file', fileChangeStatus.fileCount, true), " ")).call(_context, fileChangeStatus.status, " successfully"));
110
+ }
111
+ setFileChangeStatus(null);
112
+ }, [fileChangeStatus, helperText, status]);
113
+ var handleFileUpload = function handleFileUpload(event, newFiles) {
114
+ if (status === _statuses["default"].ERROR) {
115
+ setFileChangeMessage('');
116
+ }
89
117
  if (onFileSelect) {
90
118
  onFileSelect(event, newFiles);
91
119
  }
@@ -93,7 +121,7 @@ var FileInputField = /*#__PURE__*/(0, _react.forwardRef)(function (_ref, ref) {
93
121
  if (!isMultiple) {
94
122
  arrayWithNewFiles = (0, _slice["default"])(arrayWithNewFiles).call(arrayWithNewFiles, 0, 1);
95
123
  }
96
- var newFilesWithIdAndLink = (0, _map["default"])(arrayWithNewFiles).call(arrayWithNewFiles, function (newFile) {
124
+ var filesWithIdAndLink = (0, _map["default"])(arrayWithNewFiles).call(arrayWithNewFiles, function (newFile) {
97
125
  return {
98
126
  fileObj: newFile,
99
127
  name: newFile.name,
@@ -104,16 +132,20 @@ var FileInputField = /*#__PURE__*/(0, _react.forwardRef)(function (_ref, ref) {
104
132
  });
105
133
  if (isMultiple) {
106
134
  setUploadedFiles(function (prevFiles) {
107
- var _context;
108
- return (0, _concat["default"])(_context = []).call(_context, prevFiles, newFilesWithIdAndLink);
135
+ var _context2;
136
+ return (0, _concat["default"])(_context2 = []).call(_context2, prevFiles, filesWithIdAndLink);
109
137
  });
110
138
  } else {
111
- setUploadedFiles(newFilesWithIdAndLink);
139
+ setUploadedFiles(filesWithIdAndLink);
112
140
  }
113
- }, [isMultiple, onFileSelect]);
114
- var onDrop = (0, _react.useCallback)(function (acceptedFiles, fileRejections, event) {
141
+ setFileChangeStatus({
142
+ fileCount: filesWithIdAndLink.length,
143
+ status: FILE_CHANGE_STATUS.ADDED
144
+ });
145
+ };
146
+ var onDrop = function onDrop(acceptedFiles, fileRejections, event) {
115
147
  handleFileUpload(event, acceptedFiles);
116
- }, [handleFileUpload]);
148
+ };
117
149
  var _useDropzone = (0, _reactDropzone.useDropzone)({
118
150
  onDrop: onDrop,
119
151
  noKeyboard: true,
@@ -122,26 +154,31 @@ var FileInputField = /*#__PURE__*/(0, _react.forwardRef)(function (_ref, ref) {
122
154
  getRootProps = _useDropzone.getRootProps,
123
155
  getInputProps = _useDropzone.getInputProps,
124
156
  isDragActive = _useDropzone.isDragActive;
125
- var handleOnChange = (0, _react.useCallback)(function (event) {
157
+ var handleOnChange = function handleOnChange(event) {
126
158
  handleFileUpload(event, event.target.files);
127
- }, [handleFileUpload]);
128
- var handleFileDelete = (0, _react.useCallback)(function (e, fileId) {
129
- if (onRemove) {
130
- onRemove(e, fileId);
131
- }
132
- setUploadedFiles(function (prevFiles) {
133
- return (0, _filter["default"])(prevFiles).call(prevFiles, function (_ref2) {
134
- var id = _ref2.id;
135
- return id !== fileId;
136
- });
137
- });
138
- }, [onRemove]);
159
+ };
139
160
  var filesListNode = (0, _react.useMemo)(function () {
161
+ var handleFileDelete = function handleFileDelete(e, fileId) {
162
+ setFileChangeMessage('');
163
+ if (onRemove) {
164
+ onRemove(e, fileId);
165
+ }
166
+ setUploadedFiles(function (prevFiles) {
167
+ return (0, _filter["default"])(prevFiles).call(prevFiles, function (_ref2) {
168
+ var id = _ref2.id;
169
+ return id !== fileId;
170
+ });
171
+ });
172
+ setFileChangeStatus({
173
+ fileCount: 1,
174
+ status: FILE_CHANGE_STATUS.DELETED
175
+ });
176
+ };
140
177
  var filesToRender = uploadedFilesImperative || uploadedFiles;
141
178
  if (!(filesToRender !== null && filesToRender !== void 0 && filesToRender.length)) {
142
179
  return null;
143
180
  }
144
- return (0, _map["default"])(filesToRender).call(filesToRender, function (fileProps) {
181
+ return (0, _react2.jsx)(_react["default"].Fragment, null, (0, _map["default"])(filesToRender).call(filesToRender, function (fileProps) {
145
182
  return (0, _react2.jsx)(_FileItem["default"], (0, _extends2["default"])({
146
183
  handleFileDelete: handleFileDelete,
147
184
  isDisabled: isDisabled || isLoading,
@@ -149,8 +186,8 @@ var FileInputField = /*#__PURE__*/(0, _react.forwardRef)(function (_ref, ref) {
149
186
  textProps: textProps,
150
187
  helperTextId: helperTextId
151
188
  }, fileProps));
152
- });
153
- }, [uploadedFilesImperative, uploadedFiles, handleFileDelete, isDisabled, isLoading, textProps]);
189
+ }));
190
+ }, [helperTextId, isDisabled, isLoading, onRemove, textProps, uploadedFiles, uploadedFilesImperative]);
154
191
  var _useStatusClasses = (0, _useStatusClasses3["default"])('fileInputFieldWrapper', (0, _defineProperty2["default"])({
155
192
  isDragActive: isDragActive,
156
193
  isLoading: isLoading
@@ -191,10 +228,16 @@ var FileInputField = /*#__PURE__*/(0, _react.forwardRef)(function (_ref, ref) {
191
228
  position: 'absolute'
192
229
  },
193
230
  "data-testid": "file-input-field__loader"
194
- })), helperText && (0, _react2.jsx)(_.FieldHelperText, {
231
+ })), helperText && (0, _react2.jsx)(_.Box, {
232
+ "aria-label": helperText
233
+ }, (0, _react2.jsx)(_.FieldHelperText, {
195
234
  status: status,
196
235
  id: helperTextId
197
- }, helperText));
236
+ }, helperText)), fileChangeMessage && (0, _react2.jsx)(_.Box, {
237
+ "aria-relevant": "all",
238
+ "aria-live": "assertive",
239
+ role: "status"
240
+ }, (0, _react2.jsx)(_reactAria.VisuallyHidden, null, (0, _react2.jsx)("h1", null, fileChangeMessage))));
198
241
  });
199
242
  FileInputField.displayName = 'FileInputField';
200
243
  FileInputField.propTypes = _objectSpread(_objectSpread(_objectSpread({
@@ -190,7 +190,8 @@ test('passing helper text should display it and correct aria attributes on input
190
190
  status: _statuses["default"].ERROR,
191
191
  defaultFileList: [testFileObject]
192
192
  });
193
- var helper = _react2.screen.getByText(testHelperText);
193
+ var helper = _react2.screen.getByRole('alert');
194
+ expect(helper).toHaveTextContent(testHelperText);
194
195
  expect(helper).toBeInTheDocument();
195
196
  expect(helper).toHaveClass("is-".concat(_statuses["default"].ERROR));
196
197
  var helperTextID = helper.getAttribute('id');
@@ -34,12 +34,12 @@ function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { va
34
34
  var FileItem = function FileItem(props) {
35
35
  var downloadLink = props.downloadLink,
36
36
  handleFileDelete = props.handleFileDelete,
37
+ helperTextId = props.helperTextId,
37
38
  id = props.id,
38
39
  isDisabled = props.isDisabled,
39
40
  name = props.name,
40
41
  status = props.status,
41
- textProps = props.textProps,
42
- helperTextId = props.helperTextId;
42
+ textProps = props.textProps;
43
43
  var handleDeleteButtonPress = (0, _react.useCallback)(function (e) {
44
44
  return handleFileDelete(e, id);
45
45
  }, [id, handleFileDelete]);
@@ -87,11 +87,12 @@ var FileItem = function FileItem(props) {
87
87
  "aria-label": name,
88
88
  "data-testid": "file-uploaded__download-file-button",
89
89
  onPress: handleDownloadPress,
90
- "aria-describedby": helperTextId
90
+ "aria-describedby": helperTextId,
91
+ "aria-live": "polite"
91
92
  }, (0, _react2.jsx)(_index.Text, (0, _extends2["default"])({
92
93
  color: "active"
93
94
  }, textProps), name)), (0, _react2.jsx)(_index.IconButton, {
94
- "aria-label": "Delete ".concat(name, " file icon"),
95
+ "aria-label": "Delete ".concat(name),
95
96
  "data-testid": "file-uploaded__delete-file-button",
96
97
  isDisabled: isDisabled,
97
98
  onPress: handleDeleteButtonPress,
@@ -110,7 +111,7 @@ var FileItem = function FileItem(props) {
110
111
  }, visuallyHiddenProps, {
111
112
  download: true,
112
113
  ref: downloadRef,
113
- "aria-label": "download",
114
+ "aria-label": "download ".concat(name),
114
115
  "data-testid": "file-uploaded__download-link",
115
116
  tabIndex: -1
116
117
  })));
@@ -123,6 +124,5 @@ FileItem.propTypes = _objectSpread({
123
124
  id: _propTypes["default"].string,
124
125
  isDisabled: _propTypes["default"].bool,
125
126
  name: _propTypes["default"].string,
126
- helperTextId: _propTypes["default"].string,
127
127
  textProps: _propTypes["default"].shape({})
128
128
  }, _statusProp.statusPropTypes);
@@ -10,17 +10,18 @@ import _defineProperty from "@babel/runtime-corejs3/helpers/esm/defineProperty";
10
10
  import _slicedToArray from "@babel/runtime-corejs3/helpers/esm/slicedToArray";
11
11
  import _objectWithoutProperties from "@babel/runtime-corejs3/helpers/esm/objectWithoutProperties";
12
12
  var _excluded = ["defaultButtonText", "defaultFileList", "fileList", "helperText", "isDisabled", "isLoading", "isMultiple", "onFileSelect", "onRemove", "status", "textProps"];
13
+ import _concatInstanceProperty from "@babel/runtime-corejs3/core-js-stable/instance/concat";
13
14
  import _Array$from from "@babel/runtime-corejs3/core-js-stable/array/from";
14
15
  import _sliceInstanceProperty from "@babel/runtime-corejs3/core-js-stable/instance/slice";
15
16
  import _mapInstanceProperty from "@babel/runtime-corejs3/core-js-stable/instance/map";
16
17
  import _URL from "@babel/runtime-corejs3/core-js-stable/url";
17
- import _concatInstanceProperty from "@babel/runtime-corejs3/core-js-stable/instance/concat";
18
18
  import _filterInstanceProperty from "@babel/runtime-corejs3/core-js-stable/instance/filter";
19
19
  function ownKeys(object, enumerableOnly) { var keys = _Object$keys(object); if (_Object$getOwnPropertySymbols) { var symbols = _Object$getOwnPropertySymbols(object); enumerableOnly && (symbols = _filterInstanceProperty(symbols).call(symbols, function (sym) { return _Object$getOwnPropertyDescriptor(object, sym).enumerable; })), keys.push.apply(keys, symbols); } return keys; }
20
- function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var _context2, _context3; var source = null != arguments[i] ? arguments[i] : {}; i % 2 ? _forEachInstanceProperty(_context2 = ownKeys(Object(source), !0)).call(_context2, function (key) { _defineProperty(target, key, source[key]); }) : _Object$getOwnPropertyDescriptors ? _Object$defineProperties(target, _Object$getOwnPropertyDescriptors(source)) : _forEachInstanceProperty(_context3 = ownKeys(Object(source))).call(_context3, function (key) { _Object$defineProperty(target, key, _Object$getOwnPropertyDescriptor(source, key)); }); } return target; }
21
- import React, { forwardRef, useCallback, useImperativeHandle, useMemo, useRef, useState } from 'react';
22
- import { mergeProps, useVisuallyHidden } from 'react-aria';
20
+ function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var _context3, _context4; var source = null != arguments[i] ? arguments[i] : {}; i % 2 ? _forEachInstanceProperty(_context3 = ownKeys(Object(source), !0)).call(_context3, function (key) { _defineProperty(target, key, source[key]); }) : _Object$getOwnPropertyDescriptors ? _Object$defineProperties(target, _Object$getOwnPropertyDescriptors(source)) : _forEachInstanceProperty(_context4 = ownKeys(Object(source))).call(_context4, function (key) { _Object$defineProperty(target, key, _Object$getOwnPropertyDescriptor(source, key)); }); } return target; }
21
+ import React, { forwardRef, useCallback, useEffect, useImperativeHandle, useMemo, useRef, useState } from 'react';
22
+ import { mergeProps, useVisuallyHidden, VisuallyHidden } from 'react-aria';
23
23
  import { useDropzone } from 'react-dropzone';
24
+ import pluralize from 'pluralize';
24
25
  import PropTypes from 'prop-types';
25
26
  import { v4 as uuidv4 } from 'uuid';
26
27
  import { Box, FieldHelperText, Input, Label, Loader } from '../..';
@@ -33,6 +34,10 @@ import { statusDefaultProp, statusPropTypes } from '../../utils/docUtils/statusP
33
34
  import FileItem from './FileItem';
34
35
  import FileSelect from './FileSelect';
35
36
  import { jsx as ___EmotionJSX } from "@emotion/react";
37
+ var FILE_CHANGE_STATUS = {
38
+ ADDED: 'added',
39
+ DELETED: 'deleted'
40
+ };
36
41
  var FileInputField = /*#__PURE__*/forwardRef(function (_ref, ref) {
37
42
  var defaultButtonText = _ref.defaultButtonText,
38
43
  defaultFileList = _ref.defaultFileList,
@@ -50,6 +55,14 @@ var FileInputField = /*#__PURE__*/forwardRef(function (_ref, ref) {
50
55
  _useState2 = _slicedToArray(_useState, 2),
51
56
  uploadedFiles = _useState2[0],
52
57
  setUploadedFiles = _useState2[1];
58
+ var _useState3 = useState(null),
59
+ _useState4 = _slicedToArray(_useState3, 2),
60
+ fileChangeStatus = _useState4[0],
61
+ setFileChangeStatus = _useState4[1];
62
+ var _useState5 = useState(''),
63
+ _useState6 = _slicedToArray(_useState5, 2),
64
+ fileChangeMessage = _useState6[0],
65
+ setFileChangeMessage = _useState6[1];
53
66
  var inputRef = useRef();
54
67
  /* istanbul ignore next */
55
68
  useImperativeHandle(ref, function () {
@@ -73,7 +86,22 @@ var FileInputField = /*#__PURE__*/forwardRef(function (_ref, ref) {
73
86
  inputRef.current.value = null;
74
87
  inputRef.current.click();
75
88
  }, [inputRef]);
76
- var handleFileUpload = useCallback(function (event, newFiles) {
89
+ useEffect(function () {
90
+ // TODO: The function works fine in Google Chrome, but sometimes voiceover skips the
91
+ // update/delete file status update on Safari
92
+
93
+ if (status === statuses.ERROR) {
94
+ setFileChangeMessage(helperText);
95
+ } else if (fileChangeStatus) {
96
+ var _context;
97
+ setFileChangeMessage(_concatInstanceProperty(_context = "".concat(pluralize('file', fileChangeStatus.fileCount, true), " ")).call(_context, fileChangeStatus.status, " successfully"));
98
+ }
99
+ setFileChangeStatus(null);
100
+ }, [fileChangeStatus, helperText, status]);
101
+ var handleFileUpload = function handleFileUpload(event, newFiles) {
102
+ if (status === statuses.ERROR) {
103
+ setFileChangeMessage('');
104
+ }
77
105
  if (onFileSelect) {
78
106
  onFileSelect(event, newFiles);
79
107
  }
@@ -81,7 +109,7 @@ var FileInputField = /*#__PURE__*/forwardRef(function (_ref, ref) {
81
109
  if (!isMultiple) {
82
110
  arrayWithNewFiles = _sliceInstanceProperty(arrayWithNewFiles).call(arrayWithNewFiles, 0, 1);
83
111
  }
84
- var newFilesWithIdAndLink = _mapInstanceProperty(arrayWithNewFiles).call(arrayWithNewFiles, function (newFile) {
112
+ var filesWithIdAndLink = _mapInstanceProperty(arrayWithNewFiles).call(arrayWithNewFiles, function (newFile) {
85
113
  return {
86
114
  fileObj: newFile,
87
115
  name: newFile.name,
@@ -92,16 +120,20 @@ var FileInputField = /*#__PURE__*/forwardRef(function (_ref, ref) {
92
120
  });
93
121
  if (isMultiple) {
94
122
  setUploadedFiles(function (prevFiles) {
95
- var _context;
96
- return _concatInstanceProperty(_context = []).call(_context, prevFiles, newFilesWithIdAndLink);
123
+ var _context2;
124
+ return _concatInstanceProperty(_context2 = []).call(_context2, prevFiles, filesWithIdAndLink);
97
125
  });
98
126
  } else {
99
- setUploadedFiles(newFilesWithIdAndLink);
127
+ setUploadedFiles(filesWithIdAndLink);
100
128
  }
101
- }, [isMultiple, onFileSelect]);
102
- var onDrop = useCallback(function (acceptedFiles, fileRejections, event) {
129
+ setFileChangeStatus({
130
+ fileCount: filesWithIdAndLink.length,
131
+ status: FILE_CHANGE_STATUS.ADDED
132
+ });
133
+ };
134
+ var onDrop = function onDrop(acceptedFiles, fileRejections, event) {
103
135
  handleFileUpload(event, acceptedFiles);
104
- }, [handleFileUpload]);
136
+ };
105
137
  var _useDropzone = useDropzone({
106
138
  onDrop: onDrop,
107
139
  noKeyboard: true,
@@ -110,26 +142,31 @@ var FileInputField = /*#__PURE__*/forwardRef(function (_ref, ref) {
110
142
  getRootProps = _useDropzone.getRootProps,
111
143
  getInputProps = _useDropzone.getInputProps,
112
144
  isDragActive = _useDropzone.isDragActive;
113
- var handleOnChange = useCallback(function (event) {
145
+ var handleOnChange = function handleOnChange(event) {
114
146
  handleFileUpload(event, event.target.files);
115
- }, [handleFileUpload]);
116
- var handleFileDelete = useCallback(function (e, fileId) {
117
- if (onRemove) {
118
- onRemove(e, fileId);
119
- }
120
- setUploadedFiles(function (prevFiles) {
121
- return _filterInstanceProperty(prevFiles).call(prevFiles, function (_ref2) {
122
- var id = _ref2.id;
123
- return id !== fileId;
124
- });
125
- });
126
- }, [onRemove]);
147
+ };
127
148
  var filesListNode = useMemo(function () {
149
+ var handleFileDelete = function handleFileDelete(e, fileId) {
150
+ setFileChangeMessage('');
151
+ if (onRemove) {
152
+ onRemove(e, fileId);
153
+ }
154
+ setUploadedFiles(function (prevFiles) {
155
+ return _filterInstanceProperty(prevFiles).call(prevFiles, function (_ref2) {
156
+ var id = _ref2.id;
157
+ return id !== fileId;
158
+ });
159
+ });
160
+ setFileChangeStatus({
161
+ fileCount: 1,
162
+ status: FILE_CHANGE_STATUS.DELETED
163
+ });
164
+ };
128
165
  var filesToRender = uploadedFilesImperative || uploadedFiles;
129
166
  if (!(filesToRender !== null && filesToRender !== void 0 && filesToRender.length)) {
130
167
  return null;
131
168
  }
132
- return _mapInstanceProperty(filesToRender).call(filesToRender, function (fileProps) {
169
+ return ___EmotionJSX(React.Fragment, null, _mapInstanceProperty(filesToRender).call(filesToRender, function (fileProps) {
133
170
  return ___EmotionJSX(FileItem, _extends({
134
171
  handleFileDelete: handleFileDelete,
135
172
  isDisabled: isDisabled || isLoading,
@@ -137,8 +174,8 @@ var FileInputField = /*#__PURE__*/forwardRef(function (_ref, ref) {
137
174
  textProps: textProps,
138
175
  helperTextId: helperTextId
139
176
  }, fileProps));
140
- });
141
- }, [uploadedFilesImperative, uploadedFiles, handleFileDelete, isDisabled, isLoading, textProps]);
177
+ }));
178
+ }, [helperTextId, isDisabled, isLoading, onRemove, textProps, uploadedFiles, uploadedFilesImperative]);
142
179
  var _useStatusClasses = useStatusClasses('fileInputFieldWrapper', _defineProperty({
143
180
  isDragActive: isDragActive,
144
181
  isLoading: isLoading
@@ -179,10 +216,16 @@ var FileInputField = /*#__PURE__*/forwardRef(function (_ref, ref) {
179
216
  position: 'absolute'
180
217
  },
181
218
  "data-testid": "file-input-field__loader"
182
- })), helperText && ___EmotionJSX(FieldHelperText, {
219
+ })), helperText && ___EmotionJSX(Box, {
220
+ "aria-label": helperText
221
+ }, ___EmotionJSX(FieldHelperText, {
183
222
  status: status,
184
223
  id: helperTextId
185
- }, helperText));
224
+ }, helperText)), fileChangeMessage && ___EmotionJSX(Box, {
225
+ "aria-relevant": "all",
226
+ "aria-live": "assertive",
227
+ role: "status"
228
+ }, ___EmotionJSX(VisuallyHidden, null, ___EmotionJSX("h1", null, fileChangeMessage))));
186
229
  });
187
230
  FileInputField.displayName = 'FileInputField';
188
231
  FileInputField.propTypes = _objectSpread(_objectSpread(_objectSpread({
@@ -187,7 +187,8 @@ test('passing helper text should display it and correct aria attributes on input
187
187
  status: statuses.ERROR,
188
188
  defaultFileList: [testFileObject]
189
189
  });
190
- var helper = screen.getByText(testHelperText);
190
+ var helper = screen.getByRole('alert');
191
+ expect(helper).toHaveTextContent(testHelperText);
191
192
  expect(helper).toBeInTheDocument();
192
193
  expect(helper).toHaveClass("is-".concat(statuses.ERROR));
193
194
  var helperTextID = helper.getAttribute('id');
@@ -23,12 +23,12 @@ import { jsx as ___EmotionJSX } from "@emotion/react";
23
23
  var FileItem = function FileItem(props) {
24
24
  var downloadLink = props.downloadLink,
25
25
  handleFileDelete = props.handleFileDelete,
26
+ helperTextId = props.helperTextId,
26
27
  id = props.id,
27
28
  isDisabled = props.isDisabled,
28
29
  name = props.name,
29
30
  status = props.status,
30
- textProps = props.textProps,
31
- helperTextId = props.helperTextId;
31
+ textProps = props.textProps;
32
32
  var handleDeleteButtonPress = useCallback(function (e) {
33
33
  return handleFileDelete(e, id);
34
34
  }, [id, handleFileDelete]);
@@ -76,11 +76,12 @@ var FileItem = function FileItem(props) {
76
76
  "aria-label": name,
77
77
  "data-testid": "file-uploaded__download-file-button",
78
78
  onPress: handleDownloadPress,
79
- "aria-describedby": helperTextId
79
+ "aria-describedby": helperTextId,
80
+ "aria-live": "polite"
80
81
  }, ___EmotionJSX(Text, _extends({
81
82
  color: "active"
82
83
  }, textProps), name)), ___EmotionJSX(IconButton, {
83
- "aria-label": "Delete ".concat(name, " file icon"),
84
+ "aria-label": "Delete ".concat(name),
84
85
  "data-testid": "file-uploaded__delete-file-button",
85
86
  isDisabled: isDisabled,
86
87
  onPress: handleDeleteButtonPress,
@@ -99,7 +100,7 @@ var FileItem = function FileItem(props) {
99
100
  }, visuallyHiddenProps, {
100
101
  download: true,
101
102
  ref: downloadRef,
102
- "aria-label": "download",
103
+ "aria-label": "download ".concat(name),
103
104
  "data-testid": "file-uploaded__download-link",
104
105
  tabIndex: -1
105
106
  })));
@@ -111,6 +112,5 @@ FileItem.propTypes = _objectSpread({
111
112
  id: PropTypes.string,
112
113
  isDisabled: PropTypes.bool,
113
114
  name: PropTypes.string,
114
- helperTextId: PropTypes.string,
115
115
  textProps: PropTypes.shape({})
116
116
  }, statusPropTypes);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pingux/astro",
3
- "version": "2.44.0",
3
+ "version": "2.44.1-alpha.0",
4
4
  "description": "React component library for Ping Identity's design system",
5
5
  "repository": {
6
6
  "type": "git",
@@ -99,6 +99,7 @@
99
99
  "emotion-normalize": "^11.0.1",
100
100
  "lodash": "^4.17.21",
101
101
  "moment": "^2.29.4",
102
+ "pluralize": "^8.0.0",
102
103
  "prism-react-renderer": "1.2.1",
103
104
  "prismjs": "^1.27.0",
104
105
  "prop-types": "^15.7.2",