@pingux/astro 2.115.0 → 2.116.0-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.
- package/lib/cjs/components/AIComponents/PromptInput/PromptInput.js +3 -1
- package/lib/cjs/components/AIComponents/PromptInput/PromptInput.stories.d.ts +9 -0
- package/lib/cjs/components/AIComponents/PromptInput/PromptInput.stories.js +14 -1
- package/lib/cjs/components/AIComponents/PromptInput/PromptInput.test.js +9 -0
- package/lib/cjs/components/AIComponents/PromptInput/PromptInputReadMe.mdx +71 -0
- package/lib/cjs/components/FileInputField/FileInputField.js +17 -8
- package/lib/cjs/components/FileInputField/FileInputField.stories.js +35 -3
- package/lib/cjs/components/FileInputField/FileInputField.test.js +24 -2
- package/lib/cjs/components/FileInputField/FileItem.js +3 -3
- package/lib/cjs/types/promptInput.d.ts +1 -0
- package/lib/components/AIComponents/PromptInput/PromptInput.js +3 -1
- package/lib/components/AIComponents/PromptInput/PromptInput.stories.js +14 -1
- package/lib/components/AIComponents/PromptInput/PromptInput.test.js +9 -0
- package/lib/components/AIComponents/PromptInput/PromptInputReadMe.mdx +71 -0
- package/lib/components/FileInputField/FileInputField.js +17 -8
- package/lib/components/FileInputField/FileInputField.stories.js +32 -1
- package/lib/components/FileInputField/FileInputField.test.js +24 -2
- package/lib/components/FileInputField/FileItem.js +3 -3
- package/package.json +1 -1
@@ -41,6 +41,8 @@ var PromptInput = /*#__PURE__*/(0, _react.forwardRef)(function (props, ref) {
|
|
41
41
|
var attachmentProps = props.attachmentProps,
|
42
42
|
isFullScreen = props.isFullScreen,
|
43
43
|
isLoading = props.isLoading,
|
44
|
+
_props$isUploadButton = props.isUploadButtonHidden,
|
45
|
+
isUploadButtonHidden = _props$isUploadButton === void 0 ? false : _props$isUploadButton,
|
44
46
|
fileInputButtonProps = props.fileInputButtonProps,
|
45
47
|
valueProp = props.value,
|
46
48
|
defaultValueProp = props.defaultValue,
|
@@ -188,7 +190,7 @@ var PromptInput = /*#__PURE__*/(0, _react.forwardRef)(function (props, ref) {
|
|
188
190
|
}, fieldControlInputProps, {
|
189
191
|
onKeyUp: onKeyUp,
|
190
192
|
onKeyDown: onKeyDown
|
191
|
-
})), (0, _react2.jsx)(_index.Box, {
|
193
|
+
})), !isUploadButtonHidden && (0, _react2.jsx)(_index.Box, {
|
192
194
|
sx: {
|
193
195
|
mx: '.75rem',
|
194
196
|
mb: 'auto'
|
@@ -2,8 +2,17 @@ import React from 'react';
|
|
2
2
|
declare const _default: {
|
3
3
|
title: string;
|
4
4
|
component: React.ForwardRefExoticComponent<import("../../../types/promptInput").PromptInputProps & React.RefAttributes<HTMLInputElement>>;
|
5
|
+
parameters: {
|
6
|
+
docs: {
|
7
|
+
page: () => React.JSX.Element;
|
8
|
+
source: {
|
9
|
+
type: string;
|
10
|
+
};
|
11
|
+
};
|
12
|
+
};
|
5
13
|
argTypes: {
|
6
14
|
isLoading: any;
|
15
|
+
isUploadButtonHidden: any;
|
7
16
|
};
|
8
17
|
};
|
9
18
|
export default _default;
|
@@ -19,9 +19,11 @@ var _extends2 = _interopRequireDefault(require("@babel/runtime-corejs3/helpers/e
|
|
19
19
|
var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime-corejs3/helpers/slicedToArray"));
|
20
20
|
var _defineProperty2 = _interopRequireDefault(require("@babel/runtime-corejs3/helpers/defineProperty"));
|
21
21
|
var _react = _interopRequireWildcard(require("react"));
|
22
|
+
var _storybookDocsLayout = _interopRequireDefault(require("../../../../.storybook/storybookDocsLayout"));
|
22
23
|
var _ = require("../../..");
|
23
24
|
var _docArgTypes = require("../../../utils/docUtils/docArgTypes");
|
24
25
|
var _PromptInput = _interopRequireDefault(require("./PromptInput"));
|
26
|
+
var _PromptInputReadMe = _interopRequireDefault(require("./PromptInputReadMe.mdx"));
|
25
27
|
var _react2 = require("@emotion/react");
|
26
28
|
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); }
|
27
29
|
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; }
|
@@ -30,8 +32,19 @@ function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { va
|
|
30
32
|
var _default = {
|
31
33
|
title: 'Ai Components/Prompt Input',
|
32
34
|
component: _PromptInput["default"],
|
35
|
+
parameters: {
|
36
|
+
docs: {
|
37
|
+
page: function page() {
|
38
|
+
return (0, _react2.jsx)(_react["default"].Fragment, null, (0, _react2.jsx)(_PromptInputReadMe["default"], null), (0, _react2.jsx)(_storybookDocsLayout["default"], null));
|
39
|
+
},
|
40
|
+
source: {
|
41
|
+
type: 'code'
|
42
|
+
}
|
43
|
+
}
|
44
|
+
},
|
33
45
|
argTypes: {
|
34
|
-
isLoading: _objectSpread({}, _docArgTypes.booleanArg)
|
46
|
+
isLoading: _objectSpread({}, _docArgTypes.booleanArg),
|
47
|
+
isUploadButtonHidden: _objectSpread({}, _docArgTypes.booleanArg)
|
35
48
|
}
|
36
49
|
};
|
37
50
|
exports["default"] = _default;
|
@@ -134,6 +134,15 @@ test('onSubmit prop works correctly', /*#__PURE__*/(0, _asyncToGenerator2["defau
|
|
134
134
|
}
|
135
135
|
}, _callee2);
|
136
136
|
})));
|
137
|
+
test('', function () {
|
138
|
+
getComponent({
|
139
|
+
isUploadButtonHidden: true,
|
140
|
+
uploadButtonProps: {
|
141
|
+
'data-testid': buttonTestId
|
142
|
+
}
|
143
|
+
});
|
144
|
+
expect(_testWrapper.screen.queryByText(buttonTestId)).not.toBeInTheDocument();
|
145
|
+
});
|
137
146
|
test('onCancel prop works correctly', /*#__PURE__*/(0, _asyncToGenerator2["default"])( /*#__PURE__*/_regeneratorRuntime().mark(function _callee3() {
|
138
147
|
var control;
|
139
148
|
return _regeneratorRuntime().wrap(function _callee3$(_context3) {
|
@@ -0,0 +1,71 @@
|
|
1
|
+
import { Meta } from '@storybook/addon-docs';
|
2
|
+
|
3
|
+
<Meta title="Components/PromptInput" />
|
4
|
+
|
5
|
+
# PromptInput
|
6
|
+
|
7
|
+
The `PromptInput` component is used to capture user input in a conversational UI. It supports text input, file attachments, and customizable actions like submission or cancellation.
|
8
|
+
|
9
|
+
### Recommended Use
|
10
|
+
|
11
|
+
- Use the `PromptInput` component to collect user input in chat-like interfaces.
|
12
|
+
- Attach files or documents to the input using the file attachment feature.
|
13
|
+
|
14
|
+
### Features
|
15
|
+
|
16
|
+
- **Text Input**: Allows users to type text with dynamic height adjustment based on content.
|
17
|
+
- **File Attachments**: Supports adding and removing file attachments.
|
18
|
+
- **Customizable Actions**: Includes `onSubmit`, `onCancel`, `onKeyDown`, and `onKeyUp` handlers for custom behavior.
|
19
|
+
|
20
|
+
### Props
|
21
|
+
|
22
|
+
| Prop | Type | Description |
|
23
|
+
| --------------------- | -------------------- | --------------------------------------------------------------------------- |
|
24
|
+
| `value` | `string` | The controlled value of the input. |
|
25
|
+
| `defaultValue` | `string` | The default value of the input. |
|
26
|
+
| `onSubmit` | `function` | Callback triggered when the input is submitted. |
|
27
|
+
| `onCancel` | `function` | Callback triggered when the input is canceled. |
|
28
|
+
| `onKeyDown` | `function` | Callback triggered on key down events. |
|
29
|
+
| `onKeyUp` | `function` | Callback triggered on key up events. |
|
30
|
+
| `onFileChange` | `function` | Callback triggered when files are added or removed. |
|
31
|
+
| `attachmentProps` | `object` | Props passed to the `Attachment` component for file attachments. |
|
32
|
+
| `fileInputButtonProps`| `object` | Props passed to the file input button. |
|
33
|
+
| `uploadButtonProps` | `object` | Props passed to the upload button. |
|
34
|
+
| `isLoading` | `boolean` | Indicates whether the input is in a loading state. |
|
35
|
+
|
36
|
+
### Accessibility
|
37
|
+
|
38
|
+
This component adheres to accessibility guidelines to ensure a better user experience for all users.
|
39
|
+
|
40
|
+
#### Keyboard Navigation
|
41
|
+
|
42
|
+
| Keys | Function |
|
43
|
+
| ------------ | ----------------------------------------------------------------------- |
|
44
|
+
| Tab | Focuses on the next focusable element within the input. |
|
45
|
+
| Shift + Tab | Moves focus to the previous focusable element. |
|
46
|
+
| Enter | Submits the input when `onSubmit` is defined. |
|
47
|
+
| Shift + Enter| Adds a new line to the input. |
|
48
|
+
| Escape | Cancels the input when `onCancel` is defined. |
|
49
|
+
|
50
|
+
#### Screen Readers
|
51
|
+
|
52
|
+
- **`aria-label`**: Describes the purpose of the input field.
|
53
|
+
- **`aria-disabled`**: Indicates when the input is disabled.
|
54
|
+
- **`aria-live`**: Announces changes to the input dynamically.
|
55
|
+
|
56
|
+
### Example Usage
|
57
|
+
|
58
|
+
```jsx
|
59
|
+
<PromptInput
|
60
|
+
value=""
|
61
|
+
onSubmit={(e, value) => console.log('Submitted:', value)}
|
62
|
+
onCancel={(e) => console.log('Canceled')}
|
63
|
+
onFileChange={(files) => console.log('Files:', files)}
|
64
|
+
attachmentProps={{
|
65
|
+
icon: GlobeIcon,
|
66
|
+
}}
|
67
|
+
uploadButtonProps={{
|
68
|
+
'aria-label': 'Upload',
|
69
|
+
}}
|
70
|
+
isLoading={false}
|
71
|
+
/>
|
@@ -19,8 +19,9 @@ var _concat = _interopRequireDefault(require("@babel/runtime-corejs3/core-js-sta
|
|
19
19
|
var _from = _interopRequireDefault(require("@babel/runtime-corejs3/core-js-stable/array/from"));
|
20
20
|
var _slice = _interopRequireDefault(require("@babel/runtime-corejs3/core-js-stable/instance/slice"));
|
21
21
|
var _map = _interopRequireDefault(require("@babel/runtime-corejs3/core-js-stable/instance/map"));
|
22
|
-
var _url = _interopRequireDefault(require("@babel/runtime-corejs3/core-js-stable/url"));
|
23
22
|
var _filter = _interopRequireDefault(require("@babel/runtime-corejs3/core-js-stable/instance/filter"));
|
23
|
+
var _some = _interopRequireDefault(require("@babel/runtime-corejs3/core-js-stable/instance/some"));
|
24
|
+
var _url = _interopRequireDefault(require("@babel/runtime-corejs3/core-js-stable/url"));
|
24
25
|
var _extends2 = _interopRequireDefault(require("@babel/runtime-corejs3/helpers/extends"));
|
25
26
|
var _defineProperty2 = _interopRequireDefault(require("@babel/runtime-corejs3/helpers/defineProperty"));
|
26
27
|
var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime-corejs3/helpers/slicedToArray"));
|
@@ -43,11 +44,11 @@ var _FileItem = _interopRequireDefault(require("./FileItem"));
|
|
43
44
|
var _FileSelect = _interopRequireDefault(require("./FileSelect"));
|
44
45
|
var _FileSelectIcon = _interopRequireDefault(require("./FileSelectIcon"));
|
45
46
|
var _react2 = require("@emotion/react");
|
46
|
-
var _excluded = ["buttonProps", "defaultButtonText", "defaultFileList", "fileList", "helperText", "iconContainerProps", "iconProps", "isDisabled", "isIconButton", "isLoading", "isMultiple", "label", "onFileSelect", "onRemove", "status", "textProps"];
|
47
|
+
var _excluded = ["buttonProps", "defaultButtonText", "defaultFileList", "fileList", "helperText", "iconContainerProps", "iconProps", "isDisabled", "isIconButton", "isLoading", "isMultiple", "label", "onFileSelect", "onRemove", "status", "textProps", "fileTypes"];
|
47
48
|
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); }
|
48
49
|
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; }
|
49
50
|
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; }
|
50
|
-
function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var
|
51
|
+
function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var _context4, _context5; var source = null != arguments[i] ? arguments[i] : {}; i % 2 ? _forEachInstanceProperty(_context4 = ownKeys(Object(source), !0)).call(_context4, function (key) { (0, _defineProperty2["default"])(target, key, source[key]); }) : _Object$getOwnPropertyDescriptors ? _Object$defineProperties(target, _Object$getOwnPropertyDescriptors(source)) : _forEachInstanceProperty(_context5 = ownKeys(Object(source))).call(_context5, function (key) { _Object$defineProperty(target, key, _Object$getOwnPropertyDescriptor(source, key)); }); } return target; }
|
51
52
|
var displayName = 'FileInputField';
|
52
53
|
var FILE_CHANGE_STATUS = {
|
53
54
|
ADDED: 'added',
|
@@ -70,6 +71,7 @@ var FileInputField = /*#__PURE__*/(0, _react.forwardRef)(function (props, ref) {
|
|
70
71
|
onRemove = props.onRemove,
|
71
72
|
status = props.status,
|
72
73
|
textProps = props.textProps,
|
74
|
+
fileTypes = props.fileTypes,
|
73
75
|
others = (0, _objectWithoutProperties2["default"])(props, _excluded);
|
74
76
|
var _useState = (0, _react.useState)(defaultFileList || []),
|
75
77
|
_useState2 = (0, _slicedToArray2["default"])(_useState, 2),
|
@@ -120,6 +122,7 @@ var FileInputField = /*#__PURE__*/(0, _react.forwardRef)(function (props, ref) {
|
|
120
122
|
setFileChangeStatus(null);
|
121
123
|
}, [fileChangeStatus, helperText, status]);
|
122
124
|
var handleFileUpload = function handleFileUpload(event, newFiles) {
|
125
|
+
var _context2;
|
123
126
|
if (status === _statuses["default"].ERROR) {
|
124
127
|
setFileChangeMessage('');
|
125
128
|
}
|
@@ -130,7 +133,11 @@ var FileInputField = /*#__PURE__*/(0, _react.forwardRef)(function (props, ref) {
|
|
130
133
|
if (!isMultiple) {
|
131
134
|
arrayWithNewFiles = (0, _slice["default"])(arrayWithNewFiles).call(arrayWithNewFiles, 0, 1);
|
132
135
|
}
|
133
|
-
var filesWithIdAndLink = (0, _map["default"])(arrayWithNewFiles).call(arrayWithNewFiles, function (newFile) {
|
136
|
+
var filesWithIdAndLink = (0, _map["default"])(_context2 = (0, _filter["default"])(arrayWithNewFiles).call(arrayWithNewFiles, function (newFile) {
|
137
|
+
return !fileTypes || (0, _some["default"])(fileTypes).call(fileTypes, function (fileType) {
|
138
|
+
return newFile.type.search(fileType) !== -1;
|
139
|
+
});
|
140
|
+
})).call(_context2, function (newFile) {
|
134
141
|
return {
|
135
142
|
fileObj: newFile,
|
136
143
|
name: newFile.name,
|
@@ -141,8 +148,8 @@ var FileInputField = /*#__PURE__*/(0, _react.forwardRef)(function (props, ref) {
|
|
141
148
|
});
|
142
149
|
if (isMultiple) {
|
143
150
|
setUploadedFiles(function (prevFiles) {
|
144
|
-
var
|
145
|
-
return (0, _concat["default"])(
|
151
|
+
var _context3;
|
152
|
+
return (0, _concat["default"])(_context3 = []).call(_context3, prevFiles, filesWithIdAndLink);
|
146
153
|
});
|
147
154
|
} else {
|
148
155
|
setUploadedFiles(filesWithIdAndLink);
|
@@ -224,7 +231,8 @@ var FileInputField = /*#__PURE__*/(0, _react.forwardRef)(function (props, ref) {
|
|
224
231
|
multiple: isMultiple,
|
225
232
|
onChange: handleOnChange,
|
226
233
|
ref: inputRef,
|
227
|
-
type: "file"
|
234
|
+
type: "file",
|
235
|
+
accept: fileTypes ? fileTypes === null || fileTypes === void 0 ? void 0 : fileTypes.join(',') : '*'
|
228
236
|
})), filesListNode, shouldFileSelectRender() && (isIconButton ? (0, _react2.jsx)(_FileSelectIcon["default"], (0, _extends2["default"])({
|
229
237
|
handleFileSelect: handleFileSelect,
|
230
238
|
iconContainerProps: iconContainerProps,
|
@@ -243,7 +251,8 @@ var FileInputField = /*#__PURE__*/(0, _react.forwardRef)(function (props, ref) {
|
|
243
251
|
},
|
244
252
|
"data-testid": "file-input-field__loader"
|
245
253
|
})), helperText && (0, _react2.jsx)(_.Box, {
|
246
|
-
"aria-label": helperText
|
254
|
+
"aria-label": helperText,
|
255
|
+
role: "marquee"
|
247
256
|
}, (0, _react2.jsx)(_.FieldHelperText, {
|
248
257
|
status: status,
|
249
258
|
id: helperTextId
|
@@ -14,7 +14,8 @@ var _interopRequireDefault = require("@babel/runtime-corejs3/helpers/interopRequ
|
|
14
14
|
_Object$defineProperty(exports, "__esModule", {
|
15
15
|
value: true
|
16
16
|
});
|
17
|
-
exports["default"] = exports.WithCustomWidth = exports.ErrorWithMultipleFiles = exports.ErrorStatusSingleFile = exports.DefaultFileListUncontrolled = exports.Default = exports.CustomButtonText = exports.ControlledState = void 0;
|
17
|
+
exports["default"] = exports.WithFileTypePdfAndImage = exports.WithCustomWidth = exports.ErrorWithMultipleFiles = exports.ErrorStatusSingleFile = exports.DefaultFileListUncontrolled = exports.Default = exports.CustomButtonText = exports.ControlledState = void 0;
|
18
|
+
var _some = _interopRequireDefault(require("@babel/runtime-corejs3/core-js-stable/instance/some"));
|
18
19
|
var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime-corejs3/helpers/slicedToArray"));
|
19
20
|
var _extends2 = _interopRequireDefault(require("@babel/runtime-corejs3/helpers/extends"));
|
20
21
|
var _defineProperty2 = _interopRequireDefault(require("@babel/runtime-corejs3/helpers/defineProperty"));
|
@@ -150,7 +151,8 @@ var ControlledState = function ControlledState() {
|
|
150
151
|
fileList: userFiles,
|
151
152
|
sx: fitContentWidthSx,
|
152
153
|
status: error && _statuses["default"].ERROR,
|
153
|
-
helperText: error
|
154
|
+
helperText: error,
|
155
|
+
isMultiple: true
|
154
156
|
});
|
155
157
|
};
|
156
158
|
exports.ControlledState = ControlledState;
|
@@ -231,4 +233,34 @@ var WithCustomWidth = function WithCustomWidth() {
|
|
231
233
|
isMultiple: true
|
232
234
|
}));
|
233
235
|
};
|
234
|
-
exports.WithCustomWidth = WithCustomWidth;
|
236
|
+
exports.WithCustomWidth = WithCustomWidth;
|
237
|
+
var WithFileTypePdfAndImage = function WithFileTypePdfAndImage() {
|
238
|
+
var fileTypes = ['application/pdf', 'image/*'];
|
239
|
+
var _useState5 = (0, _react.useState)(),
|
240
|
+
_useState6 = (0, _slicedToArray2["default"])(_useState5, 2),
|
241
|
+
error = _useState6[0],
|
242
|
+
setError = _useState6[1];
|
243
|
+
var handleFileSelect = function handleFileSelect(event, files) {
|
244
|
+
var uploadedFileType = files[0].type;
|
245
|
+
var isValidFileType = (0, _some["default"])(fileTypes).call(fileTypes, function (fileType) {
|
246
|
+
return uploadedFileType.search(fileType) !== -1;
|
247
|
+
});
|
248
|
+
if (isValidFileType) {
|
249
|
+
setError(null);
|
250
|
+
} else {
|
251
|
+
setError('Not a valid File Type. Only PDF and Image files are allowed.');
|
252
|
+
}
|
253
|
+
};
|
254
|
+
return (0, _react2.jsx)(_index.FileInputField, {
|
255
|
+
label: "With File Type",
|
256
|
+
sx: fitContentWidthSx,
|
257
|
+
fileTypes: fileTypes,
|
258
|
+
onFileSelect: handleFileSelect,
|
259
|
+
onRemove: function onRemove() {
|
260
|
+
return setError(null);
|
261
|
+
},
|
262
|
+
status: error && _statuses["default"].ERROR,
|
263
|
+
helperText: error
|
264
|
+
});
|
265
|
+
};
|
266
|
+
exports.WithFileTypePdfAndImage = WithFileTypePdfAndImage;
|
@@ -34,12 +34,16 @@ var testFileURL = 'test-file-url';
|
|
34
34
|
var testFileId = 'test-file-id-1';
|
35
35
|
var testFileName = 'chucknorris.png';
|
36
36
|
var testFileName2 = 'chucknorris222.png';
|
37
|
+
var testFileName3 = 'document.pdf';
|
37
38
|
var testFile = new File(['(⌐□_□)'], testFileName, {
|
38
39
|
type: 'image/png'
|
39
40
|
});
|
40
41
|
var testFile2 = new File(['(⌐□_□)'], testFileName2, {
|
41
42
|
type: 'image/png'
|
42
43
|
});
|
44
|
+
var testFile3 = new File(['(⌐□_□)'], testFileName3, {
|
45
|
+
type: 'application/pdf'
|
46
|
+
});
|
43
47
|
var testFileObject = {
|
44
48
|
id: testFileId,
|
45
49
|
name: testFileName,
|
@@ -203,8 +207,7 @@ test('passing helper text should display it and correct aria attributes on input
|
|
203
207
|
expect(helper).toHaveTextContent(testHelperText);
|
204
208
|
expect(helper).toBeInTheDocument();
|
205
209
|
expect(helper).toHaveClass("is-".concat(_statuses["default"].ERROR));
|
206
|
-
|
207
|
-
expect(_react2.screen.getAllByRole('button')[0]).toHaveAttribute('aria-describedby', helperTextID);
|
210
|
+
expect(_react2.screen.getAllByRole('button')[0]).toHaveAttribute('aria-describedby', "file-uploaded__download-link-".concat(testFileId));
|
208
211
|
});
|
209
212
|
test('should display helper text if passed', function () {
|
210
213
|
var testHelperText = 'testHelperText';
|
@@ -221,4 +224,23 @@ test('should render icon button if isIconButton prop is true', function () {
|
|
221
224
|
name: 'Add File Icon'
|
222
225
|
});
|
223
226
|
expect(iconButton).toBeInTheDocument();
|
227
|
+
});
|
228
|
+
test('File upload should allow only image', function () {
|
229
|
+
var setStateMock = jest.fn();
|
230
|
+
jest.spyOn(_react["default"], 'useState').mockImplementation(function (initialState) {
|
231
|
+
return [initialState, setStateMock];
|
232
|
+
});
|
233
|
+
getComponent({
|
234
|
+
fileTypes: ['image/*']
|
235
|
+
});
|
236
|
+
var fileUploadFieldInput = _react2.screen.getByLabelText(testLabel);
|
237
|
+
_userEvent["default"].click(_react2.screen.getByTestId(fileSelectTestIdButton));
|
238
|
+
_react2.fireEvent.change(fileUploadFieldInput, {
|
239
|
+
target: {
|
240
|
+
files: [testFile3]
|
241
|
+
}
|
242
|
+
});
|
243
|
+
var val = _react2.screen.queryByText('document');
|
244
|
+
expect(val).not.toBeInTheDocument();
|
245
|
+
expect(setStateMock).toHaveBeenCalled();
|
224
246
|
});
|
@@ -34,7 +34,6 @@ 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,
|
38
37
|
id = props.id,
|
39
38
|
isDisabled = props.isDisabled,
|
40
39
|
name = props.name,
|
@@ -87,7 +86,7 @@ var FileItem = function FileItem(props) {
|
|
87
86
|
"aria-label": name,
|
88
87
|
"data-testid": "file-uploaded__download-file-button",
|
89
88
|
onPress: handleDownloadPress,
|
90
|
-
"aria-describedby":
|
89
|
+
"aria-describedby": "file-uploaded__download-link-".concat(id),
|
91
90
|
"aria-live": "polite"
|
92
91
|
}, (0, _react2.jsx)(_index.Text, (0, _extends2["default"])({
|
93
92
|
color: "active"
|
@@ -113,7 +112,8 @@ var FileItem = function FileItem(props) {
|
|
113
112
|
ref: downloadRef,
|
114
113
|
"aria-label": "download ".concat(name),
|
115
114
|
"data-testid": "file-uploaded__download-link",
|
116
|
-
tabIndex: -1
|
115
|
+
tabIndex: -1,
|
116
|
+
id: "file-uploaded__download-link-".concat(id)
|
117
117
|
})));
|
118
118
|
};
|
119
119
|
var _default = FileItem;
|
@@ -18,6 +18,7 @@ export interface PromptProps {
|
|
18
18
|
export interface PromptInputProps extends TextFieldProps, PromptProps {
|
19
19
|
onKeyUp?: (e: React.KeyboardEvent, value?: string) => void;
|
20
20
|
onKeyDown?: (e: React.KeyboardEvent, value?: string) => void;
|
21
|
+
isUploadButtonHidden?: boolean;
|
21
22
|
}
|
22
23
|
export interface AttachmentProps {
|
23
24
|
title: string;
|
@@ -29,6 +29,8 @@ var PromptInput = /*#__PURE__*/forwardRef(function (props, ref) {
|
|
29
29
|
var attachmentProps = props.attachmentProps,
|
30
30
|
isFullScreen = props.isFullScreen,
|
31
31
|
isLoading = props.isLoading,
|
32
|
+
_props$isUploadButton = props.isUploadButtonHidden,
|
33
|
+
isUploadButtonHidden = _props$isUploadButton === void 0 ? false : _props$isUploadButton,
|
32
34
|
fileInputButtonProps = props.fileInputButtonProps,
|
33
35
|
valueProp = props.value,
|
34
36
|
defaultValueProp = props.defaultValue,
|
@@ -176,7 +178,7 @@ var PromptInput = /*#__PURE__*/forwardRef(function (props, ref) {
|
|
176
178
|
}, fieldControlInputProps, {
|
177
179
|
onKeyUp: onKeyUp,
|
178
180
|
onKeyDown: onKeyDown
|
179
|
-
})), ___EmotionJSX(Box, {
|
181
|
+
})), !isUploadButtonHidden && ___EmotionJSX(Box, {
|
180
182
|
sx: {
|
181
183
|
mx: '.75rem',
|
182
184
|
mb: 'auto'
|
@@ -12,15 +12,28 @@ import _defineProperty from "@babel/runtime-corejs3/helpers/esm/defineProperty";
|
|
12
12
|
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; }
|
13
13
|
function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var _context, _context2; var source = null != arguments[i] ? arguments[i] : {}; i % 2 ? _forEachInstanceProperty(_context = ownKeys(Object(source), !0)).call(_context, function (key) { _defineProperty(target, key, source[key]); }) : _Object$getOwnPropertyDescriptors ? _Object$defineProperties(target, _Object$getOwnPropertyDescriptors(source)) : _forEachInstanceProperty(_context2 = ownKeys(Object(source))).call(_context2, function (key) { _Object$defineProperty(target, key, _Object$getOwnPropertyDescriptor(source, key)); }); } return target; }
|
14
14
|
import React, { useState } from 'react';
|
15
|
+
import DocsLayout from '../../../../.storybook/storybookDocsLayout';
|
15
16
|
import { AstroProvider, Box, NextGenTheme } from '../../..';
|
16
17
|
import { booleanArg } from '../../../utils/docUtils/docArgTypes';
|
17
18
|
import PromptInput from './PromptInput';
|
19
|
+
import PromptInputReadMe from './PromptInputReadMe.mdx';
|
18
20
|
import { jsx as ___EmotionJSX } from "@emotion/react";
|
19
21
|
export default {
|
20
22
|
title: 'Ai Components/Prompt Input',
|
21
23
|
component: PromptInput,
|
24
|
+
parameters: {
|
25
|
+
docs: {
|
26
|
+
page: function page() {
|
27
|
+
return ___EmotionJSX(React.Fragment, null, ___EmotionJSX(PromptInputReadMe, null), ___EmotionJSX(DocsLayout, null));
|
28
|
+
},
|
29
|
+
source: {
|
30
|
+
type: 'code'
|
31
|
+
}
|
32
|
+
}
|
33
|
+
},
|
22
34
|
argTypes: {
|
23
|
-
isLoading: _objectSpread({}, booleanArg)
|
35
|
+
isLoading: _objectSpread({}, booleanArg),
|
36
|
+
isUploadButtonHidden: _objectSpread({}, booleanArg)
|
24
37
|
}
|
25
38
|
};
|
26
39
|
export var Default = function Default(args) {
|
@@ -131,6 +131,15 @@ test('onSubmit prop works correctly', /*#__PURE__*/_asyncToGenerator( /*#__PURE_
|
|
131
131
|
}
|
132
132
|
}, _callee2);
|
133
133
|
})));
|
134
|
+
test('', function () {
|
135
|
+
getComponent({
|
136
|
+
isUploadButtonHidden: true,
|
137
|
+
uploadButtonProps: {
|
138
|
+
'data-testid': buttonTestId
|
139
|
+
}
|
140
|
+
});
|
141
|
+
expect(screen.queryByText(buttonTestId)).not.toBeInTheDocument();
|
142
|
+
});
|
134
143
|
test('onCancel prop works correctly', /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee3() {
|
135
144
|
var control;
|
136
145
|
return _regeneratorRuntime().wrap(function _callee3$(_context3) {
|
@@ -0,0 +1,71 @@
|
|
1
|
+
import { Meta } from '@storybook/addon-docs';
|
2
|
+
|
3
|
+
<Meta title="Components/PromptInput" />
|
4
|
+
|
5
|
+
# PromptInput
|
6
|
+
|
7
|
+
The `PromptInput` component is used to capture user input in a conversational UI. It supports text input, file attachments, and customizable actions like submission or cancellation.
|
8
|
+
|
9
|
+
### Recommended Use
|
10
|
+
|
11
|
+
- Use the `PromptInput` component to collect user input in chat-like interfaces.
|
12
|
+
- Attach files or documents to the input using the file attachment feature.
|
13
|
+
|
14
|
+
### Features
|
15
|
+
|
16
|
+
- **Text Input**: Allows users to type text with dynamic height adjustment based on content.
|
17
|
+
- **File Attachments**: Supports adding and removing file attachments.
|
18
|
+
- **Customizable Actions**: Includes `onSubmit`, `onCancel`, `onKeyDown`, and `onKeyUp` handlers for custom behavior.
|
19
|
+
|
20
|
+
### Props
|
21
|
+
|
22
|
+
| Prop | Type | Description |
|
23
|
+
| --------------------- | -------------------- | --------------------------------------------------------------------------- |
|
24
|
+
| `value` | `string` | The controlled value of the input. |
|
25
|
+
| `defaultValue` | `string` | The default value of the input. |
|
26
|
+
| `onSubmit` | `function` | Callback triggered when the input is submitted. |
|
27
|
+
| `onCancel` | `function` | Callback triggered when the input is canceled. |
|
28
|
+
| `onKeyDown` | `function` | Callback triggered on key down events. |
|
29
|
+
| `onKeyUp` | `function` | Callback triggered on key up events. |
|
30
|
+
| `onFileChange` | `function` | Callback triggered when files are added or removed. |
|
31
|
+
| `attachmentProps` | `object` | Props passed to the `Attachment` component for file attachments. |
|
32
|
+
| `fileInputButtonProps`| `object` | Props passed to the file input button. |
|
33
|
+
| `uploadButtonProps` | `object` | Props passed to the upload button. |
|
34
|
+
| `isLoading` | `boolean` | Indicates whether the input is in a loading state. |
|
35
|
+
|
36
|
+
### Accessibility
|
37
|
+
|
38
|
+
This component adheres to accessibility guidelines to ensure a better user experience for all users.
|
39
|
+
|
40
|
+
#### Keyboard Navigation
|
41
|
+
|
42
|
+
| Keys | Function |
|
43
|
+
| ------------ | ----------------------------------------------------------------------- |
|
44
|
+
| Tab | Focuses on the next focusable element within the input. |
|
45
|
+
| Shift + Tab | Moves focus to the previous focusable element. |
|
46
|
+
| Enter | Submits the input when `onSubmit` is defined. |
|
47
|
+
| Shift + Enter| Adds a new line to the input. |
|
48
|
+
| Escape | Cancels the input when `onCancel` is defined. |
|
49
|
+
|
50
|
+
#### Screen Readers
|
51
|
+
|
52
|
+
- **`aria-label`**: Describes the purpose of the input field.
|
53
|
+
- **`aria-disabled`**: Indicates when the input is disabled.
|
54
|
+
- **`aria-live`**: Announces changes to the input dynamically.
|
55
|
+
|
56
|
+
### Example Usage
|
57
|
+
|
58
|
+
```jsx
|
59
|
+
<PromptInput
|
60
|
+
value=""
|
61
|
+
onSubmit={(e, value) => console.log('Submitted:', value)}
|
62
|
+
onCancel={(e) => console.log('Canceled')}
|
63
|
+
onFileChange={(files) => console.log('Files:', files)}
|
64
|
+
attachmentProps={{
|
65
|
+
icon: GlobeIcon,
|
66
|
+
}}
|
67
|
+
uploadButtonProps={{
|
68
|
+
'aria-label': 'Upload',
|
69
|
+
}}
|
70
|
+
isLoading={false}
|
71
|
+
/>
|
@@ -9,15 +9,16 @@ import _extends from "@babel/runtime-corejs3/helpers/esm/extends";
|
|
9
9
|
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
|
-
var _excluded = ["buttonProps", "defaultButtonText", "defaultFileList", "fileList", "helperText", "iconContainerProps", "iconProps", "isDisabled", "isIconButton", "isLoading", "isMultiple", "label", "onFileSelect", "onRemove", "status", "textProps"];
|
12
|
+
var _excluded = ["buttonProps", "defaultButtonText", "defaultFileList", "fileList", "helperText", "iconContainerProps", "iconProps", "isDisabled", "isIconButton", "isLoading", "isMultiple", "label", "onFileSelect", "onRemove", "status", "textProps", "fileTypes"];
|
13
13
|
import _concatInstanceProperty from "@babel/runtime-corejs3/core-js-stable/instance/concat";
|
14
14
|
import _Array$from from "@babel/runtime-corejs3/core-js-stable/array/from";
|
15
15
|
import _sliceInstanceProperty from "@babel/runtime-corejs3/core-js-stable/instance/slice";
|
16
16
|
import _mapInstanceProperty from "@babel/runtime-corejs3/core-js-stable/instance/map";
|
17
|
-
import _URL from "@babel/runtime-corejs3/core-js-stable/url";
|
18
17
|
import _filterInstanceProperty from "@babel/runtime-corejs3/core-js-stable/instance/filter";
|
18
|
+
import _someInstanceProperty from "@babel/runtime-corejs3/core-js-stable/instance/some";
|
19
|
+
import _URL from "@babel/runtime-corejs3/core-js-stable/url";
|
19
20
|
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
|
21
|
+
function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var _context4, _context5; var source = null != arguments[i] ? arguments[i] : {}; i % 2 ? _forEachInstanceProperty(_context4 = ownKeys(Object(source), !0)).call(_context4, function (key) { _defineProperty(target, key, source[key]); }) : _Object$getOwnPropertyDescriptors ? _Object$defineProperties(target, _Object$getOwnPropertyDescriptors(source)) : _forEachInstanceProperty(_context5 = ownKeys(Object(source))).call(_context5, function (key) { _Object$defineProperty(target, key, _Object$getOwnPropertyDescriptor(source, key)); }); } return target; }
|
21
22
|
import React, { forwardRef, useCallback, useEffect, useImperativeHandle, useMemo, useRef, useState } from 'react';
|
22
23
|
import { mergeProps, useVisuallyHidden, VisuallyHidden } from 'react-aria';
|
23
24
|
import { useDropzone } from 'react-dropzone';
|
@@ -58,6 +59,7 @@ var FileInputField = /*#__PURE__*/forwardRef(function (props, ref) {
|
|
58
59
|
onRemove = props.onRemove,
|
59
60
|
status = props.status,
|
60
61
|
textProps = props.textProps,
|
62
|
+
fileTypes = props.fileTypes,
|
61
63
|
others = _objectWithoutProperties(props, _excluded);
|
62
64
|
var _useState = useState(defaultFileList || []),
|
63
65
|
_useState2 = _slicedToArray(_useState, 2),
|
@@ -108,6 +110,7 @@ var FileInputField = /*#__PURE__*/forwardRef(function (props, ref) {
|
|
108
110
|
setFileChangeStatus(null);
|
109
111
|
}, [fileChangeStatus, helperText, status]);
|
110
112
|
var handleFileUpload = function handleFileUpload(event, newFiles) {
|
113
|
+
var _context2;
|
111
114
|
if (status === statuses.ERROR) {
|
112
115
|
setFileChangeMessage('');
|
113
116
|
}
|
@@ -118,7 +121,11 @@ var FileInputField = /*#__PURE__*/forwardRef(function (props, ref) {
|
|
118
121
|
if (!isMultiple) {
|
119
122
|
arrayWithNewFiles = _sliceInstanceProperty(arrayWithNewFiles).call(arrayWithNewFiles, 0, 1);
|
120
123
|
}
|
121
|
-
var filesWithIdAndLink = _mapInstanceProperty(arrayWithNewFiles).call(arrayWithNewFiles, function (newFile) {
|
124
|
+
var filesWithIdAndLink = _mapInstanceProperty(_context2 = _filterInstanceProperty(arrayWithNewFiles).call(arrayWithNewFiles, function (newFile) {
|
125
|
+
return !fileTypes || _someInstanceProperty(fileTypes).call(fileTypes, function (fileType) {
|
126
|
+
return newFile.type.search(fileType) !== -1;
|
127
|
+
});
|
128
|
+
})).call(_context2, function (newFile) {
|
122
129
|
return {
|
123
130
|
fileObj: newFile,
|
124
131
|
name: newFile.name,
|
@@ -129,8 +136,8 @@ var FileInputField = /*#__PURE__*/forwardRef(function (props, ref) {
|
|
129
136
|
});
|
130
137
|
if (isMultiple) {
|
131
138
|
setUploadedFiles(function (prevFiles) {
|
132
|
-
var
|
133
|
-
return _concatInstanceProperty(
|
139
|
+
var _context3;
|
140
|
+
return _concatInstanceProperty(_context3 = []).call(_context3, prevFiles, filesWithIdAndLink);
|
134
141
|
});
|
135
142
|
} else {
|
136
143
|
setUploadedFiles(filesWithIdAndLink);
|
@@ -212,7 +219,8 @@ var FileInputField = /*#__PURE__*/forwardRef(function (props, ref) {
|
|
212
219
|
multiple: isMultiple,
|
213
220
|
onChange: handleOnChange,
|
214
221
|
ref: inputRef,
|
215
|
-
type: "file"
|
222
|
+
type: "file",
|
223
|
+
accept: fileTypes ? fileTypes === null || fileTypes === void 0 ? void 0 : fileTypes.join(',') : '*'
|
216
224
|
})), filesListNode, shouldFileSelectRender() && (isIconButton ? ___EmotionJSX(FileSelectIcon, _extends({
|
217
225
|
handleFileSelect: handleFileSelect,
|
218
226
|
iconContainerProps: iconContainerProps,
|
@@ -231,7 +239,8 @@ var FileInputField = /*#__PURE__*/forwardRef(function (props, ref) {
|
|
231
239
|
},
|
232
240
|
"data-testid": "file-input-field__loader"
|
233
241
|
})), helperText && ___EmotionJSX(Box, {
|
234
|
-
"aria-label": helperText
|
242
|
+
"aria-label": helperText,
|
243
|
+
role: "marquee"
|
235
244
|
}, ___EmotionJSX(FieldHelperText, {
|
236
245
|
status: status,
|
237
246
|
id: helperTextId
|
@@ -9,6 +9,7 @@ import _Object$defineProperty from "@babel/runtime-corejs3/core-js-stable/object
|
|
9
9
|
import _slicedToArray from "@babel/runtime-corejs3/helpers/esm/slicedToArray";
|
10
10
|
import _extends from "@babel/runtime-corejs3/helpers/esm/extends";
|
11
11
|
import _defineProperty from "@babel/runtime-corejs3/helpers/esm/defineProperty";
|
12
|
+
import _someInstanceProperty from "@babel/runtime-corejs3/core-js-stable/instance/some";
|
12
13
|
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; }
|
13
14
|
function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var _context, _context2; var source = null != arguments[i] ? arguments[i] : {}; i % 2 ? _forEachInstanceProperty(_context = ownKeys(Object(source), !0)).call(_context, function (key) { _defineProperty(target, key, source[key]); }) : _Object$getOwnPropertyDescriptors ? _Object$defineProperties(target, _Object$getOwnPropertyDescriptors(source)) : _forEachInstanceProperty(_context2 = ownKeys(Object(source))).call(_context2, function (key) { _Object$defineProperty(target, key, _Object$getOwnPropertyDescriptor(source, key)); }); } return target; }
|
14
15
|
import React, { useState } from 'react';
|
@@ -136,7 +137,8 @@ export var ControlledState = function ControlledState() {
|
|
136
137
|
fileList: userFiles,
|
137
138
|
sx: fitContentWidthSx,
|
138
139
|
status: error && statuses.ERROR,
|
139
|
-
helperText: error
|
140
|
+
helperText: error,
|
141
|
+
isMultiple: true
|
140
142
|
});
|
141
143
|
};
|
142
144
|
export var DefaultFileListUncontrolled = function DefaultFileListUncontrolled() {
|
@@ -212,4 +214,33 @@ export var WithCustomWidth = function WithCustomWidth() {
|
|
212
214
|
},
|
213
215
|
isMultiple: true
|
214
216
|
}));
|
217
|
+
};
|
218
|
+
export var WithFileTypePdfAndImage = function WithFileTypePdfAndImage() {
|
219
|
+
var fileTypes = ['application/pdf', 'image/*'];
|
220
|
+
var _useState5 = useState(),
|
221
|
+
_useState6 = _slicedToArray(_useState5, 2),
|
222
|
+
error = _useState6[0],
|
223
|
+
setError = _useState6[1];
|
224
|
+
var handleFileSelect = function handleFileSelect(event, files) {
|
225
|
+
var uploadedFileType = files[0].type;
|
226
|
+
var isValidFileType = _someInstanceProperty(fileTypes).call(fileTypes, function (fileType) {
|
227
|
+
return uploadedFileType.search(fileType) !== -1;
|
228
|
+
});
|
229
|
+
if (isValidFileType) {
|
230
|
+
setError(null);
|
231
|
+
} else {
|
232
|
+
setError('Not a valid File Type. Only PDF and Image files are allowed.');
|
233
|
+
}
|
234
|
+
};
|
235
|
+
return ___EmotionJSX(FileInputField, {
|
236
|
+
label: "With File Type",
|
237
|
+
sx: fitContentWidthSx,
|
238
|
+
fileTypes: fileTypes,
|
239
|
+
onFileSelect: handleFileSelect,
|
240
|
+
onRemove: function onRemove() {
|
241
|
+
return setError(null);
|
242
|
+
},
|
243
|
+
status: error && statuses.ERROR,
|
244
|
+
helperText: error
|
245
|
+
});
|
215
246
|
};
|
@@ -31,12 +31,16 @@ var testFileURL = 'test-file-url';
|
|
31
31
|
var testFileId = 'test-file-id-1';
|
32
32
|
var testFileName = 'chucknorris.png';
|
33
33
|
var testFileName2 = 'chucknorris222.png';
|
34
|
+
var testFileName3 = 'document.pdf';
|
34
35
|
var testFile = new File(['(⌐□_□)'], testFileName, {
|
35
36
|
type: 'image/png'
|
36
37
|
});
|
37
38
|
var testFile2 = new File(['(⌐□_□)'], testFileName2, {
|
38
39
|
type: 'image/png'
|
39
40
|
});
|
41
|
+
var testFile3 = new File(['(⌐□_□)'], testFileName3, {
|
42
|
+
type: 'application/pdf'
|
43
|
+
});
|
40
44
|
var testFileObject = {
|
41
45
|
id: testFileId,
|
42
46
|
name: testFileName,
|
@@ -200,8 +204,7 @@ test('passing helper text should display it and correct aria attributes on input
|
|
200
204
|
expect(helper).toHaveTextContent(testHelperText);
|
201
205
|
expect(helper).toBeInTheDocument();
|
202
206
|
expect(helper).toHaveClass("is-".concat(statuses.ERROR));
|
203
|
-
|
204
|
-
expect(screen.getAllByRole('button')[0]).toHaveAttribute('aria-describedby', helperTextID);
|
207
|
+
expect(screen.getAllByRole('button')[0]).toHaveAttribute('aria-describedby', "file-uploaded__download-link-".concat(testFileId));
|
205
208
|
});
|
206
209
|
test('should display helper text if passed', function () {
|
207
210
|
var testHelperText = 'testHelperText';
|
@@ -218,4 +221,23 @@ test('should render icon button if isIconButton prop is true', function () {
|
|
218
221
|
name: 'Add File Icon'
|
219
222
|
});
|
220
223
|
expect(iconButton).toBeInTheDocument();
|
224
|
+
});
|
225
|
+
test('File upload should allow only image', function () {
|
226
|
+
var setStateMock = jest.fn();
|
227
|
+
jest.spyOn(React, 'useState').mockImplementation(function (initialState) {
|
228
|
+
return [initialState, setStateMock];
|
229
|
+
});
|
230
|
+
getComponent({
|
231
|
+
fileTypes: ['image/*']
|
232
|
+
});
|
233
|
+
var fileUploadFieldInput = screen.getByLabelText(testLabel);
|
234
|
+
userEvent.click(screen.getByTestId(fileSelectTestIdButton));
|
235
|
+
fireEvent.change(fileUploadFieldInput, {
|
236
|
+
target: {
|
237
|
+
files: [testFile3]
|
238
|
+
}
|
239
|
+
});
|
240
|
+
var val = screen.queryByText('document');
|
241
|
+
expect(val).not.toBeInTheDocument();
|
242
|
+
expect(setStateMock).toHaveBeenCalled();
|
221
243
|
});
|
@@ -23,7 +23,6 @@ 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,
|
27
26
|
id = props.id,
|
28
27
|
isDisabled = props.isDisabled,
|
29
28
|
name = props.name,
|
@@ -76,7 +75,7 @@ var FileItem = function FileItem(props) {
|
|
76
75
|
"aria-label": name,
|
77
76
|
"data-testid": "file-uploaded__download-file-button",
|
78
77
|
onPress: handleDownloadPress,
|
79
|
-
"aria-describedby":
|
78
|
+
"aria-describedby": "file-uploaded__download-link-".concat(id),
|
80
79
|
"aria-live": "polite"
|
81
80
|
}, ___EmotionJSX(Text, _extends({
|
82
81
|
color: "active"
|
@@ -102,7 +101,8 @@ var FileItem = function FileItem(props) {
|
|
102
101
|
ref: downloadRef,
|
103
102
|
"aria-label": "download ".concat(name),
|
104
103
|
"data-testid": "file-uploaded__download-link",
|
105
|
-
tabIndex: -1
|
104
|
+
tabIndex: -1,
|
105
|
+
id: "file-uploaded__download-link-".concat(id)
|
106
106
|
})));
|
107
107
|
};
|
108
108
|
export default FileItem;
|