From 7cdbccbdc603746b27bd6f3e446b97aa0128223e Mon Sep 17 00:00:00 2001 From: Emir Hasan Date: Tue, 29 Apr 2025 09:35:50 +0200 Subject: [PATCH 1/5] Implement FileUpload component --- package.json | 3 + src/extensions/index.ts | 1 + src/extensions/uppy/FileUpload.tsx | 122 +++++++++++++++++++ yarn.lock | 185 ++++++++++++++++++++++++++++- 4 files changed, 309 insertions(+), 2 deletions(-) create mode 100644 src/extensions/uppy/FileUpload.tsx diff --git a/package.json b/package.json index f18207b7b..79104becc 100644 --- a/package.json +++ b/package.json @@ -81,6 +81,9 @@ "@codemirror/lang-yaml": "^6.1.2", "@codemirror/legacy-modes": "^6.4.2", "@mavrin/remark-typograf": "^2.2.0", + "@uppy/core": "^2.1.4", + "@uppy/react": "^2.1.2", + "@uppy/xhr-upload": "^2.0.7", "classnames": "^2.5.1", "codemirror": "^6.0.1", "color": "^4.2.3", diff --git a/src/extensions/index.ts b/src/extensions/index.ts index ad93a8294..ce3d1f0bd 100644 --- a/src/extensions/index.ts +++ b/src/extensions/index.ts @@ -1,2 +1,3 @@ export * from "./codemirror/CodeMirror"; export * from "./react-flow"; +export * from "./uppy/FileUpload"; diff --git a/src/extensions/uppy/FileUpload.tsx b/src/extensions/uppy/FileUpload.tsx new file mode 100644 index 000000000..b53a7e2e4 --- /dev/null +++ b/src/extensions/uppy/FileUpload.tsx @@ -0,0 +1,122 @@ +import React, { FC, useEffect } from "react"; +import Uppy, { Locale, Restrictions } from "@uppy/core"; +import { DragDrop, ProgressBar, useUppy } from "@uppy/react"; +import XHRUpload, { XHRUploadOptions } from "@uppy/xhr-upload"; + +import "@uppy/core/dist/style.css"; +import "@uppy/drag-drop/dist/style.css"; +import "@uppy/progress-bar/dist/style.css"; + +export interface FileUploadProps { + /** + * upload instance id + */ + id?: string; + /** + * upload error callback function + */ + onError?: (responseText: string) => void; + /** + * upload success callback function + */ + onSuccess?: (responseText: string) => void; + /** + * upload response callback function + */ + handleResponseData?: (responseText: string) => void; + localeOptions?: Locale; + /** + * reset form after upload or in case of error/navigation steps + */ + resetForm?: boolean; + /** + * auto proceed bolean + */ + autoProceed?: boolean; + /** + * upload restrictions + */ + restrictions?: Restrictions; + /** + * additional upload files + */ + additionalFiles?: { + id: string; + name: string; + size: number; + data: Blob; + }[]; + /** + * xhr upload options + */ + xhrUploadOptions: XHRUploadOptions; +} + +export const FileUpload: FC = ({ + id, + onError, + onSuccess, + handleResponseData, + resetForm, + autoProceed = false, + restrictions, + additionalFiles, + xhrUploadOptions, + localeOptions, +}) => { + const uppy = useUppy(() => { + return new Uppy({ + id, + autoProceed, + restrictions, + locale: localeOptions, + }) + .on("upload-success", (_, response) => { + onSuccess?.(response.body); + }) + .use(XHRUpload, { + ...xhrUploadOptions, + getResponseData: (responseText) => { + handleResponseData?.(responseText); + + return responseText; + }, + getResponseError: (responseText) => { + uppy.reset(); + + onError?.(responseText); + return new Error(responseText); + }, + }); + }); + + useEffect(() => { + if (resetForm) { + uppy.reset(); + } + + return () => { + uppy.close(); + }; + }, [resetForm, uppy]); + + useEffect(() => { + if (additionalFiles) { + additionalFiles.forEach((file) => { + uppy.addFile({ + name: file.name, + data: file.data, + size: file.size, + id: file.id, + }); + }); + } + }, [additionalFiles, uppy]); + + return ( + <> + + + + ); +}; diff --git a/yarn.lock b/yarn.lock index a4101cf79..0d3265e2b 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3906,6 +3906,11 @@ resolved "https://registry.yarnpkg.com/@topoconfig/extends/-/extends-0.16.2.tgz#0741dbe5198a28f306a116498f7ded1089d0fadc" integrity sha512-sTF+qpWakr5jf1Hn/kkFSi833xPW15s/loMAiKSYSSVv4vDonxf6hwCGzMXjLq+7HZoaK6BgaV72wXr1eY7FcQ== +"@transloadit/prettier-bytes@0.0.7": + version "0.0.7" + resolved "https://registry.yarnpkg.com/@transloadit/prettier-bytes/-/prettier-bytes-0.0.7.tgz#cdb5399f445fdd606ed833872fa0cabdbc51686b" + integrity sha512-VeJbUb0wEKbcwaSlj5n+LscBl9IPgLPkHVGBkh00cztv6X4L/TJXK58LzFuBKX7/GAfiGhIwH67YTLTlzvIzBA== + "@tsconfig/node10@^1.0.7": version "1.0.9" resolved "https://registry.yarnpkg.com/@tsconfig/node10/-/node10-1.0.9.tgz#df4907fc07a886922637b15e02d4cebc4c0021b2" @@ -4608,6 +4613,140 @@ "@typescript-eslint/types" "8.18.1" eslint-visitor-keys "^4.2.0" +"@uppy/companion-client@^2.2.2": + version "2.2.2" + resolved "https://registry.yarnpkg.com/@uppy/companion-client/-/companion-client-2.2.2.tgz#c70b42fdcca728ef88b3eebf7ee3e2fa04b4923b" + integrity sha512-5mTp2iq97/mYSisMaBtFRry6PTgZA6SIL7LePteOV5x0/DxKfrZW3DEiQERJmYpHzy7k8johpm2gHnEKto56Og== + dependencies: + "@uppy/utils" "^4.1.2" + namespace-emitter "^2.0.1" + +"@uppy/core@^2.1.4": + version "2.3.4" + resolved "https://registry.yarnpkg.com/@uppy/core/-/core-2.3.4.tgz#260b85b6bf3aa03cdc67da231f8c69cfbfdcc84a" + integrity sha512-iWAqppC8FD8mMVqewavCz+TNaet6HPXitmGXpGGREGrakZ4FeuWytVdrelydzTdXx6vVKkOmI2FLztGg73sENQ== + dependencies: + "@transloadit/prettier-bytes" "0.0.7" + "@uppy/store-default" "^2.1.1" + "@uppy/utils" "^4.1.3" + lodash.throttle "^4.1.1" + mime-match "^1.0.2" + namespace-emitter "^2.0.1" + nanoid "^3.1.25" + preact "^10.5.13" + +"@uppy/dashboard@^2.4.2": + version "2.4.3" + resolved "https://registry.yarnpkg.com/@uppy/dashboard/-/dashboard-2.4.3.tgz#0443a1b81717ccaa554fdc338e00dce5266d69b8" + integrity sha512-OPpvosiRaZXN873mraDmiM8T8c+2rIl86Ho7lQPsq+aQfjLUiPML+Y2rjmwDPE6eo7EiBszV5dQkO6vPjGO8/g== + dependencies: + "@transloadit/prettier-bytes" "0.0.7" + "@uppy/informer" "^2.1.1" + "@uppy/provider-views" "^2.1.3" + "@uppy/status-bar" "^2.2.2" + "@uppy/thumbnail-generator" "^2.2.2" + "@uppy/utils" "^4.1.3" + classnames "^2.2.6" + is-shallow-equal "^1.0.1" + lodash.debounce "^4.0.8" + memoize-one "^5.0.4" + nanoid "^3.1.25" + preact "^10.5.13" + +"@uppy/drag-drop@^2.1.2": + version "2.1.2" + resolved "https://registry.yarnpkg.com/@uppy/drag-drop/-/drag-drop-2.1.2.tgz#99756fbab07b43c7acc65b924c1ec0200fd73ec3" + integrity sha512-J6hBiYcBc8p6U9PylqtZ+eMJ48yT1qP1Xzon2Pou5AQxQ4D7UAL97OvcjnONpOfp8P7uGmaqXFUubBNgEUCfQg== + dependencies: + "@uppy/utils" "^4.1.2" + preact "^10.5.13" + +"@uppy/file-input@^2.1.2": + version "2.1.2" + resolved "https://registry.yarnpkg.com/@uppy/file-input/-/file-input-2.1.2.tgz#c71cd7c6c97764d46921bc4307ac8e40ca41857f" + integrity sha512-tdn6HNMnLOC2xpdZYbdXNSjTS9EpLvY97vOfq9SZWkoX/cmZiOf6JfFc3Qm8pS3RRnVmwsdi5usEPbzMQ5RAEg== + dependencies: + "@uppy/utils" "^4.1.2" + preact "^10.5.13" + +"@uppy/informer@^2.1.1": + version "2.1.1" + resolved "https://registry.yarnpkg.com/@uppy/informer/-/informer-2.1.1.tgz#862a05f4e69e98519da228a6d777ca63013d2b7b" + integrity sha512-aSdtJO0QvDGzcWHQ1Kd1hOFLyn+0e8LY82708WGkt8BwYwjmKhCJUuxdPDsCu3I2wpFUSUzpvQ9pik7AajBFjw== + dependencies: + "@uppy/utils" "^4.1.2" + preact "^10.5.13" + +"@uppy/progress-bar@^2.1.2": + version "2.1.2" + resolved "https://registry.yarnpkg.com/@uppy/progress-bar/-/progress-bar-2.1.2.tgz#43d6ac0dae2eab8b58a92d5251d56268ddddbed5" + integrity sha512-BzO+LSMDj+daT93yoUhNdkQ1Bq79lSm+hTUcuFpUt397B0ETzUeHUg3wUj39Zu3r7BlO/JmQLbH4NkejK4rYGg== + dependencies: + "@uppy/utils" "^4.1.2" + preact "^10.5.13" + +"@uppy/provider-views@^2.1.3": + version "2.1.3" + resolved "https://registry.yarnpkg.com/@uppy/provider-views/-/provider-views-2.1.3.tgz#dac05163064cd57130b58c202bc4605651ec4e2b" + integrity sha512-IXk8j+0nXxsTLV1KwUJbholiwMYXJ9H2r7pJlBRiu/lB/hgd5t7ENqt2susnepBFQJ+XlaIsuM5YVLgppBwc5w== + dependencies: + "@uppy/utils" "^4.1.2" + classnames "^2.2.6" + preact "^10.5.13" + +"@uppy/react@^2.1.2": + version "2.2.3" + resolved "https://registry.yarnpkg.com/@uppy/react/-/react-2.2.3.tgz#0ea2d6f775b2101911613182aa8176661c822dd9" + integrity sha512-Zr8KRHATAPeYGI10Xty+KS4rSh3mvoE5l++9Ondo0Qu7TbFPIrmLlq52d9yMI1dV4hd98kshv6kRa394Ex4UbQ== + dependencies: + "@uppy/dashboard" "^2.4.2" + "@uppy/drag-drop" "^2.1.2" + "@uppy/file-input" "^2.1.2" + "@uppy/progress-bar" "^2.1.2" + "@uppy/status-bar" "^2.2.2" + "@uppy/utils" "^4.1.2" + prop-types "^15.6.1" + +"@uppy/status-bar@^2.2.2": + version "2.2.2" + resolved "https://registry.yarnpkg.com/@uppy/status-bar/-/status-bar-2.2.2.tgz#a8248ba59273da2044ffaa2d1c57ec284459a462" + integrity sha512-XV4/3RyNF42enqPc4wWZupqI1KuGtfdt49waux7kebxaGqNzV+T72o/C+QDDqY/h4mKadrp6p98/BnMefC5QtQ== + dependencies: + "@transloadit/prettier-bytes" "0.0.7" + "@uppy/utils" "^4.1.2" + classnames "^2.2.6" + lodash.throttle "^4.1.1" + preact "^10.5.13" + +"@uppy/store-default@^2.1.1": + version "2.1.1" + resolved "https://registry.yarnpkg.com/@uppy/store-default/-/store-default-2.1.1.tgz#62a656a099bdaa012306e054d093754cb2d36e3e" + integrity sha512-xnpTxvot2SeAwGwbvmJ899ASk5tYXhmZzD/aCFsXePh/v8rNvR2pKlcQUH7cF/y4baUGq3FHO/daKCok/mpKqQ== + +"@uppy/thumbnail-generator@^2.2.2": + version "2.2.2" + resolved "https://registry.yarnpkg.com/@uppy/thumbnail-generator/-/thumbnail-generator-2.2.2.tgz#493904b7d80cf15a372c55e49da9621f7cdbe0ae" + integrity sha512-5VwwzzvKRqXJNz28U/VwXu9K9dHY5vXQvzljxqkeCJrKIMgu/8vzKEFndAPY6sJZkUcF0jtAb3gUU2q5TGRlJg== + dependencies: + "@uppy/utils" "^4.1.3" + exifr "^7.0.0" + +"@uppy/utils@^4.1.2", "@uppy/utils@^4.1.3": + version "4.1.3" + resolved "https://registry.yarnpkg.com/@uppy/utils/-/utils-4.1.3.tgz#9d0be6ece4df25f228d30ef40be0f14208258ce3" + integrity sha512-nTuMvwWYobnJcytDO3t+D6IkVq/Qs4Xv3vyoEZ+Iaf8gegZP+rEyoaFT2CK5XLRMienPyqRqNbIfRuFaOWSIFw== + dependencies: + lodash.throttle "^4.1.1" + +"@uppy/xhr-upload@^2.0.7": + version "2.1.3" + resolved "https://registry.yarnpkg.com/@uppy/xhr-upload/-/xhr-upload-2.1.3.tgz#0d4e355332fe0c6eb372d7731315e04d02aeeb18" + integrity sha512-YWOQ6myBVPs+mhNjfdWsQyMRWUlrDLMoaG7nvf/G6Y3GKZf8AyjFDjvvJ49XWQ+DaZOftGkHmF1uh/DBeGivJQ== + dependencies: + "@uppy/companion-client" "^2.2.2" + "@uppy/utils" "^4.1.2" + nanoid "^3.1.25" + "@vitest/expect@2.0.5": version "2.0.5" resolved "https://registry.yarnpkg.com/@vitest/expect/-/expect-2.0.5.tgz#f3745a6a2c18acbea4d39f5935e913f40d26fa86" @@ -5663,7 +5802,7 @@ classcat@^5.0.3: resolved "https://registry.yarnpkg.com/classcat/-/classcat-5.0.3.tgz#38eaa0ec6eb1b10faf101bbcef2afb319c23c17b" integrity sha512-6dK2ke4VEJZOFx2ZfdDAl5OhEL8lvkl6EHF92IfRePfHxQTqir5NlcNVUv+2idjDqCX2NDc8m8YSAI5NI975ZQ== -classnames@2.5.1, classnames@^2.5.1: +classnames@2.5.1, classnames@^2.2.6, classnames@^2.5.1: version "2.5.1" resolved "https://registry.yarnpkg.com/classnames/-/classnames-2.5.1.tgz#ba774c614be0f016da105c858e7159eae8e7687b" integrity sha512-saHYOzhIQs6wy2sVxTM6bUDsQO4F50V9RQ22qBpEdCW+I+/Wmke2HOl6lS6dTpdxVhb88/I6+Hs+438c3lfUow== @@ -7155,6 +7294,11 @@ exenv@^1.2.2: resolved "https://registry.yarnpkg.com/exenv/-/exenv-1.2.2.tgz#2ae78e85d9894158670b03d47bec1f03bd91bb9d" integrity sha512-Z+ktTxTwv9ILfgKCk32OX3n/doe+OcLTRtqK9pcL+JsP3J1/VW8Uvl4ZjLlKqeW4rzK4oesDOGMEMRIZqtP4Iw== +exifr@^7.0.0: + version "7.1.3" + resolved "https://registry.yarnpkg.com/exifr/-/exifr-7.1.3.tgz#f6218012c36dbb7d843222011b27f065fddbab6f" + integrity sha512-g/aje2noHivrRSLbAUtBPWFbxKdKhgj/xr1vATDdUXPOFYJlQ62Ft0oy+72V6XLIpDJfHs6gXLbBLAolqOXYRw== + exit@0.1.2, exit@0.1.x, exit@^0.1.2: version "0.1.2" resolved "https://registry.yarnpkg.com/exit/-/exit-0.1.2.tgz#0632638f8d877cc82107d30a0fff1a17cba1cd0c" @@ -8547,6 +8691,11 @@ is-set@^2.0.3: resolved "https://registry.yarnpkg.com/is-set/-/is-set-2.0.3.tgz#8ab209ea424608141372ded6e0cb200ef1d9d01d" integrity sha512-iPAjerrse27/ygGLxw+EBR9agv9Y6uLeYVJMu+QNCoouJ1/1ri0mGrcWpfCqFZuzzx3WjtwxG098X+n4OuRkPg== +is-shallow-equal@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/is-shallow-equal/-/is-shallow-equal-1.0.1.tgz#c410b51eb1c12ee50cd02891d32d1691a132d73c" + integrity sha512-lq5RvK+85Hs5J3p4oA4256M1FEffzmI533ikeDHvJd42nouRRx5wBzt36JuviiGe5dIPyHON/d0/Up+PBo6XkQ== + is-shared-array-buffer@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/is-shared-array-buffer/-/is-shared-array-buffer-1.0.2.tgz#8f259c573b60b6a32d4058a1a07430c0a7344c79" @@ -9804,6 +9953,11 @@ memfs@^3.4.1, memfs@^3.4.12: dependencies: fs-monkey "^1.0.4" +memoize-one@^5.0.4: + version "5.2.1" + resolved "https://registry.yarnpkg.com/memoize-one/-/memoize-one-5.2.1.tgz#8337aa3c4335581839ec01c3d594090cebe8f00e" + integrity sha512-zYiwtZUcYyXKo/np96AGZAckk+FWWsUdJ3cHGGmld7+AhvcWmQyGCYUh1hc4Q/pkOhb65dQR/pqCyK0cOaHz4Q== + memoizerific@^1.11.3: version "1.11.3" resolved "https://registry.yarnpkg.com/memoizerific/-/memoizerific-1.11.3.tgz#7c87a4646444c32d75438570905f2dbd1b1a805a" @@ -10139,6 +10293,13 @@ mime-db@1.52.0: resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.52.0.tgz#bbabcdc02859f4987301c856e3387ce5ec43bf70" integrity sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg== +mime-match@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/mime-match/-/mime-match-1.0.2.tgz#3f87c31e9af1a5fd485fb9db134428b23bbb7ba8" + integrity sha512-VXp/ugGDVh3eCLOBCiHZMYWQaTNUHv2IJrut+yXA6+JbLPXHglHwfS/5A5L0ll+jkCY7fIzRJcH6OIunF+c6Cg== + dependencies: + wildcard "^1.1.0" + mime-types@^2.1.12, mime-types@^2.1.27, mime-types@^2.1.31: version "2.1.35" resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.35.tgz#381a871b62a734450660ae3deee44813f70d959a" @@ -10267,6 +10428,16 @@ n3@^1.23.1: queue-microtask "^1.1.2" readable-stream "^4.0.0" +namespace-emitter@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/namespace-emitter/-/namespace-emitter-2.0.1.tgz#978d51361c61313b4e6b8cf6f3853d08dfa2b17c" + integrity sha512-N/sMKHniSDJBjfrkbS/tpkPj4RAbvW3mr8UAzvlMHyun93XEm83IAvhWtJVHo+RHn/oO8Job5YN4b+wRjSVp5g== + +nanoid@^3.1.25: + version "3.3.11" + resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.11.tgz#4f4f112cefbe303202f2199838128936266d185b" + integrity sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w== + nanoid@^3.3.6, nanoid@^3.3.7: version "3.3.7" resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.7.tgz#d0c301a691bc8d54efa0a2226ccf3fe2fd656bd8" @@ -11009,6 +11180,11 @@ postcss@^8.4.32, postcss@^8.4.33: picocolors "^1.0.0" source-map-js "^1.0.2" +preact@^10.5.13: + version "10.26.5" + resolved "https://registry.yarnpkg.com/preact/-/preact-10.26.5.tgz#7e1e998af178f139e4c7cb53f441bf2179f44ad2" + integrity sha512-fmpDkgfGU6JYux9teDWLhj9mKN55tyepwYbxHgQuIxbWQzgFg5vk7Mrrtfx7xRxq798ynkY4DDDxZr235Kk+4w== + prelude-ls@^1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.2.1.tgz#debc6489d7a6e6b0e7611888cec880337d316396" @@ -11085,7 +11261,7 @@ prompts@^2.0.1, prompts@^2.4.0: kleur "^3.0.3" sisteransi "^1.0.5" -prop-types@^15.0.0, prop-types@^15.6.2, prop-types@^15.7.2, prop-types@^15.8.1: +prop-types@^15.0.0, prop-types@^15.6.1, prop-types@^15.6.2, prop-types@^15.7.2, prop-types@^15.8.1: version "15.8.1" resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.8.1.tgz#67d87bf1a694f48435cf332c24af10214a3140b5" integrity sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg== @@ -13711,6 +13887,11 @@ wicg-inert@^3.1.3: resolved "https://registry.yarnpkg.com/wicg-inert/-/wicg-inert-3.1.3.tgz#e53dbc9ac1e0d7f8c60f25e707614a835986272a" integrity sha512-5L0PKK7iP+0Q/jv2ccgmkz/pfXbumZtlEyWS/xnX+L+Og3f7WjL4+iEs18k4IuldOX3PgGpza3qGndL9xUBjCQ== +wildcard@^1.1.0: + version "1.1.2" + resolved "https://registry.yarnpkg.com/wildcard/-/wildcard-1.1.2.tgz#a7020453084d8cd2efe70ba9d3696263de1710a5" + integrity sha512-DXukZJxpHA8LuotRwL0pP1+rS6CS7FF2qStDDE1C7DDg2rLud2PXRMuEDYIPhgEezwnlHNL4c+N6MfMTjCGTng== + window-or-global@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/window-or-global/-/window-or-global-1.0.1.tgz#dbe45ba2a291aabc56d62cf66c45b7fa322946de" From 5887f53fe3e7797ec92c563c5a43790869ce41c8 Mon Sep 17 00:00:00 2001 From: Emir Hasan Date: Tue, 29 Apr 2025 15:53:32 +0200 Subject: [PATCH 2/5] Add stories --- src/extensions/uppy/FileUpload.stories.tsx | 33 ++++++++++++++++++++++ src/extensions/uppy/FileUpload.tsx | 3 ++ 2 files changed, 36 insertions(+) create mode 100644 src/extensions/uppy/FileUpload.stories.tsx diff --git a/src/extensions/uppy/FileUpload.stories.tsx b/src/extensions/uppy/FileUpload.stories.tsx new file mode 100644 index 000000000..81e028094 --- /dev/null +++ b/src/extensions/uppy/FileUpload.stories.tsx @@ -0,0 +1,33 @@ +import React from "react"; +import { Meta, StoryFn } from "@storybook/react"; + +import { FileUpload } from "./FileUpload"; + +export default { + title: "Extensions/FileUpload", + component: FileUpload, +} as Meta; + +const TemplateFull: StoryFn = (args) => ; + +export const BasicExample = TemplateFull.bind({}); +BasicExample.args = { + id: "fileupload", + onError: null, + onSuccess: null, + handleResponseData: null, + localeOptions: { + strings: { + dropHereOr: "Drop here or %{browse}", + browse: "browse", + }, + }, + resetForm: true, + autoProceed: true, + restrictions: { + maxFileSize: 1000000, + minNumberOfFiles: 1, + maxNumberOfFiles: 5, + allowedFileTypes: [".jpg", ".png"], + }, +}; diff --git a/src/extensions/uppy/FileUpload.tsx b/src/extensions/uppy/FileUpload.tsx index b53a7e2e4..78c1924d8 100644 --- a/src/extensions/uppy/FileUpload.tsx +++ b/src/extensions/uppy/FileUpload.tsx @@ -24,6 +24,9 @@ export interface FileUploadProps { * upload response callback function */ handleResponseData?: (responseText: string) => void; + /** + * locale options, like button labels etc. + */ localeOptions?: Locale; /** * reset form after upload or in case of error/navigation steps From 3778e143f4e9a72e8f618ee94457d1a29e310df2 Mon Sep 17 00:00:00 2001 From: Emir Hasan Date: Tue, 29 Apr 2025 16:04:35 +0200 Subject: [PATCH 3/5] Add support for testid --- src/extensions/uppy/FileUpload.tsx | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/extensions/uppy/FileUpload.tsx b/src/extensions/uppy/FileUpload.tsx index 78c1924d8..cf903fe1e 100644 --- a/src/extensions/uppy/FileUpload.tsx +++ b/src/extensions/uppy/FileUpload.tsx @@ -3,11 +3,13 @@ import Uppy, { Locale, Restrictions } from "@uppy/core"; import { DragDrop, ProgressBar, useUppy } from "@uppy/react"; import XHRUpload, { XHRUploadOptions } from "@uppy/xhr-upload"; +import { TestableComponent } from "../../components/interfaces"; + import "@uppy/core/dist/style.css"; import "@uppy/drag-drop/dist/style.css"; import "@uppy/progress-bar/dist/style.css"; -export interface FileUploadProps { +export interface FileUploadProps extends TestableComponent { /** * upload instance id */ @@ -66,6 +68,7 @@ export const FileUpload: FC = ({ additionalFiles, xhrUploadOptions, localeOptions, + ...rest }) => { const uppy = useUppy(() => { return new Uppy({ @@ -117,9 +120,9 @@ export const FileUpload: FC = ({ }, [additionalFiles, uppy]); return ( - <> +
- +
); }; From e2c61e19d07c5073bb2bacfd522dc30d03868279 Mon Sep 17 00:00:00 2001 From: Emir Hasan Date: Tue, 29 Apr 2025 16:11:24 +0200 Subject: [PATCH 4/5] Update changelog --- CHANGELOG.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1b0bb9331..c8356631b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,11 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/) and this p ## [Unreleased] +### Added + +- `` + - uploads files using `Uppy` library + ## [24.1.0] - 2025-04-16 ### Added From 4ede519a6a4a001418d9660fddfc557e32527ceb Mon Sep 17 00:00:00 2001 From: darausi Date: Wed, 4 Jun 2025 11:55:19 +0100 Subject: [PATCH 5/5] added more props to adapt to DI requirements --- src/extensions/index.ts | 1 + src/extensions/uppy/FileUpload.tsx | 55 ++++++++++++++++++++++++++---- 2 files changed, 49 insertions(+), 7 deletions(-) diff --git a/src/extensions/index.ts b/src/extensions/index.ts index ce3d1f0bd..a3503f469 100644 --- a/src/extensions/index.ts +++ b/src/extensions/index.ts @@ -1,3 +1,4 @@ export * from "./codemirror/CodeMirror"; export * from "./react-flow"; export * from "./uppy/FileUpload"; +export * from "@uppy/core"; diff --git a/src/extensions/uppy/FileUpload.tsx b/src/extensions/uppy/FileUpload.tsx index cf903fe1e..b1c522c54 100644 --- a/src/extensions/uppy/FileUpload.tsx +++ b/src/extensions/uppy/FileUpload.tsx @@ -1,5 +1,5 @@ -import React, { FC, useEffect } from "react"; -import Uppy, { Locale, Restrictions } from "@uppy/core"; +import React from "react"; +import Uppy, { Locale, Restrictions, UppyEventMap, UppyFile } from "@uppy/core"; import { DragDrop, ProgressBar, useUppy } from "@uppy/react"; import XHRUpload, { XHRUploadOptions } from "@uppy/xhr-upload"; @@ -9,6 +9,8 @@ import "@uppy/core/dist/style.css"; import "@uppy/drag-drop/dist/style.css"; import "@uppy/progress-bar/dist/style.css"; +type eventNames = keyof UppyEventMap; + export interface FileUploadProps extends TestableComponent { /** * upload instance id @@ -55,9 +57,19 @@ export interface FileUploadProps extends TestableComponent { * xhr upload options */ xhrUploadOptions: XHRUploadOptions; + /** + * uppy events to register and unregister to + */ + events?: { [key in eventNames]?: any }; + /** + * set uppy instance + */ + setInstance?: (instance: Uppy) => void; } -export const FileUpload: FC = ({ +export { ProgressBar as UppyProgressBar, DragDrop } from "@uppy/react"; + +export const FileUpload: React.FC = ({ id, onError, onSuccess, @@ -68,6 +80,9 @@ export const FileUpload: FC = ({ additionalFiles, xhrUploadOptions, localeOptions, + events, + setInstance, + children, ...rest }) => { const uppy = useUppy(() => { @@ -96,7 +111,25 @@ export const FileUpload: FC = ({ }); }); - useEffect(() => { + React.useEffect(() => { + uppy && setInstance && setInstance(uppy); + const eventEntries = Object.entries(events ?? {}) as [keyof UppyEventMap, (file: UppyFile) => Promise][]; + + const unregisterEvents = () => { + eventEntries.length && eventEntries.forEach(([event, handler]) => uppy.off(event, handler)); + }; + + unregisterEvents(); + + eventEntries.length && + eventEntries.forEach(([event, handler]) => { + uppy.on(event, handler); + }); + + return () => unregisterEvents(); + }, [uppy, events]); + + React.useEffect(() => { if (resetForm) { uppy.reset(); } @@ -106,7 +139,7 @@ export const FileUpload: FC = ({ }; }, [resetForm, uppy]); - useEffect(() => { + React.useEffect(() => { if (additionalFiles) { additionalFiles.forEach((file) => { uppy.addFile({ @@ -119,10 +152,18 @@ export const FileUpload: FC = ({ } }, [additionalFiles, uppy]); + if (!uppy) return null; + return (
- - + {children ? ( + children + ) : ( + <> + + + + )}
); };