diff --git a/packages/ffe-file-upload-react/package.json b/packages/ffe-file-upload-react/package.json index f6a2bbc838..b23bda7959 100644 --- a/packages/ffe-file-upload-react/package.json +++ b/packages/ffe-file-upload-react/package.json @@ -23,8 +23,8 @@ "scripts": { "build": "ffe-buildtool babel", "watch": "ffe-buildtool babel-watch", - "lint": "eslint src", - "lint:fix": "eslint src --fix", + "lint": "eslint src --ext ts,tsx", + "lint:fix": "eslint src --fix --ext ts,tsx", "test": "ffe-buildtool jest", "test:watch": "ffe-buildtool jest --watch" }, @@ -37,16 +37,15 @@ }, "devDependencies": { "@sb1/ffe-buildtool": "^0.6.1", + "@types/sinon": "^17.0.3", "react": "^16.9.0", - "react-dom": "^16.9.0" + "react-dom": "^16.9.0", + "sinon": "^7.2.3" }, "peerDependencies": { "react": ">=16.9.0" }, "publishConfig": { "access": "public" - }, - "depencencies": { - "prop-types": "^15.6.0" } } diff --git a/packages/ffe-file-upload-react/src/FileItem.js b/packages/ffe-file-upload-react/src/FileItem.tsx similarity index 93% rename from packages/ffe-file-upload-react/src/FileItem.js rename to packages/ffe-file-upload-react/src/FileItem.tsx index ff5a2aa5fe..88f16223cf 100644 --- a/packages/ffe-file-upload-react/src/FileItem.js +++ b/packages/ffe-file-upload-react/src/FileItem.tsx @@ -1,8 +1,29 @@ import React from 'react'; -import { func, shape, object, string as stringType } from 'prop-types'; import { Icon } from '@sb1/ffe-icons-react'; -const FileItem = ({ file, onFileDeleted, cancelText, deleteText }) => { +export interface FileItemProps { + /** Shape of the file type, name is required, error and document.content is optional */ + file: { + name: string; + document?: Document; + error?: string; + }; + /** + * Called when the user clicks the delete button for a given file. Is called with the name of the file in question. + */ + onFileDeleted: React.MouseEventHandler; + /** Label for the cancel button */ + cancelText?: string; + /** Label for the delete button */ + deleteText?: string; +} + +export function FileItem({ + file, + onFileDeleted, + cancelText, + deleteText, +}: FileItemProps) { const closeIcon = 'data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIGhlaWdodD0iMjQiIHZpZXdCb3g9IjAgLTk2MCA5NjAgOTYwIiB3aWR0aD0iMjQiPjxwYXRoIGQ9Ik00ODAtNDM3Ljg0NyAyNzcuMDc2LTIzNC45MjRxLTguMzA3IDguMzA4LTIwLjg4NCA4LjUtMTIuNTc2LjE5My0yMS4yNjgtOC41LTguNjkzLTguNjkyLTguNjkzLTIxLjA3NnQ4LjY5My0yMS4wNzZMNDM3Ljg0Ny00ODAgMjM0LjkyNC02ODIuOTI0cS04LjMwOC04LjMwNy04LjUtMjAuODg0LS4xOTMtMTIuNTc2IDguNS0yMS4yNjggOC42OTItOC42OTMgMjEuMDc2LTguNjkzdDIxLjA3NiA4LjY5M0w0ODAtNTIyLjE1M2wyMDIuOTI0LTIwMi45MjNxOC4zMDctOC4zMDggMjAuODg0LTguNSAxMi41NzYtLjE5MyAyMS4yNjggOC41IDguNjkzIDguNjkyIDguNjkzIDIxLjA3NnQtOC42OTMgMjEuMDc2TDUyMi4xNTMtNDgwbDIwMi45MjMgMjAyLjkyNHE4LjMwOCA4LjMwNyA4LjUgMjAuODg0LjE5MyAxMi41NzYtOC41IDIxLjI2OC04LjY5MiA4LjY5My0yMS4wNzYgOC42OTN0LTIxLjA3Ni04LjY5M0w0ODAtNDM3Ljg0N1oiLz48L3N2Zz4='; @@ -102,23 +123,4 @@ const FileItem = ({ file, onFileDeleted, cancelText, deleteText }) => { } ); -}; - -FileItem.propTypes = { - /** Shape of the file type, name is required, error and document.content is optional */ - file: shape({ - name: stringType.isRequired, - document: object, - error: stringType, - }).isRequired, - /** - * Called when the user clicks the delete button for a given file. Is called with the name of the file in question. - */ - onFileDeleted: func.isRequired, - /** Label for the cancel button */ - cancelText: stringType, - /** Label for the delete button */ - deleteText: stringType, -}; - -export default FileItem; +} diff --git a/packages/ffe-file-upload-react/src/FileUpload.js b/packages/ffe-file-upload-react/src/FileUpload.js deleted file mode 100644 index 9bdbd97cbc..0000000000 --- a/packages/ffe-file-upload-react/src/FileUpload.js +++ /dev/null @@ -1,194 +0,0 @@ -import React from 'react'; -import { object, bool, func, string as stringType } from 'prop-types'; -import FileItem from './FileItem'; -import classNames from 'classnames'; -import { SecondaryButton } from '@sb1/ffe-buttons-react'; -import { Icon } from '@sb1/ffe-icons-react'; - -class FileUpload extends React.Component { - constructor(props) { - super(props); - - this.onFilesSelected = this.onFilesSelected.bind(this); - this.onFilesDropped = this.onFilesDropped.bind(this); - this.onFileDeleted = this.onFileDeleted.bind(this); - this.setFileInputElement = this.setFileInputElement.bind(this); - this.triggerUploadFileNativeHandler = - this.triggerUploadFileNativeHandler.bind(this); - - this.state = { hover: false }; - } - - setFileInputElement(element) { - this.fileInputElement = element; - } - - triggerUploadFileNativeHandler() { - // clear file input to trigger onChange when uploading same filename - if (this.fileInputElement) { - this.fileInputElement.value = ''; - } - this.fileInputElement.click(); - } - - onFilesSelected(event) { - this.props.onFilesSelected(event.target.files); - } - - onFilesDropped(event) { - event.preventDefault(); - this.setState({ hover: false }); - this.props.onFilesDropped(event.dataTransfer.files); - } - - onFileDeleted(event) { - this.props.onFileDeleted(this.props.files[event.currentTarget.id]); - } - - render() { - const { - id, - label, - files, - cancelText, - deleteText, - multiple, - title, - infoText, - infoSubText, - uploadTitle, - uploadMicroText, - uploadSubText, - accept, - } = this.props; - - const downloadIcon = - 'data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIGhlaWdodD0iMjAiIHZpZXdCb3g9IjAgLTk2MCA5NjAgOTYwIiB3aWR0aD0iMjAiPjxwYXRoIGQ9Ik00NzkuOC0zNTcuNTM5cS02LjQzMSAwLTExLjk2MS0yLjMwOC01LjUzMS0yLjMwNy0xMC4xNDYtNi45MjNMMzM1LjMwOS00ODkuMTUzcS03LjkyMy03LjgzMi03LjgwNy0xOC4zMzguMTE1LTEwLjUwNyA4LjMyOS0xOC44MTUgOC43ODYtOC4zMDcgMTguODYyLTguMTE1IDEwLjA3Ny4xOTIgMTguMzg1IDguNWw4MC45MjMgODEuOTIzdi0zMjYuMDAxcTAtMTEuMDY5IDcuNDA0LTE4LjUzNCA3LjQwNS03LjQ2NiAxOC4zODQtNy40NjYgMTAuOTggMCAxOC41OTUgNy40NjYgNy42MTUgNy40NjUgNy42MTUgMTguNTM0djMyNi4wMDFsODEuOTIzLTgxLjkyM3E3LjU5LTcuOTIzIDE4LjAyNi03LjgwOCAxMC40MzUuMTE2IDE5LjIyMSA4LjQyMyA4LjIxNCA4LjMwOCA4LjAyMSAxOC41NzctLjE5MiAxMC4yNjktOC40OTkgMTguNTc2TDUwMi4zMDctMzY2Ljc3cS01LjAxNSA0LjYxNi0xMC41NDYgNi45MjMtNS41MyAyLjMwOC0xMS45NjEgMi4zMDhaTTI3Ni4wMjUtMjEyLjAwMXEtMjcuMDI0IDAtNDUuNTI0LTE4LjY1dC0xOC41LTQ1LjY1OHYtMzQuNDYxcTAtMTEuMDY5IDcuNDA1LTE4LjUzNCA3LjQwNS03LjQ2NSAxOC4zODQtNy40NjUgMTAuOTggMCAxOC41OTUgNy40NjVRMjY0LTMyMS44MzkgMjY0LTMxMC43N3YzNC40NjFxMCA0LjYxNiAzLjg0NiA4LjQ2MyAzLjg0NyAzLjg0NiA4LjQ2MyAzLjg0Nmg0MDcuMzgycTQuNjE2IDAgOC40NjMtMy44NDYgMy44NDYtMy44NDcgMy44NDYtOC40NjN2LTM0LjQ2MXEwLTExLjA2OSA3LjQwNS0xOC41MzQgNy40MDQtNy40NjUgMTguMzg0LTcuNDY1IDEwLjk3OSAwIDE4LjU5NCA3LjQ2NSA3LjYxNiA3LjQ2NSA3LjYxNiAxOC41MzR2MzQuNDYxcTAgMjcuMDA4LTE4LjY2MiA0NS42NTgtMTguNjYyIDE4LjY1LTQ1LjY4NiAxOC42NUgyNzYuMDI1WiIvPjwvc3ZnPg=='; - - return ( -
-
{title}
- {Object.keys(files).length > 0 ? ( -
- {Object.keys(files).map(file => ( - - ))} -
- ) : ( -
-
- {infoText} -
-
- {infoSubText} -
-
- )} -
{ - event.preventDefault(); - this.setState({ hover: true }); - }} - onDragLeave={() => this.setState({ hover: false })} - > -
-
- {uploadTitle} -
-
- {uploadMicroText} -
- } - onClick={this.triggerUploadFileNativeHandler} - id={`${id}-button`} - > - {label} - -
- {uploadSubText} -
-
-
- -
- ); - } -} - -FileUpload.propTypes = { - /** ID for the input field. The ID is used as a base for the label ID as well. */ - id: stringType.isRequired, - /** Label for the button to trigger native upload handling. */ - label: stringType.isRequired, - /** - * A map of files, indexed by file name (check file-shape on FileItem.js propTypes), that the user has uploaded. - * Must be maintained outside of `FileUpload`. It is up to the implementation to deny or accept file types, sizes, etc, - * and it is important that duplicates are not allowed. - * */ - files: object.isRequired, - /** - * Will be called with `FileList`-object containing the `File`-objects the user selected. - * See MDN for documentation on - * [FileList](https://developer.mozilla.org/en-US/docs/Web/API/FileList) and - * [File](https://developer.mozilla.org/en-US/docs/Web/API/File). - */ - onFilesSelected: func.isRequired, - /** Will be called when objects are dropped over the upload-section. */ - onFilesDropped: func.isRequired, - /** - * Called when the user clicks the delete button for a given file. Is called with the `File` - * object of the file in question. - */ - onFileDeleted: func.isRequired, - /** Whether or not uploading multiple files at once via the native file handler is allowed*/ - multiple: bool, - /** Title module */ - title: stringType.isRequired, - /** Text on the info-section */ - infoText: stringType.isRequired, - /** Subtext on the info-section */ - infoSubText: stringType, - /** Label for the cancel button */ - cancelText: stringType, - /** Label for the delete button */ - deleteText: stringType, - /** Title on the upload-section */ - uploadTitle: stringType.isRequired, - /** MicroText on the upload-section */ - uploadMicroText: stringType.isRequired, - /** SubText on the upload-section */ - uploadSubText: stringType.isRequired, - /** Unique file type specifier that describes a type of file that may be selected by the user, e.g. ".pdf" - * See MDN for documentation on - * [Unique file type specifiers](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input/file#unique_file_type_specifiers) - */ - accept: stringType, -}; - -export default FileUpload; diff --git a/packages/ffe-file-upload-react/src/FileUpload.spec.js b/packages/ffe-file-upload-react/src/FileUpload.spec.js deleted file mode 100644 index 30524cd72d..0000000000 --- a/packages/ffe-file-upload-react/src/FileUpload.spec.js +++ /dev/null @@ -1,94 +0,0 @@ -import React from 'react'; -import { spy } from 'sinon'; - -import FileUpload from '../src/FileUpload'; - -describe('', () => { - let component; - let onFilesSelected; - let onFileDeleted; - let onFilesDropped; - - beforeEach(() => { - onFilesSelected = spy(); - onFileDeleted = spy(); - onFilesDropped = spy(); - }); - - describe('initial state', () => { - beforeEach(() => { - component = shallow( - , - ); - }); - - it('should have a button and input', () => { - expect(component.find('#file-upload-button').exists()).toBe(true); - expect(component.find('#file-upload').exists()).toBe(true); - }); - - it('should render input label', () => { - expect(component.find('#file-upload-label').text()).toBe('label'); - }); - - it('should add label as aria-label', () => { - expect(component.find('#file-upload-label').text()).toBe('label'); - }); - - it('should extract and return files when user finishes selecting files', () => { - component.find('input#file-upload').simulate('change', { - target: { - files: { - filename: { - name: 'filename', - }, - }, - }, - }); - - expect(onFilesSelected.calledOnce).toBe(true); - }); - - it('should remove file from files when delete button is clicked', () => { - // Component needs to be mounted for this test because we must render children. - component = mount( - , - ); - // Do click on span inside button with event listener instead of actual button to catch nested clicks. - component - .find('.ffe-file-upload__file-item-delete-button-text') - .simulate('click'); - expect(onFileDeleted.calledWith({ name: 'fileToDelete' })).toBe( - true, - ); - }); - }); -}); diff --git a/packages/ffe-file-upload-react/src/FileUpload.spec.tsx b/packages/ffe-file-upload-react/src/FileUpload.spec.tsx new file mode 100644 index 0000000000..61ae25f1c1 --- /dev/null +++ b/packages/ffe-file-upload-react/src/FileUpload.spec.tsx @@ -0,0 +1,65 @@ +import React from 'react'; +import { spy } from 'sinon'; +import { FileUpload, FileUploadProps } from './FileUpload'; +import { render, screen, fireEvent } from '@testing-library/react'; + +const renderFileUpload = (props?: Partial>) => + render( + {}} + onFileDeleted={() => {}} + onFilesDropped={() => {}} + {...props} + />, + ); + +describe('', () => { + it('should have a button and input', () => { + const { container } = renderFileUpload(); + expect(container.querySelector('#file-upload-button')).toBeTruthy(); + expect(container.querySelector('#file-upload')).toBeTruthy(); + }); + + it('should render input label', () => { + renderFileUpload(); + expect( + screen.getByRole('button', { name: 'label' }), + ).toBeInTheDocument(); + }); + + it('should extract and return files when user finishes selecting files', () => { + const onFilesSelected = spy(); + const { container } = renderFileUpload({ onFilesSelected }); + const input = container.querySelector('input#file-upload') as Element; + fireEvent.change(input); + expect(onFilesSelected.calledOnce).toBe(true); + }); + + it('should remove file from files when delete button is clicked', () => { + const onFileDeleted = spy(); + // Do click on span inside button with event listener instead of actual button to catch nested clicks. + const { container } = renderFileUpload({ + onFileDeleted, + files: { + fileToDelete: { + name: 'fileToDelete', + }, + }, + }); + + const deleteButton = container.querySelector( + '.ffe-file-upload__file-item-delete-button-text', + ) as Element; + fireEvent.click(deleteButton); + + expect(onFileDeleted.calledWith({ name: 'fileToDelete' })).toBe(true); + }); +}); diff --git a/packages/ffe-file-upload-react/src/FileUpload.tsx b/packages/ffe-file-upload-react/src/FileUpload.tsx new file mode 100644 index 0000000000..d5c495b0a3 --- /dev/null +++ b/packages/ffe-file-upload-react/src/FileUpload.tsx @@ -0,0 +1,175 @@ +import React, { useRef, useState } from 'react'; +import { FileItem, FileItemProps } from './FileItem'; +import classNames from 'classnames'; +import { SecondaryButton } from '@sb1/ffe-buttons-react'; +import { Icon } from '@sb1/ffe-icons-react'; + +export interface FileUploadProps { + /** ID for the input field. The ID is used as a base for the label ID as well. */ + id: string; + /** Label for the button to trigger native upload handling. */ + label: string; + /** + * A map of files, indexed by file name (check file-shape on FileItem.js propTypes), that the user has uploaded. + * Must be maintained outside of `FileUpload`. It is up to the implementation to deny or accept file types, sizes, etc, + * and it is important that duplicates are not allowed. + * */ + files: Record['file']>; + /** + * Will be called with `FileList`-object containing the `File`-objects the user selected. + * See MDN for documentation on + * [FileList](https://developer.mozilla.org/en-US/docs/Web/API/FileList) and + * [File](https://developer.mozilla.org/en-US/docs/Web/API/File). + */ + onFilesSelected(fileList: FileList | null): void; + /** Will be called when objects are dropped over the upload-section. */ + onFilesDropped(fileList: FileList | null): void; + /** + * Called when the user clicks the delete button for a given file. Is called with the `File` + * object of the file in question. + */ + onFileDeleted(file: FileItemProps['file']): void; + /** Whether or not uploading multiple files at once via the native file handler is allowed*/ + multiple?: boolean; + /** Title module */ + title: string; + /** Text on the info-section */ + infoText: string; + /** Subtext on the info-section */ + infoSubText?: string; + /** Label for the cancel button */ + cancelText?: string; + /** Label for the delete button */ + deleteText?: string; + /** Title on the upload-section */ + uploadTitle: string; + /** MicroText on the upload-section */ + uploadMicroText: string; + /** SubText on the upload-section */ + uploadSubText: string; + /** Unique file type specifier that describes a type of file that may be selected by the user, e.g. ".pdf" + * See MDN for documentation on + * [Unique file type specifiers](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input/file#unique_file_type_specifiers) + */ + accept?: string; +} + +export function FileUpload({ + id, + label, + files, + cancelText, + deleteText, + multiple, + title, + infoText, + infoSubText, + uploadTitle, + uploadMicroText, + uploadSubText, + accept, + onFilesDropped, + onFileDeleted, + onFilesSelected, +}: FileUploadProps) { + const [isHover, setIsHover] = useState(false); + const fileInputElement = useRef(null); + const downloadIcon = + 'data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIGhlaWdodD0iMjAiIHZpZXdCb3g9IjAgLTk2MCA5NjAgOTYwIiB3aWR0aD0iMjAiPjxwYXRoIGQ9Ik00NzkuOC0zNTcuNTM5cS02LjQzMSAwLTExLjk2MS0yLjMwOC01LjUzMS0yLjMwNy0xMC4xNDYtNi45MjNMMzM1LjMwOS00ODkuMTUzcS03LjkyMy03LjgzMi03LjgwNy0xOC4zMzguMTE1LTEwLjUwNyA4LjMyOS0xOC44MTUgOC43ODYtOC4zMDcgMTguODYyLTguMTE1IDEwLjA3Ny4xOTIgMTguMzg1IDguNWw4MC45MjMgODEuOTIzdi0zMjYuMDAxcTAtMTEuMDY5IDcuNDA0LTE4LjUzNCA3LjQwNS03LjQ2NiAxOC4zODQtNy40NjYgMTAuOTggMCAxOC41OTUgNy40NjYgNy42MTUgNy40NjUgNy42MTUgMTguNTM0djMyNi4wMDFsODEuOTIzLTgxLjkyM3E3LjU5LTcuOTIzIDE4LjAyNi03LjgwOCAxMC40MzUuMTE2IDE5LjIyMSA4LjQyMyA4LjIxNCA4LjMwOCA4LjAyMSAxOC41NzctLjE5MiAxMC4yNjktOC40OTkgMTguNTc2TDUwMi4zMDctMzY2Ljc3cS01LjAxNSA0LjYxNi0xMC41NDYgNi45MjMtNS41MyAyLjMwOC0xMS45NjEgMi4zMDhaTTI3Ni4wMjUtMjEyLjAwMXEtMjcuMDI0IDAtNDUuNTI0LTE4LjY1dC0xOC41LTQ1LjY1OHYtMzQuNDYxcTAtMTEuMDY5IDcuNDA1LTE4LjUzNCA3LjQwNS03LjQ2NSAxOC4zODQtNy40NjUgMTAuOTggMCAxOC41OTUgNy40NjVRMjY0LTMyMS44MzkgMjY0LTMxMC43N3YzNC40NjFxMCA0LjYxNiAzLjg0NiA4LjQ2MyAzLjg0NyAzLjg0NiA4LjQ2MyAzLjg0Nmg0MDcuMzgycTQuNjE2IDAgOC40NjMtMy44NDYgMy44NDYtMy44NDcgMy44NDYtOC40NjN2LTM0LjQ2MXEwLTExLjA2OSA3LjQwNS0xOC41MzQgNy40MDQtNy40NjUgMTguMzg0LTcuNDY1IDEwLjk3OSAwIDE4LjU5NCA3LjQ2NSA3LjYxNiA3LjQ2NSA3LjYxNiAxOC41MzR2MzQuNDYxcTAgMjcuMDA4LTE4LjY2MiA0NS42NTgtMTguNjYyIDE4LjY1LTQ1LjY4NiAxOC42NUgyNzYuMDI1WiIvPjwvc3ZnPg=='; + + const handleFilesDropped = (event: React.DragEvent) => { + event.preventDefault(); + setIsHover(false); + onFilesDropped(event.dataTransfer.files); + }; + + const handleFileDeleted = (event: React.MouseEvent) => { + onFileDeleted(files[event.currentTarget.id]); + }; + + const triggerUploadFileNativeHandler = () => { + // clear file input to trigger onChange when uploading same filename + if (fileInputElement.current) { + fileInputElement.current.value = ''; + fileInputElement.current.click(); + } + }; + + const handleFileSelected = (event: React.ChangeEvent) => { + onFilesSelected(event.target.files); + }; + + return ( +
+
{title}
+ {Object.keys(files).length > 0 ? ( +
+ {Object.keys(files).map(file => ( + + ))} +
+ ) : ( +
+
+ {infoText} +
+
+ {infoSubText} +
+
+ )} +
{ + event.preventDefault(); + setIsHover(true); + }} + onDragLeave={() => setIsHover(false)} + > +
+
+ {uploadTitle} +
+
+ {uploadMicroText} +
+ } + onClick={triggerUploadFileNativeHandler} + id={`${id}-button`} + > + {label} + +
+ {uploadSubText} +
+
+
+ +
+ ); +} diff --git a/packages/ffe-file-upload-react/src/file-content.js b/packages/ffe-file-upload-react/src/file-content.js deleted file mode 100644 index 1f9dabef5e..0000000000 --- a/packages/ffe-file-upload-react/src/file-content.js +++ /dev/null @@ -1,8 +0,0 @@ -export const getFileContent = file => { - return new Promise(function (resolve, reject) { - const reader = new window.FileReader(); - reader.onload = event => resolve(event.target.result); - reader.onerror = error => reject(error); - reader.readAsDataURL(file); - }); -}; diff --git a/packages/ffe-file-upload-react/src/getFileContent.ts b/packages/ffe-file-upload-react/src/getFileContent.ts new file mode 100644 index 0000000000..4ec3b9db9b --- /dev/null +++ b/packages/ffe-file-upload-react/src/getFileContent.ts @@ -0,0 +1,11 @@ +export const getFileContent = ( + file: File, +): Promise => { + return new Promise((resolve, reject) => { + const reader = new window.FileReader(); + reader.onload = event => + resolve(event.target ? event.target.result : null); + reader.onerror = error => reject(error); + reader.readAsDataURL(file); + }); +}; diff --git a/packages/ffe-file-upload-react/src/index.d.ts b/packages/ffe-file-upload-react/src/index.d.ts deleted file mode 100644 index de2a8b8497..0000000000 --- a/packages/ffe-file-upload-react/src/index.d.ts +++ /dev/null @@ -1,32 +0,0 @@ -import * as React from 'react'; - -export interface FileItem { - name: string; - document?: T; - error?: string; -} - -export interface FileUploadProps { - id: string; - label: string; - files: Record>; - onFilesSelected(fileList: FileList): void; - onFilesDropped(fileList: FileList): void; - onFileDeleted(file: FileItem): void; - multiple?: boolean; - title: string; - infoText: string; - infoSubText?: string; - cancelText?: string; - deleteText?: string; - uploadTitle: string; - uploadMicroText: string; - uploadSubText: string; - accept?: string; -} -declare class FileUpload extends React.Component, any> {} - -declare function getFileContent(file: File): Promise; - -export default FileUpload; -export { getFileContent }; diff --git a/packages/ffe-file-upload-react/src/index.js b/packages/ffe-file-upload-react/src/index.js deleted file mode 100644 index 2b618bc718..0000000000 --- a/packages/ffe-file-upload-react/src/index.js +++ /dev/null @@ -1,5 +0,0 @@ -import FileUpload from './FileUpload'; - -export { getFileContent } from './file-content'; - -export default FileUpload; diff --git a/packages/ffe-file-upload-react/src/index.ts b/packages/ffe-file-upload-react/src/index.ts new file mode 100644 index 0000000000..74a23f399a --- /dev/null +++ b/packages/ffe-file-upload-react/src/index.ts @@ -0,0 +1,2 @@ +export { FileUpload, FileUploadProps } from './FileUpload'; +export { getFileContent } from './getFileContent'; diff --git a/packages/ffe-file-upload-react/tsconfig.cjs.json b/packages/ffe-file-upload-react/tsconfig.cjs.json new file mode 100644 index 0000000000..6579fd2246 --- /dev/null +++ b/packages/ffe-file-upload-react/tsconfig.cjs.json @@ -0,0 +1,9 @@ +{ + "extends": "../../tsconfig.json", + "compilerOptions": { + "outDir": "./lib", + "module": "commonjs" + }, + "include": ["src/**/*"], + "exclude": ["node_modules", "src/**/*.spec.ts*"] +} diff --git a/packages/ffe-file-upload-react/tsconfig.esm.json b/packages/ffe-file-upload-react/tsconfig.esm.json new file mode 100644 index 0000000000..8e577796bf --- /dev/null +++ b/packages/ffe-file-upload-react/tsconfig.esm.json @@ -0,0 +1,9 @@ +{ + "extends": "../../tsconfig.json", + "compilerOptions": { + "outDir": "./es", + "module": "esnext" + }, + "include": ["src/**/*"], + "exclude": ["node_modules", "src/**/*.spec.ts*"] +} diff --git a/packages/ffe-file-upload-react/tsconfig.types.json b/packages/ffe-file-upload-react/tsconfig.types.json new file mode 100644 index 0000000000..3499c0be03 --- /dev/null +++ b/packages/ffe-file-upload-react/tsconfig.types.json @@ -0,0 +1,10 @@ +{ + "extends": "../../tsconfig.json", + "compilerOptions": { + "outDir": "./types", + "declaration": true, + "emitDeclarationOnly": true + }, + "include": ["src/**/*"], + "exclude": ["node_modules", "src/**/*.spec.ts*"] +}